Тест выходного буфера PHP (микротайм неточен при использовании с usleep?) - PullRequest
4 голосов
/ 20 апреля 2011

Выкладываю странное поведение, которое можно воспроизвести (по крайней мере на apache2 + php5). Я не знаю, делаю ли я что-то не так, но позвольте мне объяснить, чего я пытаюсь достичь.

Мне нужно отправить куски двоичных данных (скажем, 30) и проанализировать среднее значение Кбит / с в конце:

Я суммирую время вывода каждого блока, размер каждого блока и в конце выполняю вычисление в Кбит / с.

    <?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 Кбит / с через различные тесты).

Теперь, допустим, я хочу сформировать передачу, потому что я знаю, что у клиента будет достаточно части данных для обработки в течение секунды.

Я решил использовать 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 Кбит / с до 1 200 000, это совершенно неточно / не имеет значения. Частично проблема заключается в том, что время, измеряемое для вывода моего чанка, смехотворно мало при каждой отправке чанка (после первого перехода в спящий режим).

Я что-то не так делаю? Выходной буфер не является синхронным?

1 Ответ

0 голосов
/ 22 апреля 2011

Я не уверен, насколько важны эти тесты, но я нашел это интересным.На моем боксе я в среднем около 170000 кб / с .Из сетевой коробки это число достигает примерно 280000 кбит / с .Я предполагаю, что мы должны предположить, что microtime (true) является довольно точным, хотя я читал, что это зависит от операционной системы.Вы в системе на основе Linux?Реальный вопрос заключается в том, как мы вычисляем килобиты, переданные за 1-секундный период времени?Я пытаюсь спроецировать, сколько чанков можно отправить за 1 секунду, а затем сохранить рассчитанные килобайты в секунду для усреднения в конце.Я добавил sleep (1) перед flush (), и это привело к отрицательным кбит / с, как и следовало ожидать.

Что-то не так, и мне было бы интересно узнать, улучшили ли вы свои тестыметод.Удачи!

<code><?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
"; echo"
bytes: $bytes
"; echo"
kilobytes: $kilobytes
"; echo"
kilobits: $kilobits
"; echo""; // Счетчик тестов $ count = 100; // Инициализировать переменную общего количества килобайт / с $ total = 0; для ($ i = 0; $ i <$ count; $ i ++) {// Время начала $ start = microtime(true); // Использовать html-комментарий, чтобы браузер не разбирал эхо ""; // Время окончания $ end = microtime (true); // Секунды, необходимые для очистки двоичного чанка $ seconds = $ end - $ start; // Вычислить, сколько чанков мы можем отправить за 1 секунду $ chunks = (1 /$ seconds); // Рассчитать килобит в секунду $ kbs = $ chunks * $ kilobits; // Сохраняем kbs, и мы все усредним из цикла $ total + = $ kbs;} // Обработка среднего(генерация данных) килобит в секунду $ среднее = общее $ / количество $; эхо "<h4> Среднее кбит / с: среднее $ ";

Анализ

Несмотря на то, что я придумаю какое-то произвольное значение в тесте, это все еще значение, которое можно измерить. Использование сетевого компьютера добавляет понимание того, что на самом деле происходит. Я бы подумал, что машина localhost будет иметьболее высокое значение, чем у сетевого блока, но тесты в значительной степени доказывают обратное. Когда на локальном хосте мы должны и отправлять необработанные двоичные данные, и получать их. Это, конечно, показывает, что два потока совместно используют циклы ЦП и, следовательно, предполагаемый kb /значение s в fдействовать ниже при тестировании в браузере на той же машине.Поэтому мы действительно измеряем циклы процессора и получаем более высокие значения, когда серверу разрешено быть сервером.

Некоторые интересные вещи начинают проявляться, когда вы увеличиваете количество тестов до 1000. Во-первых, не делайтебраузер разбирает данные.Требуется много ресурсов процессора, чтобы попытаться отобразить необработанные данные в таких высоких тестовых случаях.Мы можем вручную наблюдать за тем, что происходит, например, с помощью системного монитора и диспетчера задач.В моем случае локальный сервер Linux, а сетевой блок - XP.Таким способом вы можете получить реальные скорости передачи данных в кбит / с, и становится очевидным, что мы динамически обслуживаем данные, используя в основном процессорные и сетевые интерфейсы.Сервер не реплицирует данные и, следовательно, независимо от того, насколько высоко мы установили количество тестов, нам нужно всего 40 килобайт дискового пространства.Таким образом, 40 килобайт могут генерировать 40 мегабайт динамически при 1000 тестовых случаях и 400 Мб при 10000 случаях.

Я разбил Firefox в XP с виртуальной памятью на низкую ошибку после запуска тестового примера 10000 несколько раз.Системный монитор на сервере Linux показал некоторые понятные всплески в процессоре и сети, но в целом очень быстро вытолкнул большой объем данных и оставил достаточно места.Выполнение 10000 дел в Linux несколько раз приводило к ускорению работы диска подкачки и привязке к циклу процессора сервера.Наиболее интересным фактом является то, что мои значения, которые я получил выше, менялись только тогда, когда я получал в Firefox и передавал в Apache при локальном тестировании.Я практически заблокировал окно xp, но мое сетевое значение ~ 280000 кбит / с не изменилось на распечатке.

Вывод:

Значение кбит / с, к которому мы пришли выше, практически бесполезно, если не считать его бесполезным. Сам тест, однако, показывает некоторые интересные вещи. Я полагаю, что при высоких тестах я мог наблюдать физическую буферизацию как на сервере, так и на клиенте. Наш тестовый скрипт на самом деле сбрасывает данные в apache, и он выпускается для продолжения своей работы. Apache обрабатывает детали передачи курса. Это на самом деле приятно знать, но доказывает, что мы не можем измерить фактическую скорость передачи с нашего сервера в браузер таким образом. Я думаю, мы можем измерить скорость генерации данных на наших серверах, если это имеет какое-то значение. Угадай, что! Промывка на самом деле замедлила скорость. Theres штраф за смывание . В этом случае нет причин для этого, и удаление flush () фактически увеличивает скорость генерации данных. Так как мы не имеем дело с сетью, наша ценность на самом деле более значима в килобайтах. Это бесполезно, поэтому я не меняюсь.

...