Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Самые быстрые настройки для PHP-скриптов.

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: Копипаст полезной статьи.
Invert
Отправлено: 02 Февраля, 2011 - 15:59:39
Post Id



Частый гость


Покинул форум
Сообщений всего: 223
Дата рег-ции: Нояб. 2010  


Помог: 5 раз(а)




Самые быстрые настройки для PHP-скриптов.

Источник: http://habrahabr[dot]ru/blogs/php/112402/
Автор: FrolovS

Наверное, все, кто сталкивался с разработкой более или менее серьезных приложений, знают, что выбор формата хранения настроек скрипта или приложения — достаточно ответственное дело. Конфиги должны быть легко читаемыми, легко модифицируемыми, легко переносимыми, и так далее — список можно продолжать и продолжать.

Так как серверные PHP-скрипты выполняются, бывает, много раз в секунду, скорость загрузки конфигов — достаточно важный параметр. Хотя ему, порой, уделяется не очень много внимания. Давайте сравним различные варианты хранения настроек для PHP-скриптов с точки зрения скорости их работы. Ну и коснемся вкратце их удобства.

Итак, подопытные:
* INI-файлы
* PHP-скрипты
* XML-файлы
* Текстовые файлы
* Файлы с сериализованными данными
* Вне конкурса — PHP-скрипты с define'ами
* JSON-файлы NEW!

Чтобы никого не обидеть, перечисление в алфавитном порядке. Вариант хранения настроек в базе данных, кстати, не рассматривался. Уж слишком невыгодным он выглядит с точки зрения скорости доступа к настройкам.

Условия:
* Как можно быстрее загрузить настройки из файла
* Вернуть массив настроек в виде «ключ» => «значение»
* Конфигурационный файл содержит 10, 100 или 1000 конфигурационных параметров, представляющих собой короткие строки
* Конфигурация читается 1000 раз подряд, замеряется время работы в секундах

Понятно, что со вторым из условий тестирования можно поспорить. Мне этот вариант показался оптимальным для хранения настроек в памяти во время работы скрипта, но в некоторых случаях он таковым не является. И, кстати, этому условию не удовлетворяют PHP-скрипты с define'ами, из-за чего они и были помечены «вне конкурса».

Конфигурацию оборудования не привожу. Понятно, что скорость скриптов зависит от сервера, но в данном случае сравниваются скрипты, а не серверы.

Правда, необходимо сделать небольшое уточнение по поводу программного обеспечения сервера. Использовался реальный веб-сервер, в момент низкой загрузки. Соответственно, конфигурация сервера «боевая»: Linux Debian Lenny, много памяти и RAID1-массив жестких дисков. PHP серии 5.2.x (не самый последний, врочем) с eAccelerator'ом. На время тестов отключался Zend Optimizer, чтобы тесты были более «чистыми», что минимально повлияло на результаты. Тесты без eAccelerator тоже проводились, но, как ни странно, сильно на распределение сил это не повлияло. Причина, на мой взгляд, кроется в том, что eAccelerator настроен на дисковое кэширование опкодов PHP и на сравнение времени модификации файлов, что «съедает» определенное количество времени — хотя и приносит определенные бонусы.



INI-файлы

Результаты: 0.015, 0.086, 0.784

Пример:


Скрипт:
PHP:
скопировать код в буфер обмена
  1. function config($file) {
  2.     return parse_ini_file($file);
  3. }


Конфигурационный файл с классическим, всем знакомым синтаксисом. Достаточно быстрый и удобный способ.




PHP-скрипты

Результаты: 0.029, 0.111, 0.902

Пример:
PHP:
скопировать код в буфер обмена
  1. <?
  2. return array (
  3.   'x1' => '1',
  4.   'x2' => '2',
  5.   'x3' => '3',
  6. );
  7. ?>


Скрипт:
PHP:
скопировать код в буфер обмена
  1. function config($file) {
  2.     return include($file);
  3. }


Сначала маленькая оговорка. Во многих проектах конфигурационный файл не делает return, а просто определяет элементы глобального массива настроек. Это, с одной стороны, не совсем подходило под условия теста, а с другой стороны не совсем идеологически корректно в рамках борьбы против глобальных переменных. Поэтому для сравнения был использован предложенный вариант.

Обратите внимание на то, что этот вариант стабильно проигрывает INI-файлам, хоть и не очень значительно. Что ж, это компенсируется тем, что в настройках можно использовать PHP-выражения, что позволяет сделать конфиги максимально гибкими.




XML-файлы

Результаты: 0.062, 0.385, 3.911

Пример:
CODE (htmlphp):
скопировать код в буфер обмена
  1. <root>
  2.   <x1>1</x1>
  3.   <x2>2</x2>
  4.   <x3>3</x3>
  5. </root>


Скрипт:
PHP:
скопировать код в буфер обмена
  1. function config($file) {
  2.     $r = array();
  3.     $dom = new DOMDocument;
  4.     $dom->load($file);
  5.     foreach ($dom->firstChild->childNodes as $node) {
  6.         if ($node->nodeType == XML_ELEMENT_NODE) {
  7.             $r[$node->nodeName] = $node->firstChild->nodeValue;
  8.         }
  9.     }
  10.     return $r;
  11. }


Недостаток очевидный: очень маленькая скорость работы, в несколько раз медленнее, чем другие варианты. Чтобы проверить, не слишком ли медленная PHP-часть этого кода, я попробовал сделать return сразу после загрузки XML-документа (то есть, фактически, конфигурационные параметры не возвращались). Это ускорило процесс всего приблизительно в два раза. Что подтвердило общий вывод.

Результаты: NEW! 0.047, 0.276, 2.791

Скрипт: NEW!
PHP:
скопировать код в буфер обмена
  1. function config($file) {
  2.     $r = array();
  3.     foreach(simplexml_load_file($file) as $k => $v) {
  4.         $r[$key] = strval($v);
  5.     }
  6.     return $r;
  7. }


С помощью SimpleXML получается, конечно, быстрее. Но не настолько, чтобы претендовать на лидерство.




Текстовые файлы

Результаты: 0.034, 0.250, 2.369

Пример:


Скрипт:
PHP:
скопировать код в буфер обмена
  1. function config($file) {
  2.     $r = array();
  3.     if ($F = fopen($file, "r")) {
  4.         while (($line = fgets($F)) !== false) {
  5.             list($k, $v) = explode("\t", $line, 2);
  6.             $r[trim($k)] = trim($v);
  7.         }
  8.         fclose($F);
  9.     }
  10.     return $r;
  11. }


Не знаю, право, зачем этот способ существует. Возможно, его придумали до того, как изобрели parse_ini_file, или до того, как узнали об этой функции. Не сильно быстрый, не сильно удобный способ.

Результат: NEW! 0.036, 0.250, 2.213

Скрипт: NEW!
PHP:
скопировать код в буфер обмена
  1. function config($file) {
  2.     $r = array();
  3.     foreach (explode("\n", file_get_contents($file)) as $line) {
  4.         list($k, $v) = explode("\t", $line, 2);
  5.         $r[trim($k)] = trim($v);
  6.     }
  7.     return $r;
  8. }


Такой вариант реализации несколько медленнее для небольших файлов и быстрее для больших файлов. Но, в общем, не влияет на расстановку сил.




Файлы с сериализованными данными

Результаты: 0.011, 0.041, 0.309

Пример:
CODE (htmlphp):
скопировать код в буфер обмена
  1. a:3:{s:2:"x1";s:1:"1";s:2:"x2";s:1:"2";s:2:"x3";s:1:"3";}


Скрипт:


Наименее удобочитаемый конфигурационный файл — но при этом самый быстрый результат.




PHP-скрипты с define'ами

Результаты: 0.045, 0.252, 2.404

Пример:


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




JSON-файлы NEW!

Результаты: 0.015, 0.057, 0.495

Пример:
CODE (htmlphp):
скопировать код в буфер обмена
  1. {"x1":"1","x2":"2","x3":"3"}


Скрипт:
PHP:
скопировать код в буфер обмена
  1. function config($file) {
  2.     return json_decode(file_get_contents($file), true);
  3. }


JSON ворвался в нашу жизнь. Его реализация в PHP позволила даже обогнать одного из лидеров, INI-файлы, но немного уступает встроенной сериализации PHP. Одно замечание: приведенный код возвращает не массив, а stdClass object.




Выводыp

Итак, самый быстрый способ чтения конфигов — это чтение сериализованных данных. Работает быстрее остальных, не тормозит на больших объемах данных. Правда, при этом конфигурационные файлы править вручную достаточно сложно.

Если Вы серьезный человек — то избегайте прямого чтения текстовых файлов, особенно с большими объемами. Вместо этого Вам вполне подойдут JSON-файлы или INI-файлы, тем более, что скрипты станут работать быстрее.

Если нужны гибкие настройки, с возможностью применения условий и переменных — то пишите конфигурационный файл на PHP. Работать будет медленнее предыдущих способов, но гибкость настроек в других способах недостижима.

Настройки в формате XML — самые медленные. Прежде, чем их использовать, подумайте хорошенько.

Искренне надеюсь, что define'ы никто не использует, поэтому оставляем их обсуждение вне выводов.

Итог

Итак, что же применить в реальном приложении? Само собой напрашивается применение комбинированного способа хранения настроек. Например, настройки хранятся в виде PHP-скрипта, результаты выполнения которого кэшируются в виде сериализованного массива. Использование такого подхода вместо чтения конфигурационного файла на PHP позволило получить следующие результаты:

Результаты: 0.018, 0.046, 0.317


Оптимально с точки зрения гибкости и скорости, на мой взгляд.

А вот и сам скрипт:
PHP:
скопировать код в буфер обмена
  1. function config($file) {
  2.     $file_dat = "$file.dat";
  3.     if (!file_exists($file_dat) || filemtime($file_dat) <= filemtime($file)) {
  4.         $r = include($file);
  5.         if ($F = fopen($file_dat, "w")) {
  6.             fwrite($F, serialize($r));
  7.             fclose($F);
  8.         }
  9.     } else {
  10.         $r = unserialize(file_get_contents($file_dat));
  11.     }
  12.     return $r;
  13. }


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

P.S. PHP-код в статье не самый хороший. Я писал его, преследуя две цели: краткость и скорость работы. Поэтому отсутствуют комментарии, длинные имена переменных и различные проверки. Кроме того, большая часть кода работает под PHP 4 и 5 без проблем (кроме, конечно, XML). Надеюсь, это не вызовет излишнего накала страстей.
P.P.S. В сравнение добавлен код JSON.
P.P.P.S. Добавлены небольшие ремарки по поводу железа и программного обеспечения. Без них, согласен с авторами комментариев, было как-то не так.
(Добавление)
.
.
.
.

От меня: Думаю самое место для этой статьи тут. Если разместил не в том разделе, прошу переместить в нужный.
 
 Top
Starlord
Отправлено: 04 Февраля, 2011 - 11:48:43
Post Id



Новичок


Покинул форум
Сообщений всего: 50
Дата рег-ции: Окт. 2010  
Откуда: Россия


Помог: 1 раз(а)




Супер, спасибо Подмигивание
(Добавление)
P.S. Лично меня больше всего устраивает способ с использованием INI файла.


-----
Спасибо сообществу php.su за помощь...
 
 Top
Viper
Отправлено: 04 Февраля, 2011 - 13:23:42
Post Id



Активный участник


Покинул форум
Сообщений всего: 4555
Дата рег-ции: Февр. 2007  
Откуда: Симферополь


Помог: 98 раз(а)




Интересная статья. Но все же мне как-то роднее JSON.


-----
Список фильмов с описанием, блекджеком и... для Joomla? -> https://киноархив[dot]com
Демо нового движка для сайта php.su -> php[dot]su, проект на гитхабе
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Обсуждение статей »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB