count(*) обойдет по скорости count(id) при условии правильного типа таблицы. Индексы хранятся отдельно. Намек ясен? Выборка поочередно списка столбцов или захват всех - скажется оно по производительности не в пользу второго.
не помню, было ль или нет такое: тест статических методов Код (Text): PHP 5.2.4 (cgi-fcgi) (built: Aug 30 2007 07:06:30) Copyright (c) 1997-2007 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies with the ionCube PHP Loader v3.1.32, Copyright (c) 2002-2007, by ionCube Ltd., and with Xdebug v2.0.5, Copyright (c) 2002-2008, by Derick Rethans PHP: <?php $ts = microtime(true); /* float(0.822402954102) class StaticClass { public static function doSmth($arg) { return 'doSmth' . $arg; } } for ($i = 0; $i < 100000; $i++) { $c = StaticClass::doSmth(': c'); } */ /* float(0.770346879959) class NonStaticClass { public function doSmth($arg) { return 'doSmth' . $arg; } } $obj = new NonStaticClass(); for ($i = 0; $i < 100000; $i++) { $c = $obj->doSmth(': c'); } */ /* float(1.23220682144) class NonStaticClassCalledStatic { public function doSmth($arg) { return 'doSmth' . $arg; } } for ($i = 0; $i < 100000; $i++) { $c = NonStaticClassCalledStatic::doSmth(': c'); } */ var_dump(microtime(true) - $ts);
песок ложкой меряете, на производительности обычно сказывается тупой запрос, который не использует индексы, вызывает full scan, file sort, temporary table, вот это да, сказывается, а милисекунды на разницу подсчета столбцов - х[я пугаюсь неуместного использование матов. Luge]я, тем более, что если место не критичное, то при добавлении 1 поля, придется переписывать еще и код
Желая присоединиться к клубу извращенцев могу сказать, что сам давно гоняю РНР ещё с четвертой версии и не перестаю удивляться. Я написал специальный API для проверки скорости работы разных алгоритмов, этот API выступает в роли непредвзятого эксперта: все тесты выполняются независимо друг от друга с большой частотой и исключает время, затраченное на прокрутку циклов. Тесты можно гонять в двух режимах: учитывая время, затрачиваемое РНР на загрузку и парсинг скрипта и без оного. Пример работы тестера: http://scriptumplus.ru/test.html Пример самого теста: Код (Text): ;число итераций iterations = 100 ;краткое описание теста description = "Чтение файла в массив" ;подробное описание теста text = "Нужно получить массив из файла путем разбивки его построчно. Минус функции file - внутри массива окажутся мусорные \n и \r." ;РНР-файл, который нужно выполнить до теста, но не учитывать время его выполнения (обычно там просто <?php) head = "head.php" ;перечисление самих тестов test[] = "$a=file($file);" test_info[] = "file" test[] = "explode(\"\n\", file_get_contents($file));" test_info[] = "file_get_contents+explode" Пока в разработке и в поиске интересных тестов. Может быть кто-то присоединится, API прост донельзя.
Что-то с циклами напутали. Ничего не делать в цикле нежелательно - это нереальные тесты. Хотя пых уже новый, будет интересно погонять на разных версиях.
Пока я маюсь с уменьшением дисперсии в тестах, всё равно можно сделать правильный вывод. Редко когда используется РНР без оптимизаторов, а по сему однозначно можно сказать что одинарные кавычки будут быстрее, хотя и в "чистом" РНР двойные могут обгонять одинарные. С другой стороны от версии к версии РНР преподносит такие сюрпризы, что не перестаю удивляться по сей день.
а по тесту - одинаково =) кстати я читал тесты где длинные имена переменных ниибово так все тормозили. хз может исправили...
Тест с длинными именами меня обескуражил. Во-первых в РНр без акселератора однобуквенная переменная медленнее двубуквенной (видать хэш-таблицы в пыхе особенные). А включение акслератора показало, что переменная из 60 символов быстрее чем из 6-и. Кстати у меня там второй тест, которые показывает, что двойные кавычки быстрее одинарных
Обновился http://scriptumplus.ru/test.html Выводы всё же такие: - строки в РНР теперь можно использовать как удобно, без разницы какие кавычки, так как разница невелика - большая длина переменной несильно замедляет парсинг - foreach ныне дрючит всех по части чтения массива - count и sizeof и правда алиасы - file_get_contents дрючит всех если надо открыть файл целиком - лучше использовать explode вместо file, так как это позволяет сразу избавиться от символов \n - обратный цикл и правда быстрее прямого на 30%, но с усложнением тела цикла разница сходит на нет А ещё погрешность тестов была под 300%, пока не начал запускать их каждый внутри своего интерпретатора, предварительно погоняв незначащие 6 тестов.
Проверял работу ГСЧ, кроме прочего породился еще один тест: (rand vs. mt_rand) PHP: <?php function ASD ($arr) { $sum = array_sum($arr); $avgx = $sum/count($arr); $narr = array(); for($i=0; $i<count($arr); $i++) { $narr[$i] = pow(($arr[$i]-$avgx),2); } $D = (1/count($arr))*array_sum($narr); echo "Disp ".$D."\r\n"; echo "ASD ".sqrt($D)."\r\n"; } $iters = 100000; preg_match("/\.(\d+) /", microtime(), $res); mt_srand($res[1]); //$a = mt_rand(0,100); $arr = array(); $i = $iters; $mctimeS = microtime(); while(--$i) { $arr[$i] = mt_rand(0,100); $i--; } list($mctF1,$mctF2) = explode(" ", microtime()); list($mctS1,$mctS2) = explode(" ", $mctimeS); echo "Generation time: ".($mctF1-$mctS1+$mctF2-$mctS2); echo " for iter: ".(($mctF1-$mctS1+$mctF2-$mctS2)/$iters)." s\n"; ASD($arr); preg_match("/\.(\d+) /", microtime(), $res); srand($res[1]); //$a = mt_rand(0,100); $arr = array(); $i = $iters; $mctimeS = microtime(); while(--$i) { $arr[$i] = rand(0,100); } list($mctF1,$mctF2) = explode(" ", microtime()); list($mctS1,$mctS2) = explode(" ", $mctimeS); echo "Generation time: ".($mctF1-$mctS1+$mctF2-$mctS2); echo " for iter: ".(($mctF1-$mctS1+$mctF2-$mctS2)/$iters)." s\n"; ASD($arr); ?> Код (Text): Generation time: 0.09532904624939 for iter: 9.532904624939E-7 s Disp 850.28889175313 ASD 29.159713506019 Generation time: 0.089111089706421 for iter: 8.9111089706421E-7 s Disp 846.04118214301 ASD 29.086787071504 Если не кривить душой, то у обоих методов распределение дискретное распределенное, но вот качество у mt_rand значительно выше - еще ни разу в практических задачах не наткнулся на кольцевое замыкание у mt ни под линухой, ни под виндой. У обычного rand такое короткое кольцо, что натыкаешься на него снова и снова. Сравнивал 1/mt_rand(0,mt_getrandmax()) с ГПСЧ Парка-Миллера (кольцо 2,147,483,646 значений для float), был приятно удивлен, распеределение у обоих дискретное распределенное, покрытие равномерное, а даже с делением mt_rand был капельку быстрее. Вывод: используйте mt_rand. По скорости на 8% медленнее, а длинна кольца как у взрослых ГПСЧ. Если нужен супер/мега правильный ГСЧ, используйте mcrypt_dev_rand (преимущества только с юниксоподобными системами, т.к. под виндой эмуляция) А вообще было бы неплохо, когда крутятся тесты, вычислять СКО, потому что если по результатам в 1 сигму помещается общее время выполнения всего теста, то это херня, а не тест. Переведу: если разброс больше времени выполнения, то тестируем скорость записи букв. udp: Поправил косяки, извиняюсь
всегда думал, что rand выдает равномерное распределение и нормальное нужно лишь в редких случаях. Ps ссылка слишком длинная
Магическое быстродействие Всего PHP имеет 13 магических методов. Нет особого смысла тестировать такие специфичные методы, как __sleep и __invoke, т.к. они незаменимы, а вот применения __get и __set в 90% случаев можно избежать, немного усложнив код. Стоит ли овчинка выделки? __set() Код (PHP): <? class A { } $a = new A; for ($i=0; $i<100000; $i++) { $a->$i = 1; }[/php] [code]Выполнено за 0.1124 сек. PHP: <? class A { function __set($n, $v) { $this->$n = $v; } } $a = new A; for ($i=0; $i<100000; $i++) { $a->$i = 1; } [/code] [code]Выполнено за 0.3297 сек.[/code] Магический метод в 3 раза медленнее прямого обращения к свойству. Самое время сравнить с обычным методом: [code=php]<? class A { function set($n, $v) { $this->$n = $v; } } $a = new A; for ($i=0; $i<100000; $i++) { $a->set($i, 1); } [/code] [code]Выполнено за 0.2417 сек.[/code] Обычный метод вдвое медленнее прямого обращения и на 1/3 быстрее "магии". Как сформулировать "__set аж в три раза медленнее" или "прямое обращение всего в три раза медленнее" решайте сами. [b]__get()[/b] [code=php]<? class A { function __get($n) { return null; } } $a = new A; for ($i=0; $i<100000; $i++) { $a->$i; } [/code] [code]Выполнено за 0.1955 сек.[/code] ничотак результат, но что будет без магии? [code=php]<? class A { } $a = new A; for ($i=0; $i<100000; $i++) { $a->$i; } [/code] [code]Выполнено за 3.2733 сек.[/code] Результат предсказуем чуть менее, чем полностью - php вывалил миллион нотисов, что [url=http://www.php.ru/forum/viewtopic.php?p=162482#162482]замедлило выполнение операции в 9 раз[/url]. Поэтому напишм реально альтернативную конструкцию: [code=php]<? class A { } $a = new A; for ($i=0; $i<100000; $i++) { if (isset($a->$i)) { $a->$i; } else {} } [/code] [code]Выполнено за 0.0686 сек..[/code] ну чтож, опять втрое быстрее. Но вам придется городить такую конструкцию везде, где можно было бы обойтись методом __get. Если использовать немагический метод get, то время выполнения оказывается примерно посередине. Плюшки, которые даёт магия перед прямым обращением: - выполнение функции - доступ к приватным свойствам - возможность избежать лишней проверки Плюшки магии в сравнении с обычным методом: - способ обращения как к свойству Каждая "плюшка" стоит 50% производительности =)
Тест на __get плохой. Сделайте в классе property и тестируйте доступ к ней, а не скорость работы isset
ob_start() ... ob_get_clean() вместо конкатенации (vers 2.0) Однажды обнаружил, что конструкция вида ob_start() ... echo ... ob_get_clean() выполняется быстрее вместо множественной конкатенации: Код (Text): <?php // Инициализация счётчиков. $exOne = $exTwo = 0; for ($k = 1000; --$k;) { ## ## Example I: concatenation ## $start = microtime(true); $tmp = null; for ($m = 1000; --$m;) { $tmp .= '-i' . '-t' . '-e' . '-r' . '-a'; } $exOne += (microtime(true) - $start); ## ## Example II: buffered output ## $start = microtime(true); ob_start(); for ($m = 1000; --$m;) { echo '-i', '-t', '-e', '-r', '-a'; } $tmp = ob_get_clean(); $exTwo += (microtime(true) - $start); } ?> <table> <tr> <td>Average of concatenation</td> <td><?= sprintf('%0.6f с', $exOne / 1000) ?></td> </tr> <tr> <td>Average of buffering</td> <td><?= sprintf('%0.6f с', $exTwo / 1000) ?></td> </tr> </table> Результат выполнения (PHP 5.3.10): Код (Text): Average of concatenation 0.000509 с Average of buffering 0.000278 с Результат выполнения (PHP 5.4.3): Код (Text): Average of concatenation 0.000391 с Average of buffering 0.000322 с Однако, в случае малой конкатенации: Код (Text): <?php // Инициализация счётчиков. $exOne = $exTwo = 0; for ($k = 1000; --$k;) { ## ## Example I: concatenation ## $start = microtime(true); $tmp = null; for ($m = 1000; --$m;) { $tmp .= '-i'; } $exOne += (microtime(true) - $start); ## ## Example II: buffered output ## $start = microtime(true); ob_start(); for ($m = 1000; --$m;) { echo '-i'; } $tmp = ob_get_clean(); $exTwo += (microtime(true) - $start); } ?> <table> <tr> <td>Average of concatenation</td> <td><?= sprintf('%0.6f с', $exOne / 1000) ?></td> </tr> <tr> <td>Average of buffering</td> <td><?= sprintf('%0.6f с', $exTwo / 1000) ?></td> </tr> </table> Результат выполнения (PHP 5.3.10): Код (Text): Average of concatenation 0.000095 с Average of buffering 0.000101 с Результат выполнения (PHP 5.4.3): Код (Text): Average of concatenation 0.000088 с Average of buffering 0.000115 с Имел место баг циклов (единая переменная $i), исправил 20.04.2012.
Способ адекватного сравнения __get Заметил одну особенность в PHP 5.3: если свойство объявлено как null, обращение к индексу null[$key] даст null. Вот соответствующий тест: Код (Text): <?php class Sample { public $prop = null; public function __get($name) { return $this->prop[$name]; } } // Инициализация счётчика. $exOne = $exTwo = 0; $a = new Sample; for ($i = 1000; --$i;) { ## ## Example I: __get access. ## $start = microtime(true); for ($m = 10000; --$m;) { $a->$i; } $exOne += (microtime(true) - $start); ## ## Example II: direct access. ## $start = microtime(true); for ($m = 10000; --$m;) { $a->prop[$i]; } $exTwo += (microtime(true) - $start); } ?> <table> <tr> <td>Average of __get access is </td> <td><?= sprintf('%0.6f sec', $exOne / 1000) ?></td> </tr> <tr> <td>Average of direct access is </td> <td><?= sprintf('%0.6f sec', $exTwo / 1000) ?></td> </tr> </table> Результат выполнения (PHP 5.3.10): Код (Text): Average of __get access is 0.006844 sec Average of direct access is 0.001566 sec Результат выполнения (PHP 5.4.3): Код (Text): Average of __get access is 0.006132 sec Average of direct access is 0.000856 sec
Интересует сравнение времени исполнения операции include на системе с SSD в сравнении с HDD, если у кого есть возможность - буду весьма благодарен информации!