ID: 18367 Updated by: [EMAIL PROTECTED] Reported By: [EMAIL PROTECTED] Status: Bogus Bug Type: Performance problem Operating System: All PHP Version: 4.2.1 New Comment:
I've used Apache 1.3.26 and today's CVS of php. This test was done across local network, which is very important for this test, because your bechmark also includes network latency in it's test. Meaning that if you do this test over a slow connection the timings would reflect that fact. Because the 2nd timing won't be taken until the printed data is recieved by the browser on the other end. I've also done more accurate tests using php-cli on the console where there is network overhead. My benchmark resulted in the following timings for printing 250000 byte long string 10000 times. PHP - 0.824s Perl - 1m2.245s Ignore the manual comment, that is automatically added by the bug tracking system. Previous Comments: ------------------------------------------------------------------------ [2002-09-22 17:56:09] [EMAIL PROTECTED] > I've tried the suggested test and did not see any > significant slowdown you've mentioned. Did you really test with a server which which is in a significant distance to your client machine? And if so, which PHP and Apache Version did you use? I mean, I didn't invent this story, you know. Neither did the other users who faced this thing. I was just trying to track down the reason. Although I do not understand much of the interna it seems very likely to me that the reason sits in php OR in apache OR in the playing together of both. > There is one thing however, that may have skewed the > benchmark towards Perl in your initial code. In Perl > you seperate the text with a space, while in > PHP you use a new line. Sorry for this negligence, I tested in fact both variants in both systems and it wasn't any difference. PS: I do not understand your hint to the manual. If the manual says something about this, can you please point me to the exact location? ------------------------------------------------------------------------ [2002-09-22 16:35:38] [EMAIL PROTECTED] Thank you for taking the time to write to us, but this is not a bug. Please double-check the documentation available at http://www.php.net/manual/ and the instructions on how to report a bug at http://bugs.php.net/how-to-report.php I've tried the suggested test and did not see any significant slowdown you've mentioned. Infact the benchmarks came about the same. There is one thing however, that may have skewed the benchmark towards Perl in your initial code. In Perl you seperate the text with a space, while in PHP you use a new line. ------------------------------------------------------------------------ [2002-08-15 09:10:22] [EMAIL PROTECTED] Hi team! Was there any progress regarding this thing? Please tell me if you need more info. Thank you for your attention. Urs ------------------------------------------------------------------------ [2002-07-16 09:27:55] [EMAIL PROTECTED] This is a follow-up to http://bugs.php.net/bug.php?id=18029 (I can't reach the author of this bug, so I will do it this way). 18029 is in status "bogus", but I don't think this is correct. In my opinion it is buggy behaviour of either PHP or apache or both in combination. Please read the following to see why I think this can and has to be changed. What I noticed on my system: Redhat Linux 7.2 (Kernel 2.4.7-10) Apache/1.3.26 (Unix) PHP/4.2.1 mod_ssl/2.8.10 OpenSSL/ 0.9.6b resp. Apache/1.3.26 (Unix) PHP/4.2.0 mod_ssl/2.8.10 OpenSSL/0.9.6b Outputting a string of x characters length takes 2 milliseconds. Outputting a string of x+1 characters length takes 340 milliseconds. x is a number between 12000 and 15000. It does not matter whether I use echo, print, print_r or whatever to output the string. When I split the string in smaller parts and output the results separately, everything is normal. The timeout occurs if my browser is remote (ping-time about 200ms). This happens NOT, if my browser is in a LAN or local with the server, i.e. very close. The hint to TCP/IP window size (Nagle Algorithm) given by Ron Kuris to Shawn (owner of bug 18029) matches with this and the above observations. Execution of the Script does not continue before the ACK from the client for the first packet is received. This means that in scripts working with long strings the execution time of the script depends on the ping-time between the server and the client, and the duration of the idle time goes up together with the length of the string, i.e. a roundtrip is made for each multiple of the window size. I have positive reports of this from four systems, amongst them PHP 4.2.0 und 4.2.1; Apache 1.3.23, 1.3.24 and 1.3.26; OS Redhat, Cobalt and Windows 2000. I have 5 negative reports, but maybe all false negative because they were tested locally. Below is a test php script that can be used to verify this. There is also an equivalent perl script. I used it on the same host as a CGI-Script and found everything works fine there. I might be wrong of course, but I think this thing has to be treated as a bug because 1) it should be avoided 2) it can be avoided Please let me tell you why: 1) - There is growing number of modern PHP applications depending on the possibility of flawlessly outputting large strings. PEAR Cache for instance is affected, but template processors and XML/XSL applications as well. Of course these applications could all care themselves about splitting their output in smaller chunks, but this is very inefficient. - Although there is no additional CPU load, the number of running httpd-processes is kept high - for nothing. I don't know whether this is actually bad, but it sure is not very cool. - Clients have a bad response time although the server and network performance is good. 2) - The fact that a Perl CGI script (see below) can do the same thing without any problems shows imo that it is possible in some way to avoid these roundtrips! I have to admit that I have no idea of the apache/php interna, but I would be very glad if someone of the experts had a look at this. Thank you in advance! Urs <?php /** Long string performance behaviour test */ // ------ small Benchmark suite (as in in perl's Benchmark) --------- class Benchmark { var $time = 0; function Benchmark() { $mt = microtime(); $a = explode(" ",$mt); $t = $a[0] + $a[1]; $this->time = round(1000 * $t); } } function timestr($ms) { return sprintf("%01.2f", $ms/1000) . " seconds"; } function timediff($b1, $b2) { $ms = ($b1->time - $b2->time); return $ms; } // ------ test procedure --------- // prepare ($len = $_GET[l]) || ($len = 12905); $loop = floor($len / 5); $rest = $len % 5; $rlen = 5 * $loop; $str = ""; $t0 = new Benchmark; // generate the long string for($i=0; $i<=$loop; $i++) { $str = $str . "1234"; $str .= "\n"; } $str .= str_repeat(".",$rest); // report $t1 = new Benchmark; $report .= "<h1>Long string performance behaviour test</ h1>"; $report = "\n<br>\n<br>Generated a string with $len characters" . " (use ?l=12345 in the URI to override)"; $report .= "\n<br>(took me " . timestr(timediff($t1, $t0)) . ")"; // print the long string print $str; // report again $t2 = new Benchmark; $report .= "\n<br>Time to output string: ".timestr(timediff($t2, $t1)); print $report; ?> test.pl: #! /usr/bin/perl use CGI qw(:standard); use Benchmark; print header(); # prepare ($len = param("l")) || ($len = 50000); $loop = int($len / 5); $rest = $len % 5; $rlen = 5 * $loop; $str = ""; $t0 = new Benchmark; # generate the long string for($i=0; $i<=$loop; $i++) { $str = $str . "1234 "; } # report $t1 = new Benchmark; $report .= "<h1>Long string performance behaviour test</ h1>"; $report = "\n<br>\n<br>Generated a string with $len characters" . " (use ?l=12345 in the URI to override)"; $report .= "\n<br>(took me " . timestr(timediff($t1, $t0)) . ")"; # print the long string print $str; # report again $t2 = new Benchmark; $report .= "\n<br>Time to output string: ".timestr(timediff($t2, $t1)); print $report; ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=18367&edit=1