摘要:(当我测试各种途径时,这篇文章变得史诗般)
PHP 需要(通常是两次)while 循环迭代来检测断开连接或传递输出。这种延迟可能来自 Web 服务器软件、主机、客户端计算机和客户端浏览器,但它应该根据每次迭代的睡眠而有所不同。延迟更可能来自 PHP 的内部执行或输出过程(可能来自一个小的内部缓冲区或中断处理过程)。
史诗般的帖子:
从 [Refresh] 或URL-submit计算您的执行时间并不完全是一个准确的起点 - 首先可能需要任何数量的步骤,并且可能会增加延迟:
- 需要 DNS 查找(有 TCP 开销)
- 与服务器建立 TCP 连接
- Web 服务器创建线程或子线程
- Web Server 决定如何处理请求
- PHP 可能需要启动
- PHP 可能需要将您的源代码转换为操作码
因此,我没有测量 [Refresh] -> [Stop] 时间并将其与 PHP 记录的数字进行比较,而是测量了显示的输出与记录的输出- 这将延迟测量减少到大部分仅在 PHP 内(尽管服务器/浏览器会起作用)。修改后的脚本不能跑掉(它在固定数量的迭代后终止),清除默认php.ini
缓冲,并在屏幕和计时文件中报告迭代计数。我用不同的时间段运行脚本$sleep
来查看效果。最终脚本:
<?php
date_default_timezone_set('America/Los_Angeles'); //Used by ob apparently
ignore_user_abort(true); //Don't terminate script because user leaves
set_time_limit(0); //Allow runaway script !danger !danger
while (@ob_end_flush()) {}; //By default set on/4K in php.ini
$start=microtime(true);
$n=1000;
$i=0;
$sleep=100000;// 0.1s
while(!connection_aborted() && $i<$n) {
echo "\n[".++$i."]";flush();
usleep($sleep);
}
$end=microtime(true);
file_put_contents("timing.txt",
"#\$sleep=".($sleep/1000000).
"s\n/ s=$start / e=$end ($i) / d=".($end-$start)."\n",
FILE_APPEND);
?>
结果:(多个运行串联,在 Firefox 中运行)
# On-screen $i / start utime / end utime (current $i) / delta utime
#$sleep=1s
2 / s=1296251342.5729 / e=1296251346.5721 (4) / d=3.999242067337
3 / s=1296251352.9094 / e=1296251357.91 (5) / d=5.000559091568
#$sleep=0.1s
11 / s=1296251157.982 / e=1296251159.2896 (13) / d=1.3075668811798
8 / s=1296251167.5659 / e=1296251168.5709 (10) / d=1.0050280094147
16 / s=1296251190.0493 / e=1296251191.8599 (18) / d=1.810576915741
4 / s=1296251202.7471 / e=1296251203.3505 (6) / d=0.60339689254761
16 / s=1296251724.5782 / e=1296251726.3882 (18) / d=1.8099851608276
#$sleep=0.01s
42 / s=1296251233.0498 / e=1296251233.5217 (44) / d=0.47195816040039
62 / s=1296251260.4463 / e=1296251261.1336 (64) / d=0.68735003471375
150 / s=1296251279.2656 / e=1296251280.901 (152) / d=1.6353850364685
379 / s=1296252444.7587 / e=1296252449.0108 (394) / d=4.2521529197693
#$sleep=0.001s
337 / s=1296251293.4823 / e=1296251294.1515 (341) / d=0.66925406455994
207 / s=1296251313.7312 / e=1296251314.1445 (211) / d=0.41328597068787
792 / s=1296251324.5233 / e=1296251326.0915 (795) / d=1.5682451725006
(Opera 期间不显示数字,但显示大致匹配的最终数字)
(Chrome 在测试期间/之后不显示任何内容)
(Safari 在测试期间/之后不显示任何内容)
(IE 不显示任何内容测试期间/之后)
每行的第一个数字表示按下[停止]后屏幕上显示的数字(手动记录)。
几点:
- 您的停止点被量化到最近的
$sleep
周期(上述脚本中的 1/10 秒),因为脚本仅在每次迭代开始时检查,存在一些变化,因为该usleep
方法不是完美的延迟。
- 您使用的浏览器和服务器会有所不同。刷新手册页指出“可能无法覆盖 Web 服务器的缓冲方案,并且对浏览器中的任何客户端缓冲没有影响。” 然后更详细地介绍服务器和客户端问题。[服务器:WinXPsp3 / Apache 2.2.17 / PHP 5.3.3 客户端:WinXPsp3 / FireFox 3.6.13]
分析:
除了 0.001 秒的延迟之外,我们看到 [stop] 和 PHP 捕获它(或 Firefox 或 Apache 报告)之间存在 2 次迭代延迟。延迟为 0.001 秒,它会有所不同,平均约为 4 次迭代或 0.004 秒 - 这可能接近检测速度阈值。
当延迟时间为 0.1 秒或以上时,我们会看到执行时间与$sleep
* {记录的迭代}非常匹配。
当延迟时间低于 0.1 秒时,我们会看到执行延迟大于睡眠时间。这可能来自检查客户端连接、递增$i
、输出文本和每次迭代刷新缓冲区的成本。$i*$sleep
执行时间和非常线性之间的差异表明完成这些任务需要大约 0.001 秒/次迭代(0.01 秒的睡眠时间为 0.0008,而 0.001 秒的睡眠时间为 0.0010 - 可能是MALLOC
/ 输出增加的结果)。