PHP输出缓冲区基准测试(与usleep一起使用时微时间不准确?)

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,

我发布了一个可以复制的奇怪行为(至少在apache2+php5上)。 我不知道我是否做错了,但让我解释一下我试图实现的目标

我需要发送二进制数据块(比如说30)并在最后分析平均Kbit/s:

我对每个块输出时间、每个块大小求和,并在最后执行Kbit/s计算

    <?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套接字中写入数据?