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";

?>

上記のこの例では、これまでのところ機能しています(ローカルホストでは、さまざまなテストを通じて7000から10000 Kbit / sまで振動します)。

ここで、送信を整形したいとします。これは、クライアントが1秒間処理するのに十分なデータのチャンクを持っていることがわかっているためです。

チャンク送信間の一時停止をマークするために、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に跳ね上がる可能性があり、まったく不正確/無関係です。問題の一部は、チャンクが送信されるたびに(最初のusleepの後)、チャンクを出力するために測定された時間が途方もなく短いことです。

私は何か間違ったことをしていますか?バッファ出力は同期していませんか?

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 では、生のバイナリ データの送信と受信の両方を行う必要があります。もちろん、これは 2 つのスレッドが CPU サイクルを共有していることを示しているため、同じマシン上のブラウザーでテストすると、想定される kb/s 値は実際には低くなります。したがって、実際に CPU サイクルを測定しており、サーバーがサーバーとして許可されている場合は、より高い値が得られます。

テスト数を 1000 に増やすと、いくつかの興味深いことが明らかになり始めます。まず、ブラウザーにデータを解析させないでください。このような高いテストケースで生データをレンダリングしようとすると、大量の CPU が必要になります。たとえば、システム モニターやタスク マネージャーを使用して、何が起こっているかを手動で監視できます。私の場合、ローカルは Linux サーバーで、ネットワーク ボックスは XP です。この方法で実際の kb/s 速度を得ることができ、主に CPU とネットワーク インターフェイスを使用して動的にデータを提供していることが明らかになります。サーバーはデータをレプリケートしないため、テスト カウントをどれだけ高く設定しても、必要なメモリ空間は 40 キロバイトだけです。したがって、40 キロバイトは、1000 件のテスト ケースで 40 メガバイトを動的に生成でき、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 に答える