PHP输出缓冲区基准测试(与usleep一起使用时微时间不准确?)
我发布了一个可以复制的奇怪行为(至少在apache2+php5上)。 我不知道我是否做错了,但让我解释一下我试图实现的目标 我需要发送二进制数据块(比如说30)并在最后分析平均Kbit/s: 我对每个块输出时间、每个块大小求和,并在最后执行Kbit/s计算PHP输出缓冲区基准测试(与usleep一起使用时微时间不准确?),php,buffer,microtime,usleep,Php,Buffer,Microtime,Usleep,我发布了一个可以复制的奇怪行为(至少在apache2+php5上)。 我不知道我是否做错了,但让我解释一下我试图实现的目标 我需要发送二进制数据块(比如说30)并在最后分析平均Kbit/s: 我对每个块输出时间、每个块大小求和,并在最后执行Kbit/s计算 <?php // build my binary chunk $var= ''; $o=10000; while($o--) { $var.= pack('N', 85985); } // get the size,
<?php
// build my binary chunk
$var= '';
$o=10000;
while($o--)
{
$var.= pack('N', 85985);
}
// get the size, prepare the memory.
$size = strlen($var);
$tt_sent = 0;
$tt_time = 0;
// I send my chunk 30 times
for ($i = 0; $i < 30; $i++)
{
// start time
$t = microtime(true);
echo $var."\n";
ob_flush();
flush();
$e = microtime(true);
// end time
// the difference should reprenent what it takes to the server to
// transmit chunk to client right ?
// add this chuck bench to the total
$tt_time += round($e-$t,4);
$tt_sent += $size;
}
// total result
echo "\n total: ".(($tt_sent*8)/($tt_time)/1024)."\n";
?>
在上面的这个例子中,它迄今为止仍然有效(在本地主机上,它通过不同的测试从7000到10000 Kbit/s振荡)
现在,让我们假设我想要塑造传输,因为我知道客户端将有足够的数据块处理一秒钟
我决定使用usleep(1000000)来标记块传输之间的暂停
<?php
// build my binary chunk
$var= '';
$o=10000;
while($o--)
{
$var.= pack('N', 85985);
}
// get the size, prepare the memory.
$size = strlen($var);
$tt_sent = 0;
$tt_time = 0;
// I send my chunk 30 times
for ($i = 0; $i < 30; $i++)
{
// start time
$t = microtime(true);
echo $var."\n";
ob_flush();
flush();
$e = microtime(true);
// end time
// the difference should reprenent what it takes to the server to
// transmit chunk to client right ?
// add this chuck bench to the total
$tt_time += round($e-$t,4);
$tt_sent += $size;
usleep(1000000);
}
// total result
echo "\n total: ".(($tt_sent*8)/($tt_time)/1024)."\n";
?>
在最后一个例子中,我不知道为什么,计算的带宽可以从72000kbit/s跳到1200000,这是完全不准确/不相关的。
问题的一部分在于每次发送块时(在第一次usleep之后),输出我的块所用的时间都少得可笑
我做错了什么?缓冲区输出是否不同步?我不确定这些测试有多确定,但我发现它很有趣。在我的盒子上,我的平均速度约为170000kb/s。从一个联网的盒子中,这个数字上升到大约280000 kb/s。我想我们必须假设microtime(true)是相当准确的,尽管我读到它依赖于操作系统。您使用的是基于Linux的系统吗?真正的问题是我们如何计算1秒时间内传输的千比特数?我试图预测在1秒内可以发送多少个块,然后存储计算出的Kb/s,最后求平均值。我在flush()之前添加了一个sleep(1),这会产生预期的负kb/s 有些地方感觉不对劲,我很想知道您是否改进了测试方法。祝你好运
<?php
// build my binary chunk
$var= '';
$o=10000;
//Alternative to get actual bytes
$m1 = memory_get_usage();
while($o--)
{
$var.= pack('N', 85985);
}
$m2 = memory_get_usage();
//Your size estimate
$size = strlen($var);
//Calculate alternative bytes
$bytes = ($m2 - $m1); //40108
//Convert to Kilobytes 1 Kilobyte = 1024 bytes
$kilobytes = $size/1024;
//Convert to Kilobits 1 byte = 8 bits
$kilobits = $kilobytes * 8;
//Display our data for the record
echo "<pre>size: $size</pre>";
echo "<pre>bytes: $bytes</pre>";
echo "<pre>kilobytes: $kilobytes</pre>";
echo "<pre>kilobits: $kilobits</pre>";
echo "<hr />";
//The test count
$count = 100;
//Initialize total kb/s variable
$total = 0;
for ($i = 0; $i < $count; $i++)
{
// Start Time
$start = microtime(true);
// Utilize html comment to prevent browser from parsing
echo "<!-- $var -->";
// End Time
$end = microtime(true);
// Seconds it took to flush binary chunk
$seconds = $end - $start;
// Calculate how many chunks we can send in 1 second
$chunks = (1/$seconds);
// Calculate the kilobits per second
$kbs = $chunks * $kilobits;
// Store the kbs and we'll average all of them out of the loop
$total += $kbs;
}
//Process the average (data generation) kilobits per second
$average = $total/$count;
echo "<h4>Average kbit/s: $average</h4>";
在开始时间和结束时间之间添加usleep(50000)将导致本地和网络框以大约310 kb/s的速度保持一致。在循环中的任何其他地方,它都能按预期工作,除了本地框下降到大约100kb/s之外。网络盒似乎不受延迟的影响。在使用更新的测试脚本时,我没有发现usleep或sleep的异常行为。您是否在基于Linux的系统上?->对真正的问题是我们如何计算1秒时间内传输的千比特数?->不完全是。我想知道客户端需要多少时间来接收一块数据,然后睡眠来进行带宽整形。感谢您的时间,我正在测试您的结果,以确保我没有做错任何事情。@nunja“客户端接收一大块数据需要多长时间”。测试表明,我们不能这样做。在这种情况下,javascript解决方案会更好,但您并不意味着客户端是浏览器。客户端将可以访问实际数据速率。一些JQuery解决方案可以给您反馈,并允许一些“流量整形”。祝你好运,希望你能为其他感兴趣的人发布你的解决方案。我的感觉是,解决方案是使用直接套接字连接。但在我的服务器上,我只能使用apache2和端口80。是否有任何解决方案可以在传入的apache套接字中写入数据?