Tag Archives: PHP

PHP curl_multi_init Example

One of the extensions I’ve used a lot in PHP is cURL, as it’s a great way to fetch remote documents. Previously I have showed that cURL is much faster than file_get_contents.While curl_init and curl_exec works well and is faster than file_get_contents, it can be quite slow when the need to fetch multiple files arises. For situations where multiple files need to be fetched, curl_multi_init and curl_multi_exec will work better in that it can fetch multiple files simultaneously.

The curl_multi_exec is a very powerful function, but the PHP documentations make it seem like quite a complicated one. Here is a basic demonstration where Google, Yahoo, and Bing are all fetched:

$urls = array('http://www.google.com/', 'http://www.yahoo.com/', 'http://www.bing.com/');
$url_count = count($urls);

$curl_array = array();
$ch = curl_multi_init();

foreach($urls as $count => $url) {
	$curl_array[$count] = curl_init($url);
	curl_setopt($curl_array[$count], CURLOPT_RETURNTRANSFER, 1);
	curl_multi_add_handle($ch, $curl_array[$count]);
}

do {
	curl_multi_exec($ch, $exec);
} while($exec > 0);

In this example, the 3 URLs are all set and fetched at the same time. Even though we are not reading the contents of those three files, we are setting CURLOPT_RETURNTRANSFER to prevent the content of the 3 files from being automatically outputted.

curl_multi_getcontent

In certain cases, we will want to read the content of the 3 files. To read the content of the files, we will use the curl_multi_getcontent function. The example below demonstrates how this can be done (the code below should be appended to the previous example as they work together):

foreach($urls as $count => $url) {
	$returned = curl_multi_getcontent($curl_array[$count]);
	echo "$url - $returned";
}

Closing the cURL Handles

Some PHP coders prefer to execute curl_close after it is used. You should only use curl_close, curl_multi_close, and curl_multi_remove_handle after you have retrieved the content (in the case if you need it). It is demonstrated in the example below:

foreach($urls as $count => $url) {
	curl_multi_remove_handle($ch, $curl_array[$count]);
}

curl_multi_close($ch); 

foreach($urls as $count => $url) {
	curl_close($curl_array[$count]);
}

Randomness of MySQL Rand

A few days ago, I needed to use MySQL’s rand() function. Some rows seemed to be picked more often than others, so I decided to test the randomness of the function. I tested this function in PHP using the MySQLi module.

$db = new mysqli('host', 'user', 'password', 'database');

To begin with, I inserted 100 rows, with numbers 1 to 100, using the following script:

for($i = 1; $i <= 100; $i++) {
     $query = $db->query("INSERT INTO numbers ( number ) VALUES ( $i );");
}

I used the following PHP snippet to test and record the randomness. Each round was ran 1000 times, and there were 10 rounds.

for($a = 0; $a < 10; $a++) {
    for($b = 0; $b < 1000; $b++) {         $query = $db->query("SELECT number FROM numbers ORDER BY RAND() LIMIT 1");
        $result = $query->fetch_assoc();
        $results[$a][$result['number']]++;
    }
    ksort($results[$a]);
}

Results
The easy way would be to use print_r to output the results. However, I wanted the final results in CSV format, so I could graph it in Excel.

for($a = 1; $a <= 100; $a++) {
    $str .= $a;
    for($b = 0; $b < 10; $b++) {
        $str .= ',' . $results[$b][$a];
    }
    $str .= "n";
}
echo $str;

Average

MySQL Rand Average

Although the difference is minor, there is actually a large difference since the rand() function was ran a total of 10,000 times. Since this graph shows the average number of times each number was picked among the 10 trials, the difference between 8 and 12 is 40 in reality. Here’s a graph showing the total number of times each number was picked out of 10,000.

Total Number Picked

Even though the above graphs doesn’t show any “dramatic” difference, one interesting thing to look at is the actual results for each round. Here are the results for the last 3 rounds.

Last 3 Rounds

As you can see, among the individual rounds, there are dramatic difference between the numbers. I’m hoping to find an alternative to MySQL’s rand function (perhaps use PHP’s rand function instead?). If you have any good alternatives, let me know!

PHP – BC Math Review

Recently, I have been really involved with Project Euler, and frequently encountered many large numbers that PHP was unable to deal with using it’s core functions. However, PHP has an extension called BC math, which can process numbers of any size. To add using BC math, you would use:

$sum = bcadd($num1, $num2);

You can subtract, multiply, divide, and etc, using bcsub, bcmul, bcdiv, respectively. However, there are many drawbacks to using BC Math.

After doing several benchmarks, it seems as if BC math was 20 times slower than PHP’s core math functions. Here are the benchmark scripts:

Core Math Functions

<?php
$t = microtime(1);
$i = 0;
while($i < 1000000) {
	$i++;
}
echo microtime(1) - $t;
?>

BC Math

<?php
$t = microtime(1);
$i = 0;
while($i < 1000000) {
	$i = bcadd($i, 1);
}
echo microtime(1) - $t;
?>

Summary
It seems interesting how BC math is so many times slower than the regular math functions. Considering these benchmark results, it’s much better to use PHP’s core math functions than to use BC math, unless dealing with numbers too big to be dealt with by the normal math functions.