Вы не зашли.
Тесты производительности различных часто употребляемых конструкций PHP кода и отдельных функций.
Для тестов использовался скрипт прилагаемый к этой статье
http://wapinet.ru/textbook/speed.htmТестировалось на PHP 5.2.4 + Apache 2.2.4 + WinXP SP2 (Denwer 3)
Задача: просмотр содержимого папки.
Результаты
Код:
span style="color: #0000BB"><?php// 10000 проходов// и так 5 раз// 7.0788// 7.2023// 7.4333// 7.0996// 7.1290$dir = "./";$scan = scandir($dir);foreach($scan as $f){//print $f;}---// 7.3640// 7.4306// 7.3660// 7.4751// 7.2902$dir = "./";$open = opendir($dir);while(($f = readdir($open)) != false){//print $f;}closedir($open);---// 7.9307// 8.1111// 8.4703// 8.0594// 8.3077$dir = "./";$hand = dir($dir);while(($f = $hand->read()) != false){//print $f;}$hand->close();---// 53.0054// 53.6093// 52.9707// 53.2398// 53.3150$dir = "*";$glob = glob($dir);foreach($glob as $f){//print $f;}?> |
// print $f - закомментированно для более точных результатов тестирования
glob вне конкуренции
данная функция работает НАМНОГО медленнее остальных, тестировавшихся.
Остальные более-менее равны по производительности. Встроенный класс
dir работает, как видим, чуть медленнее, видимо сказывается ООП.
Продолжение следует...
Отредактировано Gemorroj (2008.03.22 10:10)
Код:
span style="color: #0000BB"><?php// 250000 проходов// 4.0472// 3.9551// 3.9555// 3.9487// 3.9205$test = null;if($test == null){// print $test;}// 3.9390// 3.9610// 3.9629// 3.9878// 3.9631$test = null;if($test == ''){// print $test;}// 3.9386// 3.9192// 3.9468// 3.9178// 3.9390$test = null;if($test === null){// print $test;}// 3.5278// 3.5305// 3.7416// 3.6181// 3.5312$test = null;if(!$test){// print $test;}// 7.3735// 6.6924// 6.6803// 6.7138// 6.9515$test = null;if(empty($test)){// print $test;}// 7.0340// 6.7897// 6.8383// 6.7610// 6.8296$test = null;if(isset($test)){// print $test;}?> |
Интересный момент, не точная проверка на соответствие, в данном тесте, выполняется столько же, сколько и точная (== и ===).
Так же код с применением
isset или
empty работает заметно медленнее, это связано с тем, что вызываются
функции, а в остальных случаях для проверки работают
операторы сравнения, которые по определению быстрее.
Из всех приведенных примеров кода, быстрее работает код с применением отрицания (
!)
Отредактировано Gemorroj (2008.03.22 12:12)
вот еще интересная инфа, взята из комментариев к CURL функциям на php.net
Calculating 50 queries to http://www.flickr.com/.
cURL took 9.550734 seconds.
file_get_contents() took 10.878360 seconds.
Calculating 50 queries to http://www.yahoo.com/.
cURL took 4.729566 seconds.
file_get_contents() took 10.443786 seconds.
Calculating 50 queries to http://www.ebay.com/.
cURL took 46.348250 seconds.
file_get_contents() took 52.685604 seconds.
Calculating 50 queries to http://www.godaddy.com/.
cURL took 1.505460 seconds.
file_get_contents() took 37.154304 seconds.
Calculating 50 queries to http://www.php.net/.
cURL took 13.136836 seconds.
file_get_contents() took 17.981879 seconds.другими словами CURL неизбежно быстрее чем file_get_contents
#4.
Helqg
Off
(2)
Участник
2008.03.22 12:12
А проверка на пустоту empty()?
Стране нужны автобусы!
да, точно
не подумал, щас исправлюсь)
#6.
Helqg
Off
(2)
Участник
2008.03.23 09:09
Да просто я всегда ей проверяю, хотелось бы быть уверенным в ее использовании.
Стране нужны автобусы!
сравнивал
mysql_fetch_assoc, mysql_fetch_array и mysql_fetch_rowтестировал следующим образом, 1 раз запускается этот код
Код:
span style="color: #0000BB"><?php// Хост, логин, пароль$con = mysql_connect('localhost','root','') or die ('Ошибка подключения к базе данных!');// Кодировкаmysql_query('SET NAMES `utf8`');// Имя БДmysql_select_db('gbs',$con);$q = mysql_query('SELECT * FROM `users`');?> |
в таблице
users 183 записи, состоит из 22 колонок.
далее 250000 раз запускалась одна из тестировавшихся функций.
вот что в результате имеем
Код:
$a = mysql_fetch_row($q); |
4.9316 |
4.9642 |
4.9255 |
5.0077 |
4.9354 |
|
$a = mysql_fetch_assoc($q); |
5.1141 |
5.0620 |
5.1188 |
5.0473 |
5.0907 |
|
$a = mysql_fetch_array($q); |
5.1535 |
5.1544 |
5.2150 |
5.1027 |
5.2089 |
Если с
mysql_fetch_row и mysql_fetch_assoc все более-менее понятно (
mysql_fetch_row чуть быстрее, т.к. создает нумерованный массив, а не ассоциативный), то почему
mysql_fetch_array практически не уступает
mysql_fetch_assoc не совсем понятно. Ведь
mysql_fetch_array создает целых 2 массива, и как мне казалось должна прилично уступать по скорости. Ан нет. Как это обьяснить без понятия.
#8.
Helqg
Off
(2)
Участник
2008.04.20 21:09
там написанно не 2 массива, а массив с двойными индексами. Че это такое меня спрашивать не надо.
Стране нужны автобусы!
Теперь Win XP
SP3 Вобщем страшное дело...
Код:
span style="color: #0000BB"><?php// 250000 проходовif(1)print '';/*2.81532.87822.92932.78122.81512.79462.82552.85112.82742.8898*/if(1){print '';}/*3.23253.22893.29253.23093.21443.26043.36183.24813.22013.2240*/?> |
воооот...
даже не знаю что сказать( расстройство прям ='(
для 25 тысяч не фатальна 1 секунда
Стране нужны автобусы!
250 тысяч
но сам факт...
250!!! А собственно нафига они там скобки то...
Стране нужны автобусы!
ну так для меня удобнее. без скобок для меня код становится абсолютно не читабельным. да и сами разработчики PHP рекомендуют использовать скобки везде. а вот на деле со скобками медленне получается код(
Кстати про читабельность. Ща прочитал- "Perl был основан на awk sed grep, и других средствах UNIX , и в результате при работе с перл часто получается код только для записи( то есть через несколько месяцов вы его понять не сумеете)." А ты про скобки
Стране нужны автобусы!
извечный спор, что быстрее,
print или
echo 500.000 проходов
Код:
span style="color: #0000BB"><?phpprint '';/*1.03411.04261.04401.03851.0431*/echo '';/*0.84390.83790.84870.83680.8507*/?> |
вот такие результаты)
значит echo быстрее)
ska ska ska
#17.
AntiKiller
Гость
2008.08.01 00:12
Я тут на сайтик наткнулся... Gemorroj, глянь... http://www.phpbench.com , если с инглишом дружишь(я думаю что дружишь
), почитай там... если не дружишь(или кто ещё глянет сайтик не знающий инглиша, перезагрузи страницу которая откроется пару раз...)..........
Ага, здорово. Особенно поразило на сколько быстрее код если подсчет кол-ва итераций вынести из цикла. А так же использование функций для работы с массивами
array_keys() / array_values()
Кто-то просил потестить скорость работы операторов
AND, &&, OR, ||.
Результаты приводить не буду, т.к. разницы в скорости вообще не заметил. 100.000 проходов с любым из этих операторов занимало около 1.6 секунды.
Код:
span style="color: #0000BB"><?php//150.000 проходовiconv_substr('1',1);//1.8843//1.8550//1.8388//1.8268//1.8288mb_substr('1',1);//1.7029//1.6956//1.6940//1.7172//1.6928substr('1',1);//1.6691//1.6661//1.6394//1.6151//1.6076?> |
Как видно, шустрее всех substr, потом mb_substr и самая медленная iconv_substr
При чем, чем входящая строка больше, тем разница ощущается сильнее.
Вообще не совсем понятно, помему библиотеки (iconv и mbstring) имеющие по большей части одинаковое предназначение разделены на 2 библиотеки.
Интересно было бы сравнить ещё и while, do while, for и foreach
Да я знаю эти тесты от Бородина, но интересно будет ещё тесты именно на Windows XP SP3
Теперь PHP 5.3
файла не существует
error_reporting(0);
file_get_contents("xxx");
16.7541
17.4581
17.4037
14.7361
14.7268
@file_get_contents("xxx");
17.8958
16.7447
16.2829
14.8839
14.8261
а теперь ставим error_reporting(2039);
50.000 проходов
file_get_contents("xxx");
294.0389
@file_get_contents("xxx");
7.6748
такое получается из-за забивания буфера ошибками.
#25.
JInn
Off
(2)
Участник
2009.04.12 17:05
Я где то читал что при использовании знака @ код работает медленне в 7 раз... Врут?...
Как все таки сложно быть ботом...
я тоже такое читал, поэтому и решил проверить. В случае с file_get_contents выходит врут.
#27.
JInn
Off
(2)
Участник
2009.04.12 18:06
А можешь проверить с этим же значком, только истинное утверждение? Возможно в том случае, если не будет никаких ошибок, результаты будут другими?
Как все таки сложно быть ботом...
10.000 проходов
file_get_contents(__FILE__);
// 6.7937
// 6.9678
// 6.5534
// 6.8022
// 6.7107
@file_get_contents(__FILE__);
// 7.1111
// 7.2268
// 6.8919
// 7.0816
// 7.0639
да, действительно, если файл существует, то подавление ошибок с помощью собаки замедляет работу.
#29.
JInn
Off
(2)
Участник
2009.04.19 16:04
Примерно 0.3 секунды за 10000 проходов. Не так существенно, как говорят, но все равно прилично
Как все таки сложно быть ботом...
Сегодня пол дня воевал со следующим SQL запросом
Код:
SELECT DISTINCT `links`.`id` , `links`.`id_user` , `links`.`link` , `links`.`link_text` , `links`.`timeout` , `links`.`timeout_ip` , `links`.`timeout_ip_browser` |
FROM `links` , `users` |
WHERE `links`.`id_user` <>0 |
AND `links`.`16_17` = "1" |
AND `links`.`sunday` = "1" |
AND `links`.`in` >0 |
AND `links`.`on_off` = "1" |
AND `links`.`comp` = "1" |
AND `users`.`ban` = "0" |
ORDER BY `links`.`id` DESC; |
Требовалось оптимизировать... Результатов выборки без DISTINCT примерно 80.000 с DISTINCT примерно 150.
Так вот скорость мягко говоря удручает. Более 2-х секунд на средненьком сервере.
Решилось следующим образом
Код:
SELECT `links`.`id` , `links`.`id_user` , `links`.`link` , `links`.`link_text` , `links`.`timeout` , `links`.`timeout_ip` , `links`.`timeout_ip_browser` |
FROM `links` , `users` |
WHERE `links`.`id_user` <>0 |
AND `links`.`16_17` = "1" |
AND `links`.`sunday` = "1" |
AND `links`.`in` >0 |
AND `links`.`on_off` = "1" |
AND `links`.`comp` = "1" |
AND `users`.`ban` = "0" |
GROUP BY `links`.`id` |
ORDER BY `links`.`id` DESC; |
Совсем небольшие изменения в коде, а запрос выполняется примерно за 0.2 секунды. В принципе тоже не ахти, но прогресс все равно очень заметный. В 10 раз.
#31.
JInn
Off
(2)
Участник
2009.05.06 03:03
Вот еще вопрос. Вывод текста с переменными. Есть три варианта.
1 - echo "text $aaa text";
2 - echo 'text '.$aaa.' text';
3 - echo "text ".$aaa." text";
В первом варианте интерпретатор должен проверять весь текст на $ и пробел, что и замедляет процесс. Это типа ищет переменную.
Во втором варианте проверка не идет (процесс быстрее), но используется конкатенация (даже две), что по идее должно замедлять процесс.
Третий вариант из области антивариантов и "Так писать не надо", так что его можно не иметь ввиду.
Собственно вопрос в том, какой из вариантов, 1 или 2, работает быстрее? Для чистоты эксперимента текст должен быть в двух вариантах. Небольшим - до 50 символов и большим - до 300 символов. Это связано с первым вариантом, там потому что поиск идет. В принципе может кто то и так знает результат?
Как все таки сложно быть ботом...
#33.
JInn
Off
(2)
Участник
2009.05.06 18:06
Посмотрел... Скажем так - я в шоке... К тому, что увидел могу добавить, что
$x="test ".$test." test ".$test." test ".$test;
быстрее на 10% чем
$x="test ".$test." test ".$test." test ".$test."";
то есть если последнюю переменную не закрывать, то это хорошо. Не смог правда проверить с одинарными кавычками
Как все таки сложно быть ботом...
PHP 5.3.1
30 тысяч проходов
Код:
span style="color: #0000BB"><?php// 0.5504// 0.5523// 0.5499// 0.5622// 0.5541$a = 1;switch($a){ case 2: break; case 3: break; default: break;}// 0.4459// 0.4513// 0.4421// 0.4456// 0.4510$a = 1;if($a == 2){}else if($a == 3){}else{}?> |
Добавлено спустя 7 минут 18 секунд: JInn написал:
Посмотрел... Скажем так - я в шоке... К тому, что увидел могу добавить, что
$x="test ".$test." test ".$test." test ".$test;
быстрее на 10% чем
$x="test ".$test." test ".$test." test ".$test."";
то есть если последнюю переменную не закрывать, то это хорошо. Не смог правда проверить с одинарными кавычками
а что здесь шокирующего? нафига делать эту лишнюю конкатенацию с пустой строкой?
Интересно, но как по мне, ради этого не стоит избегать switch, ведь там возможно без break; подключить сразу несколько условий, да и визуально кода немного меньше)
Желание стать программистом из-за того, что вам нравляться компьютерные игры-это все равно, что желание стать гинекологом из-за того, что вам нравиться секс
Akdmeh, да, зачастую switch удобнее. Но если скорость критически важный параметр, то приходится жертвовать удобством. Я на этот switch обратил внимание когда профилировал Gmanager. Оказалось что одна совсем ничем не примечательная функция определения расширения файла, занимает приличную долю ремени. Тем более что вызывается несколько раз в цикле. Пришлось отказаться от switch и переписать на if / elseif / else. Немного, но прирост производительности это дало.
Конечно, в циклах это бывает важно.
Кст, сравни у себя mb_substr и iconv_substr - интересно что у тебя выйдет.
Желание стать программистом из-за того, что вам нравляться компьютерные игры-это все равно, что желание стать гинекологом из-за того, что вам нравиться секс
ок
Кстати, сейчас искал самый быстрый способ прохода по папке, без подпапок. Вероятно это достигается следующим способом:
Код:
span style="color: #0000BB"><?php$arr = array_diff(scandir('directory/', 0), array('.', '..'));?> |
Пробовал в т.ч. новые итераторы, но с ними как минимум в 3 раза медленнее.
iconv_substr быстрее примерно на треть.
100000 проходов
Код:
span style="color: #0000BB"><?php// 3.5349// 3.6812// 3.6436$a = "";iconv_substr($a, 0, 6, "UTF-8");// 5.7895// 5.8432// 5.8222$a = "";mb_substr($a, 0, 6, "UTF-8");?> |
Такая же ситуация, если переменной $a присвоить какую-нибудь длинную строку.
Нужно отметить, что многое зависит от кодировки. Если у mb_substr стоит какая-нибудь однобайтовая кодировка, а у iconv_substr мультибайтовая, то естественно mb_substr выиграет.
#40.
AND
Off
(11)
Участник
2009.11.06 22:10
MySQLi. Запрос с подготовленным выражением и без него.
Код:
span style="color: #0000BB"><?php$db = new Mysqli('localhost', 'root', '', 'test') or die('Can not connect to MySQL');$prepare = true;$integer = 1234567890;$string = 'dgjmnvyuoplhgdenjhtrmnfqskytkgoyhjkdfmdigjewruytgrehguhksjgijerpoiwhgjeijgewyewyhlnjkbgsyigbvydbwg';$start = microtime(true); if($prepare) { $stmt = $db->prepare('INSERT INTO test (`integer`, `string`) VALUES (?, ?)'); $stmt->bind_param('is', $integer, $string); for($i = 0; $i < 10000; $i++) { $stmt->execute(); } $stmt->close(); // 10000 проходов // 5.50247 // 5.46265 // 5.59152 // 1 проход // 0.00141 // 0.00125 // 0.00172}else { for($i = 0; $i < 10000; $i++) { $db->query('INSERT INTO test (`integer`, `string`) VALUES ('.intval($integer).', "'.$db->real_escape_string($string).'")'); } // 10000 проходов // 6.11369 // 6.08014 // 6.16883 // 1 проход // 0.00082 // 0.00106 // 0.00067}echo round(microtime(true) - $start, 5);$db->close();?> |