4

我发布了一个可以重现的奇怪行为(至少在 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";

?>

在上面的这个例子中,它到目前为止工作(在 localhost 上,它通过不同的测试从​​ 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";

?>

在最后一个示例中,我不知道为什么,计算出的带宽可以从 72000 Kbit/s 跃升至 1,200,000,这完全不准确/无关紧要。部分问题是每次发送一个块时(在第一次睡眠之后),输出我的块所测量的时间非常低。

我做错了什么?缓冲区输出是否不同步?

4

1 回答 1

0

我不确定这些测试有多明确,但我发现它很有趣。在我的盒子上,我的平均速度约为170000 kb/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>";

分析

即使我在测试中得出了一些任意值,它仍然是一个可以测量的值。使用联网的计算机可以增加对实际情况的洞察力。我原以为 localhost 机器会比联网机器具有更高的价值,但测试在很大程度上证明了这一点。在本地主机上时,我们必须发送原始二进制数据并接收它。这当然表明两个线程共享 cpu 周期,因此在同一台机器上的浏览器中进行测试时,假定的 kb/s 值实际上更低。因此,我们实际上是在测量 cpu 周期,并且当允许服务器成为服务器时,我们会获得更高的值。

当您将测试计数增加到 1000 时,一些有趣的事情开始出现。首先不要让浏览器解析数据。尝试在如此高的测试用例中呈现原始数据需要大量 CPU。我们可以手动查看系统监视器和任务管理器的情况。就我而言,本地是linux服务器,网络盒是xp。您可以通过这种方式获得一些实际的 kb/s 速度,并且很明显我们主要使用 cpu 和网络接口动态地提供数据。服务器不复制数据,因此无论我们设置多高的测试计数,我们只需要 40 KB 的内存空间。所以 40 KB 可以在 1000 个测试用例时动态生成 40 MB,在 10000 个用例时可以动态生成 400mb。

在运行测试用例 10000 多次后,我在 xp 中使用虚拟内存将 firefox 崩溃到低错误。linux 服务器上的系统监视器显示 cpu 和网络出现了一些可以理解的峰值,但总体而言非常快速地推出了大量数据并且有足够的空间可供使用。在 linux 上运行 10000 次实际上启动了交换驱动器并与服务器 cpu 周期挂钩。最有趣的事实是,我在上面获得的值仅在我在 Firefox 中接收和在本地测试时在 apache 中传输时才发生变化。我几乎锁定了 xp 盒子,但我的 ~280000 kb/s 网络值在打印输出时没有改变。

结论:

我们上面得出的 kb/s 值实际上是无用的,除非证明它无用。然而,测试本身显示了一些有趣的事情。在高测试案例中,我相信我实际上可以在服务器和客户端中看到一些物理缓冲。我们的测试脚本实际上将数据转储到 apache 并被释放以继续其工作。Apache当然会处理传输的细节。这实际上很高兴知道,但证明我们无法以这种方式测量从服务器到浏览器的实际传输速率。我们可以测量我们的服务器数据生成率,我猜这在某种程度上是否有意义。你猜怎么着!冲洗实际上减慢了速度。冲水是有惩罚的. 在这种情况下,没有理由这样做,并且删除 flush() 实际上加快了我们的数据生成速度。由于我们不处理网络,因此我们上面的值实际上更有意义的是保持为千字节。任何方式都没有用,所以我不会改变。

于 2011-04-21T20:35:53.207 回答