Резюме: (этот пост стал эпическим, когда я тестировал различные возможности)
PHP обычно использует две итерации цикла для обнаружения разъединения или для выдачи выходных данных.Эта задержка может исходить от программного обеспечения веб-сервера, хост-компьютера, клиентского компьютера и клиентского браузера, но тогда она должна варьироваться в зависимости от времени ожидания на одну итерацию.Скорее всего, задержка происходит из-за внутреннего выполнения или процесса вывода PHP (возможно, из небольшого внутреннего буфера или процесса обработки прерываний).
Epic Post:
ПодсчетВаше время выполнения из [Обновить] или URL-подтверждения не совсем точная отправная точка - сначала может потребоваться любое количество шагов, которое может увеличить задержку:
- Требуется поиск DNS (с использованием TCP)
- Установлено TCP-соединение с сервером
- Веб-сервер создает поток или дочерний элемент
- Веб-сервер решает, как обрабатывать запрос
- PHP может потребоваться запустить
- PHP может потребоваться преобразовать ваш источник в код операции
Поэтому вместо измерения [Обновить] -> [Стоп] время и сравнивая его с числом, записанным PHP, я измерил отображаемый вывод до записанный вывод - что уменьшает измерение задержки в основном только в пределах PHP (хотя сервер / браузер будет действоватьг).Измененный скрипт не может убежать (он завершается после фиксированного числа итераций), очищает буферизацию php.ini
по умолчанию и сообщает счетчик итераций на экране и в файле синхронизации.Я запускал скрипт с различными $sleep
периодами, чтобы увидеть эффекты.Окончательный сценарий:
<?php
date_default_timezone_set('America/Los_Angeles'); //Used by ob apparently
ignore_user_abort(true); //Don't terminate script because user leaves
set_time_limit(0); //Allow runaway script !danger !danger
while (@ob_end_flush()) {}; //By default set on/4K in php.ini
$start=microtime(true);
$n=1000;
$i=0;
$sleep=100000;// 0.1s
while(!connection_aborted() && $i<$n) {
echo "\n[".++$i."]";flush();
usleep($sleep);
}
$end=microtime(true);
file_put_contents("timing.txt",
"#\$sleep=".($sleep/1000000).
"s\n/ s=$start / e=$end ($i) / d=".($end-$start)."\n",
FILE_APPEND);
?>
Результаты: (несколько запусков объединены, запуск в Firefox)
# On-screen $i / start utime / end utime (current $i) / delta utime
#$sleep=1s
2 / s=1296251342.5729 / e=1296251346.5721 (4) / d=3.999242067337
3 / s=1296251352.9094 / e=1296251357.91 (5) / d=5.000559091568
#$sleep=0.1s
11 / s=1296251157.982 / e=1296251159.2896 (13) / d=1.3075668811798
8 / s=1296251167.5659 / e=1296251168.5709 (10) / d=1.0050280094147
16 / s=1296251190.0493 / e=1296251191.8599 (18) / d=1.810576915741
4 / s=1296251202.7471 / e=1296251203.3505 (6) / d=0.60339689254761
16 / s=1296251724.5782 / e=1296251726.3882 (18) / d=1.8099851608276
#$sleep=0.01s
42 / s=1296251233.0498 / e=1296251233.5217 (44) / d=0.47195816040039
62 / s=1296251260.4463 / e=1296251261.1336 (64) / d=0.68735003471375
150 / s=1296251279.2656 / e=1296251280.901 (152) / d=1.6353850364685
379 / s=1296252444.7587 / e=1296252449.0108 (394) / d=4.2521529197693
#$sleep=0.001s
337 / s=1296251293.4823 / e=1296251294.1515 (341) / d=0.66925406455994
207 / s=1296251313.7312 / e=1296251314.1445 (211) / d=0.41328597068787
792 / s=1296251324.5233 / e=1296251326.0915 (795) / d=1.5682451725006
(Opera не отображает числа во время, но отображаетпоследние цифры, которые примерно совпадают)
(Chrome ничего не отображает во время / после теста)
(Safari ничего не показывает во время / после теста)
(IE ничего не отображает во время /после теста)
Первое число в каждой строке указывает число, отображаемое на экране после нажатия [стоп] (запись вручную).
Несколько точек:
- Ваша точка останова квантуется до ближайшего
$sleep
периода (1/10 с в приведенном выше скрипте), потому что скрипт проверяет только в начале каждой во время итерации, есть некоторые различия, потому что метод usleep
не идеалензадержка. - Браузер и сервер, который вы используете, имеют значение.Примечания на странице руководства flush «могут не иметь возможности переопределить схему буферизации вашего веб-сервера и не влияют на буферизацию на стороне клиента в браузере».Затем более подробно расскажем о проблемах как сервера, так и клиента.[ Сервер : WinXPsp3 / Apache 2.2.17 / PHP 5.3.3 Клиент : WinXPsp3 / FireFox 3.6.13]
Анализ:
Во всех случаях, кроме задержки 0,001 с, мы наблюдаем задержку в 2 итерации между [остановкой] и перехватом PHP (или отчетами Firefox или Apache).С задержкой 0,001 с она немного меняется, в среднем ~ 4 итерации или 0,004 с - это, вероятно, приближается к порогу скорости обнаружения.
Когда время задержки составляет 0,1 с или выше, мы видимвремя выполнения близко совпадает $sleep
* {записанные итерации}.
Когда время задержки ниже 0,1 с, мы видим, что задержки выполнения превышают время ожидания.Вероятно, это связано со стоимостью проверки клиентского соединения, увеличением $i
, выводом текста и очисткой буфера за итерацию.Расхождение между временем выполнения и $i*$sleep
является довольно линейным, предполагая, что для выполнения этих задач требуется ~ 0,001 с / итерация (при сне в 0,01 с это 0,0008, в то время как в режиме сна 0,001 с получается 0,0010 - вероятно, в результате увеличения MALLOC
/ выход).