Archive for the ‘Performance’ Category
Searching data in xml efficiently
Sunday, October 16th, 2011There is many way to search data in xml documents.
For example I needed find Spanish subtitles in given xml:
<?xml version="1.0" encoding="UTF-8"?> <import> <video> <title>Movie_1</title> <id>123</id> <meta_data> <duration>1:59:12</duration> </meta_data> <subtitles> <subtitle>ftp://user:pass@example.com/123/subtitles_fi.sub</subtitle> <subtitle>ftp://user:pass@example.com/123/subtitles_en.sub</subtitle> <subtitle>ftp://user:pass@example.com/123/subtitles_es.sub</subtitle> <subtitle>ftp://user:pass@example.com/123/subtitles_pl.sub</subtitle> </subtitles> </video> </import>
The most easy way is of course:
/** * Return callback function which check if fileURL contains proper language version */ $fFindSubtitlesByLang = function ($lang) { $lang .= '.'; //to be sure that no part of 'example' word is searching return function ($fileUrl) use ($lang) { return strpos($fileUrl, $lang); }; }; //normal usage of Simple Xml Element $subtitles = (array) $xml->video->subtitles; $spanishSubtitles = reset(array_filter($subtitles['subtitle'], $fFindSubtitlesByLang('es'))); echo $spanishSubtitles .PHP_EOL;
It works, great. But there is also possibility to use Xpath
$subtitles = $xml->xpath('/import/video/subtitles/subtitle'); $spanishSubtitles = reset(array_filter($subtitles, $fFindSubtitlesByLang('es'))); echo $spanishSubtitles .PHP_EOL;
In my opinion this solution looks much better. Special designed function (xpath) is used for traversing XML, but this attempt is slower than previous example. This is not good.
So lets try modify xpath a little:
$spanishSubtitles = reset($xml->xpath('/import/video/subtitles/subtitle[contains(., "es.")]')); echo $spanishSubtitles .PHP_EOL;
Viola! Fast, readable, only 2 lines of code, not need to use anonymous function. Also adding some additional logic (e.g. specify id of element which I am looking for) is extremely easy.
More info about available function can be found on W3C pages http://www.w3schools.com/xpath/xpath_functions.asp
All files are available here: https://github.com/mrok/xpath-examples
Http build query
Monday, July 18th, 2011Today during code review Olle noticed that there is much simpler way to build query part of url then concatenate strings in loop.
For example instead of:
$aParams = array('id' => 12,
'method' => 'post',
'callback_function_name' => 'add');
$sQuery = '?';
foreach ($aParams as $key => $value) {
$sQuery .= $key .'=' .$value .'&';
}
$sQuery = substr($sQuery, 0, -1); //to remove last &
$sUrl = $sHost .$sQuery;
Solution proposed by Olle was:
$aParams = array('id' => 12,
'method' => 'post',
'callback_function_name' => 'add');
$sQuery = http_build_query($aParams, '', '&');
$sUrl = $sHost . $sQuery;
I checked that function in manual and it looks quite powerful. One thing which considered me was performance, of course native C function are faster then loop, etc, but is not that function too powerful and slow to use it in responsible part of code with huge load?
Lets check:
$aParams = array('id' => 12,
'user_id' => 234,
'method' => 'post',
'callback_function_name' => 'add');
$fStarttime = microtime(true);
for ($i = 0; $i < 100000; $i++) {
$sQuery = http_build_query($aParams, '', '&');
}
echo 'http_build_query: ' . (microtime(true) - $fStarttime) .PHP_EOL;
$fStarttime = microtime(true);
for ($i = 0; $i < 100000; $i++) {
$sQuery = '';
foreach ($aParams as $key => $value) {
$sQuery .= $key . '=' . $value . '&';
}
$sQuery = substr($sQuery, 0, -1); //to remove last &
}
echo 'concatenation: ' . (microtime(true) - $fStarttime);
and results:
http_build_query: 0.69601511955261 concatenation: 1.1222679615021
As you see it is definitely easier, faster way and needs less lines of code.
Tip: there is an extension called http://dk.php.net/manual/en/book.http.php which posses more useful function.
In PHP5.4 second approach will faster due to introduce caches to eliminate repeatable run-time bindings of functions, classes, constants, methods and properties – more info about this feature here