Bug #73412 [Opn->Ana]: url-wrappers in PHP7 terrible slow
| From: | rasmus@php.net | Date: | Mon, 31 Oct 2016 01:52:20 +0000 |
| Subject: | Bug #73412 [Opn->Ana]: url-wrappers in PHP7 terrible slow | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-205084@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=73412&edit=1
ID: 73412
Updated by: rasmus@php.net
Reported by: spam2 at rhsoft dot net
Summary: url-wrappers in PHP7 terrible slow
-Status: Open
+Status: Analyzed
Type: Bug
Package: Performance problem
Operating System: Linux
PHP Version: 7.0.12
Block user comment: N
Private report: N
New Comment:
I see a couple of issues with your sample code here. The biggest one being that you are not
comparing the same things at all. get_headers(), as per the docs, uses a GET request by default. But
your curl example uses a HEAD request. Obviously a HEAD request is going to be much quicker.
Your php get_headers() vs. wget timing isn't valid either since obviously php cli has way more
startup work to do than wget.
I just wrote a quick test and I don't see a drastic difference between curl and the url
wrappers on Linux. I got this output:
4.2943890094757
5.9716069698334
So yes, get_headers() is a bit slower, but certainly not orders of magnitude like you are claiming.
This is my test script:
<?php
function curl_headers($url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$r = curl_exec($ch);
curl_close($ch);
return explode("\n", trim($r));
}
$i=0;
$start = microtime(true);
while($i++<1000) {
$headers = curl_headers('http://htpc/index.html');
}
echo (microtime(true) - $start)."\n";
$i=0;
stream_context_set_default(['http' => ['method' => 'HEAD']]);
$start = microtime(true);
while($i++<1000) {
$headers = get_headers('http://htpc/index.html');
}
echo (microtime(true) - $start)."\n";
Previous Comments:
------------------------------------------------------------------------
[2016-10-30 18:56:01] spam2 at rhsoft dot net
just switch between curl and pure PHP and you have factor 57 by *just* 57 requests, that's
ridiculous, especially since the curl stuff uses much more function calls and wiithin 36 secodns
every sane software can make thousands of http requests
_______________________________
$use_url = true;
real 0m0.647s
user 0m0.057s
sys 0m0.041s
_______________________________
$use_url = false;
real 0m36.959s
user 0m0.047s
sys 0m0.051s
_______________________________
#!/usr/bin/php
<?php
if(PHP_SAPI == 'cli')
{
$use_url = false;
$dynamic = array();
$static = array();
$staticp = array();
$requests = 50;
for($count=1; $count<=$requests; $count++)
{
$dynamic[] = get_repsonse_time('http://corecms/index.php');
$static[] = get_repsonse_time('http://corecms/static.htm');
$staticp[] = get_repsonse_time('http://corecms/static.php');
}
$dynamic_sum = array_sum($dynamic);
$static_sum = array_sum($static);
$staticp_sum = array_sum($staticp);
$dynamic_avg = $dynamic_sum / count($dynamic);
$static_avg = $static_sum / count($static);
$staticp_avg = $staticp_sum / count($staticp);
echo 'COUNT: ' . count($dynamic) . "\n";
echo 'DYNAMIC CMS: ' . round($dynamic_avg) . " us\n";
echo 'STATIC HTM: ' . round($static_avg) . " us\n";
echo 'STATIC PHP: ' . round($staticp_avg) . " us\n";
echo 'FACTOR D/S: ' . round($dynamic_avg / $static_avg, 1) . "\n";
echo 'FACTOR P/S: ' . round($staticp_avg / $static_avg, 1) . "\n";
echo 'FACTOR D/P: ' . round($dynamic_avg / $staticp_avg, 1) . "\n";
}
function get_repsonse_time($url)
{
global $use_url;
switch($use_url)
{
case false:
$response = get_headers($url, 1);
$response = explode('D=', $response['X-Response-Time']);
return (int)trim(str_replace(' us', '', $response[1]));
break;
case true:
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD');
$response = curl_exec($ch);
curl_close($ch);
$response = explode("\n", $response);
foreach($response as $response_line)
{
if(strpos($response_line, 'X-Response-Time') !== false)
{
$response = explode('D=', $response_line);
return (int)trim(str_replace(' us', '', $response[1]));
break;
}
}
break;
}
}
?>
------------------------------------------------------------------------
[2016-10-30 18:33:09] spam2 at rhsoft dot net
changed subject
------------------------------------------------------------------------
[2016-10-30 18:31:27] spam2 at rhsoft dot net
the same for file_get_contents, HEAD Requests or GET, the same with the curl extension is
*magnitudes* faster and in fact this is a PHP/ regression because i just needed to rewrite some
fuzzy-request scripts which would run the whole day long and originally had no problem with PHP5.x
in short: url-wrappers in PHP7 are broken and unuseable in case you have a noticebale amount of
requests triggering them
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $dst_url);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:49.0)
Gecko/20100101 Firefox/49.0');
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD');
$buffer = curl_exec($ch);
curl_close($ch);
------------------------------------------------------------------------
[2016-10-28 14:06:38] spam2 at rhsoft dot net
Description:
------------
may someone explain me why PHP is that terrible slow with the test-script below doing 150 HTTP-calls
on a local webserver where the 50 most expensive CMS requests take only 5037 us (the header which i
want to parse out to measure the difference between cms, htm-file and htm-file with .php extension
comes from httpd - Header always set "X-Response-Time" "%D us")
40 seconds for 150 requests - on a machine which can "ab -c 20 -n 100000 http://localhost/" handle 1200 per second?
[harry@srv-rhsoft:/downloads]$ time php -r "get_headers('http://corecms/static.htm');"
real 0m0.040s
user 0m0.026s
sys 0m0.013s
[harry@srv-rhsoft:/downloads]$ time wget http://corecms/static.htm
real 0m0.006s
user 0m0.002s
sys 0m0.003s
Test script:
---------------
[harry@srv-rhsoft:/downloads]$ time php /www/corecms.rhsoft.net/response-times.php
COUNT: 50
DYNAMIC CMS: 5037 us
STATIC HTM: 346 us
STATIC PHP: 1645 us
FACTOR D/S: 14.6
FACTOR P/S: 4.8
FACTOR D/P: 3.1
real 0m39.557s
user 0m0.059s
sys 0m0.043s
________________________________________
[harry@srv-rhsoft:/downloads]$ cat /www/corecms.rhsoft.net/response-times.php
#!/usr/bin/php
<?php
if(PHP_SAPI == 'cli')
{
$dynamic = array();
$static = array();
$staticp = array();
$requests = 50;
for($count=1; $count<=$requests; $count++)
{
$dynamic[] = get_repsonse_time('http://corecms/index.php');
$static[] = get_repsonse_time('http://corecms/static.htm');
$staticp[] = get_repsonse_time('http://corecms/static.php');
}
$dynamic_sum = array_sum($dynamic);
$static_sum = array_sum($static);
$staticp_sum = array_sum($staticp);
$dynamic_avg = $dynamic_sum / count($dynamic);
$static_avg = $static_sum / count($static);
$staticp_avg = $staticp_sum / count($staticp);
echo 'COUNT: ' . count($dynamic) . "\n";
echo 'DYNAMIC CMS: ' . round($dynamic_avg) . " us\n";
echo 'STATIC HTM: ' . round($static_avg) . " us\n";
echo 'STATIC PHP: ' . round($staticp_avg) . " us\n";
echo 'FACTOR D/S: ' . round($dynamic_avg / $static_avg, 1) . "\n";
echo 'FACTOR P/S: ' . round($staticp_avg / $static_avg, 1) . "\n";
echo 'FACTOR D/P: ' . round($dynamic_avg / $staticp_avg, 1) . "\n";
}
function get_repsonse_time($url)
{
$response = get_headers($url, 1);
$response = explode('D=', $response['X-Response-Time']);
return (int)trim(str_replace(' us', '', $response[1]));
}
?>
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=73412&edit=1