Неа, я менял местами циклы - всё одно, статика быстрее. И наследование методов работает быстрее объявления.
Возраждаем тему) Навеяно вот этим http://www.php.ru/forum/viewtopic.php?t=21449 Решил проверить, какой способ наиболее быстр. Искать будем тут: PHP: <? $text = 'Диапазон целых чисел (integer) в PHP зависит от платформы (обычно это диапазон 32-битных знаковых целых чисел, то есть от −2 147 483 648 до 2 147 483 647). Числа можно задавать в десятичной, восьмеричной и шестнадцатеричной системах счисления. Диапазон вещественных чисел (double) также зависит от платформы (для 32-битной архитектуры диапазон позволяет оперировать числами от ±1.7×10-308 до ±1.7×10+308). PHP предоставляет разработчикам логический тип (boolean), способный принимать только два значения TRUE («истина») и FALSE («ложь»). При преобразовании в логический тип число 0, пустая строка, ноль в строке «0», NULL и пустой массив считаются FALSE. Все остальные значения автоматически преобразуются в TRUE. Специальный тип NULL предназначен для переменных без определённого значения. Единственным значением данного типа является константа NULL. Тип NULL принимают неинициализированные переменные, переменные инициализированные константой NULL, а также переменные, удалённые при помощи конструкции unset(). Ссылки на внешние ресурсы имеют тип «ресурс» (resource). Переменные данного типа, как правило, представляют собой дескриптор, позволяющий управлять внешними объектами, такими как файлы, динамические изображения, результирующие таблицы базы данных и т. п. Массивы (array) поддерживают числовые и строковые ключи и являются гетерогенными. Массивы могут содержать значения любых типов, включая другие массивы. Порядок элементов и их ключей сохраняется.'; ?> Способ 1. Регулярные выражения. PHP: <? for($i=0;$i<8000;$i++) { preg_match_all("#\d#", $text, $m); $nums = implode('', $m[0]); } ?> Код (Text): 7.38235497475 7.4467279911 7.19334411621 Остальные способы - простой перебор в цикле с различными условиями. Способ 2. PHP: <? for($i=0;$i<8000;$i++) { $nums = ''; for($j = 0, $length = strlen($text); $j < $length; $j++) { if($text[$j] == 0 || $text[$j] == 1 || $text[$j] == 2 || $text[$j] == 3 || $text[$j] == 4 || $text[$j] == 5 || $text[$j] == 6 || $text[$j] == 7 || $text[$j] == 8 || $text[$j] == 9) $nums .= $text[$j]; } } ?> Код (Text): 16.2349131107 17.1354785147 16.4527785241 Способ 3. PHP: <? for($i=0;$i<8000;$i++) { $nums = ''; for($j = 0, $length = strlen($text); $j < $length; $j++) { if(is_numeric($text[$j])) $nums .= $text[$j]; } } ?> Код (Text): 17.8225140572 17.9709398746 18.8869121075 Способ 4. Вариант с массивом ожидаемо оказывается самым тупым. PHP: <? for($i=0;$i<8000;$i++) { $nums = ''; $ar = Array("1", "2", "3", "4", "5", "6", "7", "8", "9", "0"); for($j = 0, $length = strlen($text); $j < $length; $j++) { if(in_array($text[$j], $ar)) $nums .= $text[$j]; } } ?> Код (Text): 34.7916491032 36.6915969849 34.7056632042 Способ 5. А вот вариант с его индексами оказывается наиболее приближенным к регуляркам. з.ы. Справледливости ради надо отметить, что при небольших фразах этот вариант оказывается быстрее, чем регулярки. PHP: <? for($i=0;$i<8000;$i++) { $nums = ''; $ar = Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1); for($j = 0, $length = strlen($text); $j < $length; $j++) { if(isset($ar[$text[$j]])) $nums .= $text[$j]; } } ?> Код (Text): 7.44147801399 7.60429906845 7.7537958622 Итог. Регулярные выражения оказались наиболее быстрым способом "вытаскивания" цифр из строки. Итог для меня довольно неожидан. ps. Если кто надумает, предлагайте свои способы, я наверняка что-то упустил
sorteros Можешь даже не тестировать. Регулярки быстрее во всех нетривиальных обработках текста. Исключение только для простейших операций вроде нахождения строки или подстроки.
Вы чего? регулярные выражения в этой тривиальной задаче совершенно не при чем. Выйгрыш они дают исключительно из-за того, что представляют из себя одну функцию написанную на Си, а не цикл на php Код (Text): Регулярные выражения 0.1 сек Способ 2 3.8 сек Способ 5 0.47 сек ... Функция на Си: 0.008 сек
Проверка скорости циклов (while, do...while, for, foreach) Что-то у меня такое получилось о_О: PHP: <? $i=0; $a=0; $arr = array("0","1","2","3","4","5","6","7","8","9","10"); timer(); while($i<=10) { echo"$i"; $i++; } echo ' <br>While: '.timer().' sec <br><br>'; timer(); do { echo"$a"; $a++; } while($a<=10); echo ' <br>Do...while: '.timer().' sec <br><br>'; timer(); for($a=0;$a<=10;$a++){ echo"$a"; } echo ' <br>FOR: '.timer().' sec <br><br>'; timer(); foreach($arr as $key => $value) { echo"$key"; } echo ' <br>Foreach: '.timer().' sec <br><br>'; ?> Код (Text): While: 4.399999 sec Do...while: 2.299999 sec FOR: 2.299999 sec Foreach: 2.599999 sec While: 4.200000 sec Do...while: 2.400000 sec FOR: 2.299999 sec Foreach: 2.699999 sec While: 4.300000 sec Do...while: 3.199999 sec FOR: 2.599999 sec Foreach: 2.900000 sec While: 4.499999 sec Do...while: 2.399999 sec FOR: 2.399999 sec Foreach: 2.599999 sec Как более правильно проверять скорость работы функций?
Омг, господи... Может не стоит заниматся таким тестированием вовсе? Что проверялось то? Скорость вывода цифр? или что? Код (Text): While: 0.34265089035034 sec Do...while: 0.51998710632324 sec FOR: 3.0228791236877 sec Foreach: 2.1040971279144 sec то же самое в консоли Код (Text): While: 0.16053700447083 sec <br><br> <br>Do...while: 0.19756603240967 sec <br><br> <br>FOR: 0.90979814529419 sec <br><br> <br>Foreach: 0.99230909347534 sec <br><br> PHP: <?php $i=0; $a=0; $arr = array("0","1","2","3","4","5","6","7","8","9","10"); define('CYCLES', 1000000); $start = microtime(true); for($k = 0; $k<CYCLES; $k++) while($i<=10) { $i++; } $end = microtime(true); echo ' <br>While: ' . ($end - $start) . ' sec <br><br>'; $start = microtime(true); for($k = 0; $k<CYCLES; $k++) do { $a++; } while($a<=10); $end = microtime(true); echo ' <br>Do...while: ' . ($end - $start) . ' sec <br><br>'; $start = microtime(true); for($k = 0; $k<CYCLES; $k++) for($a=0;$a<=10;$a++){ } $end = microtime(true); echo ' <br>FOR: '. ($end - $start) .' sec <br><br>'; $start = microtime(true); for($k = 0; $k<CYCLES; $k++) foreach($arr as $key => $value) { } $end = microtime(true); echo ' <br>Foreach: '. ($end - $start) .' sec <br><br>';
Здравствуйте, очень интересует Ваше общее мнение по нескольким вопросам. Самому проверить в данный момент пока нет времени(и опыта) но может для кого то это очевидно и он меня просветит)) 1. Что выгоднее по быстродействию и/или памяти - использования global для доступа к переменным вне функций и методов или использование метода синглтона класса-хранилища, как это реализовано, например, в зендфреймворке? 2. Что выгоднее с точки зрения быстродействия - создать класс и таскать его за собой по системе используя его набор методов как инструмент или создавать экземпляр объекта для каждой отдельной сущности? На примере класса формы - у него есть метод проверить значения и восстановить, например, из пост параметров (возможно еще отфильтровать) и нужно спроектировать его работу. Вариант первый: он будет съедать массив полей и параметров извне и возвращать какой то код/валидность/выполнять отправку/делать запись и будет существовать грубо говоря в одном экземпляре. Вариант второй: для каждой формы создавать новый объект который будет наполняться абстрактными данными (создать поле text, создать поле textarea) и отвечать так же абстрактно. 3. И вопрос на засыпку: для создания объекта насколько мне известно нужно довольно много ресурсов, особенно если речь идет от классе с большим количеством кода - нужно инициализировать всего его члены и методы. Каким образом интерпретатор php тиражирует классы - для каждого экземпляра заново инициализирует все методы и члены или как то более быстро делает объект просто "таким же"? Иначе говоря php сложнее всего инициализирует класс или каждый новый объект этого класса дается ему так же тяжко и, если $obj1 и $obj2 два объекта одного класса, то $obj->method() и $obj2->method() - это две разных "функции" и каждая имеет свое место в памяти? Буду очень благодарен развернутому ответу с объяснениями и примерами, так как это мне бы это помогло съэкономить просто тонну времени ))
1. как тебе удобнее в профессиональном смысле. 2. с точки зрения быстродействия не важно - важно с точки зрения удобства. 3. ты не там ищешь экономию. кодить надо как тебе или команде удобнее и выгоднее, потому, что любой тяжелый SQL положит твою оптимизацию далеко и надолго. во вторых - высоконагруженные приложения строятся совсем по другим меркам, вернее они не зависят от железа. мало мощности? втыкается еще одна железяка и все. код не меняется. в третьих - оптимизировать надо тогда - когда тормозит, а ловля блох - кому она нах нужна?
спасибо! такой ответ мне очень важен тем что подтверждает мою точку зрения - объектно ориентированный подход это удобство за цену равную копейкам производительности в худшем случае.
вот тут я бы посоветовал искать середину, т.к. в ООП можно такого нагородить - монстр получится. ООП это очень тонкий инструмент и пользоваться им надо там, где он нужен а не радии ООП. вообще - задача выбирает инструменты а не наоборот. очень бы хотелось донести именно этот момент до всех.
Чтобы не быть голословным выбрал время и провел несколько замеров. Результаты примерно такие 1. global в 5-7 быстрее цепляет данные, думаю из за 2х промежуточных методов (getInstance(), get()) и проверок на существование в каждом из них. 2. создания объектов в цикле (10000 итераций, зависимость от кол-ва этих итераций во всех случаях получалась линейная) создание обыкновенных массивов PHP: for ($i = 0; $i < 10000; $i++) { $arr[] = array(1); } time: 0.00724411010742 memory: 2386136 создание стандартных классов (взял встроенный ArrayObject) PHP: for ($i = 0; $i < 10000; $i++) { $arr[] = new ArrayObject(); } time: 0.0210390090942 memory: 4034856 создания класса (код класса ~1000 строк кода, но, думаю, не суть) PHP: for ($i = 0; $i < 10000; $i++) { $arr[] = new MyObj(); } time: 0.033038854599 memory: 9474832 Для себя сделал примерно такой вывод - не так страшен черт как его малюют )) Ожидал увидеть разницу в порядках (10-100 раз). Для сравнения - на подключения файла с этим классом потребовалось PHP: require_once('MyObj.php'); time: 0.00677990913391 memory: 455840 (грубо говоря по времени как создать 10000 массивов и памяти как на 10000 ArrayObject) Разница в ресурсах на создание ArrayObject и MyObj - для меня главный аргумент в защиту ООП как подхода. Пускай это ресурсозатратно, зато расширение функциональности уже не влечет за собой каких то скачков. А по поводу использования ОПП согласен на 100%, хотя нагородить монстра используя процедурных подход имхо гораздо проще. Естественно, речь идет о какой-нибудь системе а-ля новый движок сайта (читай очередной велосипед) с которой имеют дело более 1 человека.[/php]
Здравствуйте господа извращенцы? Возьмете меня в свой клуб? Я тут почитал ваши тесты на производительность и наткнулся на сообщение: так вот во мне заиграло любопытство... что быстрее заработает вывод всех 10к записей по 1 запросу Mysql или 10к выводов десяти тысяч записей по очереди... UPD: Провел первый тест - добавление 10к запросов в базу данных потратил 0.343271 времени... код простой PHP: <? set_time_limit(0); require_once('bd.php'); $time_0=microtime(); for ($i=0; $i<10000; $i++) { $sql="Insert into test (name) VALUES ('1')"; mysql_query($sql); } $time_1=microtime(); $time_process=$time_1-$time_0; echo $time_process; ?>
далее модифицировал скрипт и провел тест на вывод 10к запросов из базы данных каждый раз выбирая данные из БД потратил вот сколько времени : 0.167259 кажется что в первом случае времени потратил гараздо больше но вот кода там меньше. на всякий случай код: PHP: <? set_time_limit(0); require_once('bd.php'); $time_0=microtime(); for ($i=0; $i<=10000; $i++) { $sql="select * From test limit 1"; $sql=mysql_query($sql); $sql=mysql_fetch_row($sql); echo $sql[1]."<br>"; } $time_1=microtime(); $time_process=$time_1-$time_0; echo $time_process; ?>
и на последок вывод 10к строк по одному запросу дал следующий неоднозначный результат: 0.106475 0.304437 0.140644 0.075494 0.103298 в среднем получается 10к раз ->0.167259 вывод -> 0.146069 ввод -> 0.343271 код следующий: PHP: <? set_time_limit(0); require_once('bd.php'); $time_0=microtime(); $sql="SELECT id, name FROM test"; $zql=mysql_query($sql); WHILE ($xql=mysql_fetch_row($zql)) { echo $xql[1].$xql[0]; } $time_1=microtime(); $time_process=$time_1-$time_0; echo $time_process; ?> В заключение скажу что количество запросов или обьем выводимой информации мало как влияет на быстродействие. Вконце концов 10000 раз повториить запрос довольно трудоемко так же как за 1 раз вывести 10к строк. Это так же лишний раз доказывает что от переставновки мест слогаемых сумма не меняется.
А тебя не смущает, что ты в первом тесте выбираешь 10к раз одну и ту же первую строчку, а во втором - 10к разных?
Вопросы: Правда ли что один запрос на много значений, быстрее чем много запросов на одно значение? Сильно ли влияет limit на скорость запроса? Результаты: Итоги: 1. Один запрос работает быстрее чем много запросов в цикле (вполне ожидаемо). 2. Limit ускоряет выполнение запроса (тоже вполне ожидаемо). 3. Один запрос работает настолько быстрее, что оправдывается дополнительный цикл обработки результата. 4. PS работает быстрее для вставки. PS работал медленнее для выбора при первом прогоне. При последующих прогонах показал результаты лучше, чем без PS. В "результаты" я скопировал более стабильные данные. Да, я в курсе: http://www.php.ru/forum/viewtopic.php?t=24239 Код: Начало: Код (PHP): <style> * {margin:0px; padding:0px; font-size:100%} .zag {font-weight:bold; margin-top: 1em;font-size:110%} </style> <?php ini_set("max_execution_time","0"); $link=mysql_connect("localhost", "u", "p"); $temp=mysql_select_db("test"); mysql_query("set names utf8"); Все действия с базой разбиты на функции. Вызываются функции так: Код (PHP): ?> <p class='zag'>Вставка в цикле (10000 значений)</p> <?php $arrTime=array(); for ($j=0;$j<5;$j++){ $time=microtime(1); insert(); $timeI=(microtime(1)-$time); $arrTime[]=$timeI; echo $timeI,"<br />"; clear(); } echo "<b>Среднее</b> ",array_sum($arrTime)/count($arrTime),"<br />"; Сами функции: Код (PHP): <?php function insert(){ for ($i=0; $i<=10000; $i++){ $sql="insert into t(num) values($i) "; mysql_query($sql); } } function insertOneQuery(){ $sql="insert into t(num) values(0) "; for ($i=1; $i<=10000; $i++){ $sql .= ", ($i)"; } mysql_query($sql); } function select(){ for ($i=0; $i<=1000; $i++){ $sql="select num from t where num=$i"; $res=mysql_query($sql); $row=mysql_fetch_row($res); $k=$row[0]; } } function selectOneQuery(){ $sql="select num from t where num in (0"; for ($i=1; $i<=1000; $i++){ $sql .= ", $i"; } $sql .= ")"; $res=mysql_query($sql); while($row=mysql_fetch_row($res)){ $k=$row[0]; } } function fullSelect(){ $sql="select num from t"; $res=mysql_query($sql); while($row=mysql_fetch_row($res)){ $k=$row[0]; } } function select10000(){ for ($i=0; $i<=10000; $i++){ $sql="select num from t where num=$i"; $res=mysql_query($sql); $row=mysql_fetch_row($res); $k=$row[0]; } } function selectOneQuery10000(){ $sql="select num from t where num in (0"; for ($i=1; $i<=10000; $i++){ $sql .= ", $i"; } $sql .= ")"; $res=mysql_query($sql); while($row=mysql_fetch_row($res)){ $k=$row[0]; } } function selectLimit(){ for ($i=0; $i<=1000; $i++){ $sql="select num from t where num=$i limit 1"; $res=mysql_query($sql); $row=mysql_fetch_row($res); $k=$row[0]; } } function selectOneQueryLimit(){ $sql="select num from t where num in (0"; for ($i=1; $i<=1000; $i++){ $sql .= ", $i"; } $sql .= ") limit 1000"; $res=mysql_query($sql); while($row=mysql_fetch_row($res)){ $k=$row[0]; } } function selectLimit10000(){ for ($i=0; $i<=10000; $i++){ $sql="select num from t where num=$i limit 1"; $res=mysql_query($sql); $row=mysql_fetch_row($res); $k=$row[0]; } } function selectOneQueryLimit10000(){ $sql="select num from t where num in (0"; for ($i=1; $i<=10000; $i++){ $sql .= ", $i"; } $sql .= ") limit 10000"; $res=mysql_query($sql); while($row=mysql_fetch_row($res)){ $k=$row[0]; } } function clear(){ mysql_query("delete from t"); } function insertPS(){ global $db; $stmt = $db->prepare("insert into t(num) values(?)"); $stmt->bind_param("i", $i); for ($i=0; $i<=10000; $i++){ $stmt->execute(); } } function selectPS(){ global $db; $stmt = $db->prepare("select num from t where num=?"); $stmt->bind_param("i", $i); $stmt->bind_result($k); for ($i=0; $i<=1000; $i++){ $stmt->execute(); $stmt->fetch(); } } function select10000PS(){ global $db; $stmt = $db->prepare("select num from t where num=?"); $stmt->bind_param("i", $i); $stmt->bind_result($k); for ($i=0; $i<=10000; $i++){ $stmt->execute(); $stmt->fetch(); } } function selectLimitPS(){ global $db; $stmt = $db->prepare("select num from t where num=? limit 1"); $stmt->bind_param("i", $i); $stmt->bind_result($k); for ($i=0; $i<=1000; $i++){ $stmt->execute(); $stmt->fetch(); } } function selectLimit10000PS(){ global $db; $stmt = $db->prepare("select num from t where num=? limit 1"); $stmt->bind_param("i", $i); $stmt->bind_result($k); for ($i=0; $i<=10000; $i++){ $stmt->execute(); $stmt->fetch(); } } ?>
Взял на вооружение сей коментарий и провел следующий эксперемент: Модифицировал первый скрипт следующим образом: PHP: <? set_time_limit(0); require_once('bd.php'); $time_0=microtime(); for ($i=0; $i<=10000; $i++) { $sql="select id, name From test where id='".$i."'"; $xql=mysql_query($sql); $zql=mysql_fetch_row($xql); echo $zql[1]." ".$zql[0]."<br>"; } $time_1=microtime(); $time_process=$time_1-$time_0; echo $time_process; ?> провел несколько тестов. И они показали следующие результаты: [sql] 0.510761 0.119496 -0.266093(возьмем за какойнибудь процесс кеширования страницы и не учитываем) незнаю каким чудом но они разные вплоть до того что PHP опережает время О_о если сравнить с пердыдущими результатами то несильно то они и отличаются. (0.510761+0.119496)/2= 0.3151285 > 0.167259 [/sql] Итого полученный результат получается дольше чем в пердыдущем тесте и дольше чем вывести 10к строчек за 1 раз в три раза.
непонимаю причем тут поиск в таблице всего 10000 запрсов и все они так или иначе будут выведены одним запросом с поиском или без него. возможно он просто отнимает время на поиск нужного значения в поле Id но присваивать поиск к запросу где он выводит вю таблицу глупо и нерентабельно =)