Comparing communication speed between different machines in PHP
For a project we needed some sort of inter-server communication. Due to performance critical tasks like Click Tracking we decided that we need to investigate first the most reliable and fastest way to communicate.
1. Using Sockets
I created a Test Socket Server using more or less the demo script under http://de.php.net/sockets . This Server just takes what he receives and send it back. What is not implemented is multi threading and optimization - but it should be enough to get some reasonable results.
The Test Server looks like this…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | do { if (FALSE === ($buf = socket_read ($msgsock, 2048))) { echo "socket_read() fehlgeschlagen: Grund: "; echo socket_strerror ($ret) . "n"; break 2; } if (!$buf = trim ($buf)) { continue; } if ($buf == 'quit') { break; } if ($buf == 'shutdown') { socket_close ($msgsock); break 2; } $buf .= "n"; socket_write ($msgsock, $buf, strlen ($buf)); } while (true); socket_close ($msgsock); } while (true); |
Now we need to create some client. In our case we keep the connection open so we could avoid opening and closing sockets. The client for testing looks like this:
1 2 3 4 5 | $sh = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (! socket_connect( $sh, '192.168.20.33', 10000) ) die( 'Could not bind to Socket!'.PHP_EOL); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | $dStart = microtime( true); for( $iIdx = 0; $iIdx < $iMaxCyles; $iIdx++) { $aClient[$iIdx] = $iIdx; $aData = array( 'iIdx' => $iIdx ); // call $aRes = Comm_Socket( $sh, $aData); $sResult = $aRes['iIdx']; $aServer[$iIdx] = $sResult; } $dDuration = microtime( true) - $dStart; echo( $iMaxCyles." calls total: $dDuration sec. ".PHP_EOL); echo( "Average: ".$dDuration/$iMaxCyles." sec. per call ".PHP_EOL.PHP_EOL); $aLost = array_diff( $aClient, $aServer); if( count( $aLost)) { echo( "lost call/differences:".PHP_EOL); print_r( array_diff( $aClient, $aServer)); } |
where as function Comm_Socket looks quite simple:
1 2 3 4 5 6 7 8 9 10 11 | function Comm_Socket( $Socket, $mPostData) { $sMessage = serialize( $mPostData); socket_write( $Socket, $sMessage, strlen( $sMessage)); $sRet = socket_read( $Socket,512,PHP_NORMAL_READ); return unserialize( $sRet); } |
The results look like this:
1000 calls total: 0.473767995834 sec.
Average: 0.000473767995834 sec. per call
2. Using http via file_get_contents
Now let’s modify our testscript a bit and change our server so, that he takes any POST parameter and echo’s it.
This is easy to do - and our Client Function looks now like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | function Comm_File_Get_Contents( $sUri, $mPostData) { $fTimeout = 20; $sHttpPostQuery = http_build_query ( $mPostData ); $aStreamContextOpts = array( 'http'=>array( 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $sHttpPostQuery ) ); $oContext = stream_context_create ( $aStreamContextOpts ); // inject a request read timeout $aAddOpts = array( 'http' => array('timeout' => (float) $fTimeout ) ); stream_context_set_option( $oContext, $aAddOpts ); $sResponse = file_get_contents ( urldecode($sUri), false, $oContext ); return $sResponse; } |
Ok the results are quite interesting:
1000 calls total: 4.02230811119 sec.
Average: 0.00402230811119 sec. per call
Nearly 10 times slower compared to our Socket communication. For sure - by using lighttpd and tweaking the system we could improve performance - but still it’s a lot slower.
Also interesting are the results when we call the server not by IP but by URI - then the results look a lot worse:
1000 calls total: 156.423214912 sec.
Average: 0.156423214912 sec. per call
This is probably because our nslookup is quite slow ( we run Microsoft Small Business Server ) but still - the differences are dramatically.
Actually I could sum up now - but for the records I will try also the cURL way.
3. Using http via cURL
For using cURL we have to modify our client function a bit - the server can be left untouched.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | function Comm_cUrl( $sUri, $mPostData) { $mOptions = array( 'host' => $sUri, 'port' => 80, 'method' => 'POST', 'timeout' => 3, 'params' => $mPostData);$ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, $sUri ); curl_setopt( $ch, CURLOPT_HEADER, 0 ); curl_setopt( $ch, CURLOPT_USERAGENT, @$_SERVER['HTTP_USER_AGENT'] ); curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0 ); if ( 'POST' == $mOptions['method'] ) { curl_setopt( $ch, CURLOPT_POST, 1 ); $sPostString = ""; foreach( $mOptions['params'] as $key => $value ) { $sPostString .= "$key=" . utf8_encode( $value ) . "&"; } $sPostString = substr( $sPostString, 0, -1 ); curl_setopt( $ch, CURLOPT_POSTFIELDS, $sPostString ); } $mData = curl_exec( $ch ); curl_close( $ch ); return $mData; } |
Using IP we get these results:
1000 calls total: 3.17922592163 sec.
Average: 0.00317922592163 sec. per call
Interesting - a bit faster then with file_get_contents.
Finally let’s also try an URI and we get:
1000 calls total: 4.69447493553 sec.
Average: 0.00469447493553 sec. per call
So - cURL obivously caches the nslookup what leads to much better results.
4. Conclusion
More or less we got what we expected. Taking into account that multi threaded socket communication is a real beast and can cause a lot of trouble my personal opinion is that http will work fine for us. There is a lot of potential of speeding things up - so the difference is tolerable for us. This might be different for you
Results: Time Avg Typeof 0.47 0.00047 Socket 4.02 0.00402 file_get_contents 156.42 0.15642 file_get_contents by uri 3.17 0.00317 curl 4.69 0.00469 curl by uri
Comments
2 Responses to “Comparing communication speed between different machines in PHP”
Leave a Reply
[...] Comparing communication speed between different machines in PHP [...]
oh thanks.. everything i looked for