Проблема вывода информации из ПХП в Апач.

ONK

Пассивист PHPСluba
Проблема вывода информации из ПХП в Апач.

Занимался оптимизацией кода скриптов и в результате замеров различных участков кода обнаружил что
самым большим тормозом является вывод информации, скрипты генерируют HTML быстрее чем его удаётся вывести. Причём нет никакой разницы между методом вывода информации, что echo то и print() и другие функции вывода работают одинаково медленно.

Протестировал на трёх различных системах, результаты абсалютно разные, но стабильные.
Везде наблюдается очень быстрая работа вывода до тех пор пока выводимая строка не привысит определённую длину от 6 до 50кб..

Тогда я написал небольшой тест результаты которого просто ужасающие. Фактически на некоторых реально работающих хостингах просто нельзя размещать проекты генерирующие большие страници и это притом что скоро страница размером в 100кб и более будет вполне нормальным явлением, да собственно и сейчас часто встречаются..

Вот код применённого теста:
PHP:
<?php
class onk_Time_marker{
	var $start_mark;

	function onk_Time_marker(){
	  $prom = explode(" ",substr(microtime(),2));
	  $this->start_mark = "$prom[1].$prom[0]";
	}

	function current_time(){
		$prom = explode(" ",substr(microtime(),2));
   		$micro_stop = "$prom[1].$prom[0]";
		$time = round($micro_stop - $this->start_mark,8);
		return $time;
	}
}

$mark10 = new onk_Time_marker();
$chr = "a";
$str = "";

//сгенерим строку в 10000 символов.
for($i=0;$i<10000;$i++){
	$str .= $chr;
}

$time_log = "";
$out = "";

for($j=0;$j<15;$j++){
	$out .= $str;
	$prom_time = $mark10->current_time();
	echo "<br>",$out ;
	$time_log .= "<br>Блок $j длинной ".strlen($out)." символов выводился ".($mark10->current_time() - $prom_time);
}
//вывод лога времени вывода строк.
echo $time_log;
?>
Тест был запущен в трёх режимах :
1. Вывод 15 строк по 10кб
2. Вывод 3 строк по 100кб
3. Вывод 15 строк по 1кб

Третий тест был применён для более точного установления критического размера строка с которого начинается резкое падение скорости вывода на самом плохом из протестированных серверов.
Лучшие результаты показал тестовый сервер на Win2k , но и на нём мои скрипты генерируют html быстрее чем он потом выводится..
Поммо этих тестов я проводил тесы на вывод коротких срок, наблюдалось очень странное поведение системы, строки по 100знаков выводились очень быстро, но регулярно одна из нескольких десятков строк выводилась на два порядка дольше чем остальные, суммарно время вывода 200кб текста составило примерно одинаковое время как при выводе в виде одной строки так и в виде мелких строк (мелкие строки выводились чуть дольше).
Вот такая вот информация для размышленя..


PHP 4.2.3
System - Linux P3-1000
Apache Version - Apache/1.3.27
Apache Release – 10327100
Apache API Version – 19990320

Отчёт работы теста:
Блок 0 длинной 10000 символов выводился 0.00060106
Блок 1 длинной 20000 символов выводился 1.40620291
Блок 2 длинной 30000 символов выводился 2.49554503
Блок 3 длинной 40000 символов выводился 3.06659603
Блок 4 длинной 50000 символов выводился 4.60277391
Блок 5 длинной 60000 символов выводился 4.46952605
Блок 6 длинной 70000 символов выводился 5.879825
Блок 7 длинной 80000 символов выводился 5.8825109
Блок 8 длинной 90000 символов выводился 7.52892601
Блок 9 длинной 100000 символов выводился 8.18411803
Блок 10 длинной 110000 символов выводился 9.18472195
Блок 11 длинной 120000 символов выводился 9.93079603
Блок 12 длинной 130000 символов выводился 10.35447407
Блок 13 длинной 140000 символов выводился 11.180511
Блок 14 длинной 150000 символов выводился 12.72193003
Тест 2
Блок 0 длинной 100000 символов выводился 7.39310801
Блок 1 длинной 200000 символов выводился 60.21533799
Блок 2 длинной 300000 символов выводился 26.92223811
Тест 3
Блок 0 длинной 1000 символов выводился 0.00030803
Блок 1 длинной 2000 символов выводился 0.00010597
Блок 2 длинной 3000 символов выводился 0.00027394
Блок 3 длинной 4000 символов выводился 0.00011599
Блок 4 длинной 5000 символов выводился 0.00021994
Блок 5 длинной 6000 символов выводился 0.00019896
Блок 6 длинной 7000 символов выводился 1.12903798
Блок 7 длинной 8000 символов выводился 0.72569001
Блок 8 длинной 9000 символов выводился 0.82241702
Блок 9 длинной 10000 символов выводился 0.80723202
Блок 10 длинной 11000 символов выводился 0.72387004
Блок 11 длинной 12000 символов выводился 0.70184803
Блок 12 длинной 13000 символов выводился 1.41053605
Блок 13 длинной 14000 символов выводился 0.82312703
Блок 14 длинной 15000 символов выводился 1.409536

PHP 4.1.0
System - Windows NT 5.0 build 2195 P3-933
Apache Version - Apache/1.3.20
Apache Release – 10320100
Apache API Version – 19990320

Отчёт работы теста:
Блок 0 длинной 10000 символов выводился 0.00471198
Блок 1 длинной 20000 символов выводился 0.00233006
Блок 2 длинной 30000 символов выводился 0.00326002
Блок 3 длинной 40000 символов выводился 0.004583
Блок 4 длинной 50000 символов выводился 0.01220894
Блок 5 длинной 60000 символов выводился 0.30644393
Блок 6 длинной 70000 символов выводился 0.20436299
Блок 7 длинной 80000 символов выводился 0.19851303
Блок 8 длинной 90000 символов выводился 0.20067799
Блок 9 длинной 100000 символов выводился 0.20014107
Блок 10 длинной 110000 символов выводился 0.01142108
Блок 11 длинной 120000 символов выводился 0.01164198
Блок 12 длинной 130000 символов выводился 0.186566
Блок 13 длинной 140000 символов выводился 0.19300294
Тест 2
Блок 0 длинной 100000 символов выводился 0.18351007
Блок 1 длинной 200000 символов выводился 0.0182159
Блок 2 длинной 300000 символов выводился 0.02775705
Тест 3
Блок 0 длинной 1000 символов выводился 0.00022399
Блок 1 длинной 2000 символов выводился 8.595E-005
Блок 2 длинной 3000 символов выводился 0.00259197
Блок 3 длинной 4000 символов выводился 0.00139999
Блок 4 длинной 5000 символов выводился 0.00079298
Блок 5 длинной 6000 символов выводился 0.00146902
Блок 6 длинной 7000 символов выводился 0.00074101
Блок 7 длинной 8000 символов выводился 0.00173699
Блок 8 длинной 9000 символов выводился 0.00141299
Блок 9 длинной 10000 символов выводился 0.00146401
Блок 10 длинной 11000 символов выводился 0.00161898
Блок 11 длинной 12000 символов выводился 0.00162506
Блок 12 длинной 13000 символов выводился 0.00203109
Блок 13 длинной 14000 символов выводился 0.00183892
Блок 14 длинной 15000 символов выводился 0.00781894

PHP 4.2.2 как внешний модуль Apache
System - FreeBSD 4.6-STABLE P3-1000

Отчёт работы теста:
Блок 0 длинной 10000 символов выводился 0.00522995
Блок 1 длинной 20000 символов выводился 0.00072503
Блок 2 длинной 30000 символов выводился 0.01086604
Блок 3 длинной 40000 символов выводился 0.0140841
Блок 4 длинной 50000 символов выводился 0.03641308
Блок 5 длинной 60000 символов выводился 0.08528399
Блок 6 длинной 70000 символов выводился 0.29034996
Блок 7 длинной 80000 символов выводился 0.20144701
Блок 8 длинной 90000 символов выводился 0.33344603
Блок 9 длинной 100000 символов выводился 0.73573995
Блок 10 длинной 110000 символов выводился 3.912467
Блок 11 длинной 120000 символов выводился 2.96254098
Блок 12 длинной 130000 символов выводился 3.54025507
Блок 13 длинной 140000 символов выводился 9.90644992
Тест 2
Блок 0 длинной 100000 символов выводился 0.04573202
Блок 1 длинной 200000 символов выводился 0.93989706
Блок 2 длинной 300000 символов выводился 2.80137802
 

aloner

Guest
Никогда не задумывался об этом.
Скорость вывода в Апач слишком уж большая по сравнению со скоростью работы с базой. :)
 

csa

Guest
я правильно понял, тест запускался на хостингах?
может влияние оказывала имевшаяся в тот момент нагрузка на сервак?
мелкие строки успевали за выделенный процессу квант обработаться, а крупным приходилось делить время
 

ONK

Пассивист PHPСluba
Тест запускался и на хостингах и дома, и везде результат похожий, хотя вот один хостинг выделяется в худшую сторону.
Я провёл по несколько тестов, сдесь приведены самые типичные результаты..

Очень интересно как этот тест ведёт себя на других системах,, может кто тестанёт ещё где??
Особенно интересно поведение связки Апач 2.0 + ПХП, так как понятно что проблемма возникакет именно при обмене данными между Апачем и ПХП, может новый Апач лучше работает?
 

csa

Guest
ну тогда покажи результаты домашних тестов
уж слишком разные результаты на примерно одинаковом железе (грубо говоря)
к тому же еще и зависимости весьма странные
вот это например:
Тест 2
Блок 0 длинной 100000 символов выводился 0.18351007
Блок 1 длинной 200000 символов выводился 0.0182159
Блок 2 длинной 300000 символов выводился 0.02775705

если винда выполняет проги по времени обратно пропорционально объему обрабатываемых ими данным, то.... :)
 

csa

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

вот мои результаты (от приведенного тобой скрипта)
Блок 0 длинной 10000 символов выводился 0.00066304
Блок 1 длинной 20000 символов выводился 0.00039792
Блок 2 длинной 30000 символов выводился 0.00095999
Блок 3 длинной 40000 символов выводился 0.00068092
Блок 4 длинной 50000 символов выводился 0.00197208
Блок 5 длинной 60000 символов выводился 0.00091099
Блок 6 длинной 70000 символов выводился 0.00108993
Блок 7 длинной 80000 символов выводился 0.00095701
Блок 8 длинной 90000 символов выводился 0.00129008
Блок 9 длинной 100000 символов выводился 0.00112307
Блок 10 длинной 110000 символов выводился 0.001593
Блок 11 длинной 120000 символов выводился 0.00137508
Блок 12 длинной 130000 символов выводился 0.00185204
Блок 13 длинной 140000 символов выводился 0.00163197
Блок 14 длинной 150000 символов выводился 0.00200903

как видишь имеем зубчатую кривую.
так что тут скорее всего погрешности при получении точного времени

сервак был свободный, без нагрузки
 

ONK

Пассивист PHPСluba
Очень хорошие данные, а какая операционная система, проц, какой Апач, ПХП...??

Мой домашний тест приведён в самой теме, это тот где 2000 винда и ПХП 4.1. ПХП стоит как модуль Апач - а.

Погрешность измерения времени можно исключить, т.к. microtime() скорей всего написан на стандартной библиотеке time.h которавя берёт временные метки из регистров аппаратного таймера системы (cmos).

Кстати протестируй по второму тесту, там где 3 по 100 000...
интересно
 

csa

Guest
rh7.1 p3-700
1.3.26+4.2.2
тока все это фигня :) попробуй вот так написать:
ob_start();
echo "<br>",$out ;
ob_end_clean();
та же картина.. ты ищещь какие-то мифические тормоза :))
а такие дикие цифры у хостеров скорее всего из-за того, что у них процы наверное постоянно загружены
 

csa

Guest
Блок 0 длинной 100000 символов выводился 0.00210702
Блок 1 длинной 200000 символов выводился 0.00334108
Блок 2 длинной 300000 символов выводился 0.00447106
Блок 3 длинной 400000 символов выводился 0.00564194
Блок 4 длинной 500000 символов выводился 0.00691891

а это уже практически линейная зависимость
 

ONK

Пассивист PHPСluba
Если бы мне надо было закешировать вывод, я бы просто объединил сроки и вывел их также как $time_log..

Я тестировал вывод длинных строк, так как это для меня актуально.

Хостёр тут не причём, утечка времени исполнения я заметил на своей машине, при анализе различных блоков кода. Надо будет поставить ПХП 4.2.2, может он действительно хорошо работает. В том тесте что я привёл для ПХП 4.2.2 он установлен как внешний модуль..

Было б интересно увидеть ещё тесты,, пока счёт 3/1.
Один тест можно прзнать приемлимы по времени вывода. Хотелось бы увидить результаты в том числе и с реально работающих серверов, как мои примеры.
 

csa

Guest
попробуй вот такой код:

PHP:
for($j=0;$j<15;$j++){
    $out .= $str;
    $prom_time = $mark10->current_time();
    for($i=0; $i<1000; $i++) echo "<br>",$out ;

    $time_log .= "<br>Блок $j длинной ".strlen($out)." символов выводился ".($mark10->current_time() - $prom_time)/1000;
}
Обычно проводят много измерений, а потом берут среднее
 

csa

Guest
да, пробуй это на маленьких строках, порядка нескольких сотен байт
 

ONK

Пассивист PHPСluba
Блок 0 длинной 10000 символов выводился 0.001145204
Блок 1 длинной 20000 символов выводился 0.0018428006666667
Блок 2 длинной 30000 символов выводился 0.0024347306666667
Блок 3 длинной 40000 символов выводился 0.0030524013333333
Блок 4 длинной 50000 символов выводился 0.0042646013333333
Блок 5 длинной 60000 символов выводился 0.26380786933333
Блок 6 длинной 70000 символов выводился 0.13371086133333
Блок 7 длинной 80000 символов выводился 0.13356053
Блок 8 длинной 90000 символов выводился 0.12921033733333
Блок 9 длинной 100000 символов выводился 0.019928868
Блок 10 длинной 110000 символов выводился 0.10409320133333
Блок 11 длинной 120000 символов выводился 0.14707960333333
Блок 12 длинной 130000 символов выводился 0.150224066
Блок 13 длинной 140000 символов выводился 0.15879539666667
Блок 14 длинной 150000 символов выводился 0.144768866

это при таком коде
PHP:
for($i=0; $i<10; $i++) echo "<br>",$out ; 
$time_log .= "<br>Блок $j длинной ".strlen($out)." символов выводился ".($mark10->current_time() - $prom_time)/10;
Дальше у меня 30секунд..
 

csa

Guest
мда... в системе видать что-то происходило во время теста.....
 

ONK

Пассивист PHPСluba
Вот я и теряюсь в догадках, чётко повторяется ступенчатость, и резкое падение скорости на строке в 60кб. Это на моей машине.
 

csa

Guest
Автор оригинала: ONK
Вот я и теряюсь в догадках, чётко повторяется ступенчатость, и резкое падение скорости на строке в 60кб. Это на моей машине.
думаю, что как раз на 60К у тебя кто-то запускался на машине
попробовал бы ты по максимуму убить процессы в системе, сервисы не нужные остановить
 

csa

Guest
запусти несколько раз этот тест и сравни результат
если провалы будут совпадать, то тогда у пхп точно проблемы
 

ONK

Пассивист PHPСluba
Провалы совпадают с очень высокой вероятностью, тестировал в различных режимах под две сотни раз на своей машине и по десятку раз на хостингах...

Начинал тестирование просто с вывода файла в виде строки, а генератор строк написал для удобства настройки тестов.
 

ForJest

- свежая кровь
Мож ПХП заточен на 64Кб текста? В принципе это размер сегмента вроде...
 

ONK

Пассивист PHPСluba
Незнаю, слишком уж разное поведение различных систем. Я вообще не предпологал что такая проблемма может быть...
 
Сверху