Интернет - справочник для веб-мастеров
    441-847-152
     
 
 
php, javascript,ajax,mysql,TIGER CMS
  Для начинающих
php, javascript,ajax,mysql,TIGER CMS
  Общие
php, javascript,ajax,mysql,TIGER CMS
  Безопасность
php, javascript,ajax,mysql,TIGER CMS
  Интересное
php, javascript,ajax,mysql,TIGER CMS
  Новости PHP
php, javascript,ajax,mysql,TIGER CMS
  PHP + AJAX
php, javascript,ajax,mysql,TIGER CMS
  JavaScript
php, javascript,ajax,mysql,TIGER CMS
  Дизайн
php, javascript,ajax,mysql,TIGER CMS
  Раскрутка
php, javascript,ajax,mysql,TIGER CMS
  Заработок
php, javascript,ajax,mysql,TIGER CMS
  Советы

   
 

   
 
  SEO статьи HTML, как раскрутить сайт
1. Рейтинг сайтов

дизайн студия краснодар


 
 
  Всего статей: 405
  Опубликовано: 405
  Проверяються: 0
  Добавлено сегодня: 0
-------------------------------------
  Прочитано статей: 405
  Всего прочтений: 189635
-------------------------------------
  Сейчас читают: 6 чел.


 

Быстрая оптимизация PHP-скриптов (часть 2) [Версия для печати]
Разместил: admin . Раздел: Общие. Опубликовано: 07-25-2007 21:50:15

Циклы: for, foreach, while, count/sizeof() - ускорение 15%-30%

В начале программы создается массив $test из целых чисел (100 000 элементов). Потом один раз запускаются приведенные ниже примеры. Цикл проходит данный массив 3-мя способами (разными циклами) и выполняет кое-какие операции. Не выполнять в цикле ничего нельзя ибо это будет уже совсем нереальный тест.

{$x=0; foreach($test as $n)                          { $x=sprintf("test%08i",$i);        }}
{$x=0; for ($it=0; $it<100000; $it++)                { $x=sprintf("test%08i",$i);        }}
{$x=0; $it=0; while($it<100000)                      { $x=sprintf("test%08i",$i); $it++; }}
{$x=0; for ($it=0; $it<count($test); $it++)          { $x=sprintf("test%08i",$i);        }}
{$x=0; $it=0; while($it<count($test))                { $x=sprintf("test%08i",$i); $it++; }}
{$x=0; $co=count($test); for ($it=0; $it<$co; $it++) { $x=sprintf("test%08i",$i);        }}
{$x=0; $co=count($test); $it=0; while($it<$co)       { $x=sprintf("test%08i",$i); $it++; }}
счетчик кол-во
вызовов общее
вpемя сpеднее
вpемя % от min % от max общее
время 
test N1 1 12.0313 12.0313 154.4% 100.0% 


 
test N2 1 4.7290 4.7290 00.0% 39.3% 


 
test N3 1 4.7712 4.7712 00.9% 39.7% 


 
test N4 1 10.2847 10.2847 117.5% 85.5% 


 
test N5 1 10.3466 10.3466 118.8% 86.0% 


 
test N6 1 9.1271 9.1271 93.0% 75.9% 


 
test N7 1 9.1409 9.1409 93.3% 76.0% 

 

Почему sprintf, а не реальное echo? echo использовать нельзя т.к. от него будет очень большой буфер (OUTPUT в браузер или консоль).

Теперь о деле. Бесспорный вывод - использование foreach сильно тормозит дело, а между for и while большой разницы нет. (На голом тесте for/while/foreach {..} тормоза foreach - 30%). Это не удивительно, т.к. foreach делает копию массива, на что тратиться масса времени (хотя это только слухи).

Вывод о не ассоциативных массивах: 1) foreach существенно замедляет работу 2) использование count() в простых циклах - замедленение 10%. Но на сложных циклах потери от лишних запусков count() будут абсолютно незаметны, так что ситуация не очевидна.

Сравнение count() и sizeof().

Судя по данным руководства - это алиасы. Об этом написано на страницах самих функций и дополнительной странице "Appendex => Aliases list". Что же мы видим на массиве в 100000 элементов:

{$x=0; for ($it=0; $it<count($test); $it++)  { $x=sprintf("test%08i",$test[$it]);}}
{$x=0; for ($it=0; $it<sizeof($test); $it++) { $x=sprintf("test%08i",$test[$it]);}}
счетчик кол-во
вызовов общее
вpемя сpеднее
вpемя % от min % от max общее
время 
test N1 1 3.0087 3.0087 15.7% 100.0% 


 
test N2 1 2.5998 2.5998 00.0% 86.4% 

 

Пусть тесты будут иметь погрешности... Но результат один - count() заметно отстает по скорости от sizeof()! Хм, я бы к записи в руководстве сделал приписку: "The sizeof() function is an alias for count(), but the last is very slow!"

Если кол-во элементов в массиве меньше 65000 (64К), то эти функции по скорости практически не различимы. Тут вывод простой - переходим на использование sizeof(), как ускоренного алиаса count(). Это принесет свои результаты на огромных массивах.

Ассоциативные массивы: тестирование разных способов перебора

С ними наблюдается такая же проблема: на разных по величине массивах разные функции эффективны, но лучше всех foreach!

Массив в 200 элементов и 1000 повторов программы:

{$x=0; foreach($test as $k=>$v) { $x=sprintf("%s=>%s ",$k,$v);                                                           }}
{$x=0; reset($test); while (list($k, $v) = each($test)) { $x=sprintf("%s=>%s ",$k,$v);                                   }}
{$x=0; $k=array_keys($test); $co=sizeof($k); for ($it=0; $it<$co; $it++) { $x=sprintf("%s=>%s ",$k[$it],$test[$k[$it]]); }}
{$x=0; reset($test); while ($k=key($test)) { $x=sprintf("%s=>%s ",$k,current($test)); next($test);                       }}
счетчик кол-во
вызовов общее
вpемя сpеднее
вpемя % от min % от max общее
время 
test N1 1 8.1222 8.1222 00.0% 78.7% 


 
test N2 1 10.3221 10.3221 27.1% 100.0% 


 
test N3 1 9.7921 9.7921 20.6% 94.9% 


 
test N4 1 8.9711 8.9711 10.5% 86.9% 

 

Тоже самое, но массив в 5000 элементов и 200 повторов:
счетчик кол-во
вызовов общее
вpемя сpеднее
вpемя % от min % от max общее
время 
test N1 1 14.4473 14.4473 00.0% 67.2% 


 
test N2 1 18.6801 18.6801 29.3% 86.9% 


 
test N3 1 21.5056 21.5056 48.9% 100.0% 


 
test N4 1 15.8514 15.8514 09.7% 73.7% 

 

Опять тоже самое, но массив в 100 000 элементов и без повторов:

счетчик кол-во
вызовов общее
вpемя сpеднее
вpемя % от min % от max общее
время 
test N1 1 3.5116 3.5116 00.0% 82.8% 


 
test N2 1 3.9724 3.9724 13.1% 93.6% 


 
test N3 1 4.2436 4.2436 20.8% 100.0% 


 
test N4 1 4.0026 4.0026 14.0% 94.3% 

 

Другие тесты на холостых циклах тоже показывают преимущество foreach.

Резюме:
sizeof() лучше, чем count()
в циклах sizeof лучше вообще заменить на переменную
for и while практически не отличимы
для перебора простых индексных массивов нужно использовать for или while
для перебора ассоциативных массивов нужно использотьва foreach

Для чтения файла file() быстрее, чем fopen+цикл - ускорение 40%

Чтобы прочитать в массив $x файл размером 1Мб (100 000 строк по 10 байт) можно воспользоваться двумя вариантами: чтение файла с помощью file(), либо традиционным методом fopen/fgets. Разумеется, для файлов разного объема и содержимого скорость может меняться. Но в данном примере статистика такова: file("1Mb_file.txt") работает на 40% быстрее, чем:

 


   $f=fopen("1Mb_file.txt","r") or die(1);
   while($x[]=fgets($f,1000));
   fclose($f);

Аналогичные варианты:

 


   $f=fopen("1Mb_file.txt","r") or die(1);
   while($s=fgets($f,1000)) $x[]=$s;
   fclose($f);

или

 

   $f=fopen("1Mb_file.txt","r") or die(1);
   while(!feof($f))) $x[]=fgets($f,1000);
   fclose($f);

работают еще медленнее (во втором случае лишняя функция feof() заметно снижает скорость). Тот же тест, но на 15Мб файле (100 000 строк по 150 байт) показывает разницу в 50%, в пользу file(). Тест проводился так, чтобы исключить фоновый своппинг во время работы из-за предшествующих команд создания/чтения таких больших файлов. Подсчитать тоже самое на очень маленьких файлах в 1-2 Кб не представляется возможным, т.к. операцию чтения нельзя повторять в течении одного теста, операции чтения будут кешироваться...

Источник: http://www.softportal.com/   Прочитана 618 раз.
  Закладки:  
     
     
     
Google
 




     
Copyright 2007 by bvisoft.com