Pull to refresh

Вдогонку к предыдущему посту или О разных методах хранения конфигов

Reading time3 min
Views696
Настоящее приложение просто обязано быть конфигурируемым.

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

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

С конфигом связаны две проблемы —
1. Как и где его хранить?
2. Как и откуда его получать?
Взаимосвязь этих проблем прослеживается очень четко, поэтому их можно свести в одну — «Как хранить конфиги?»

INI-файлы


В PHP есть богатый инструментарий для работы с ini-файлами, состоящий аж из двух функций: parse_ini_file() и parse_ini_string().

Предположим, что у нас имеется конфиг из 1000 переменных. Для простоты ситуации будем считать, что секций в ini-файле мы не выделяем.

Для тех, кто захочет повторить тесты, вот пример простейшего кода для формирования тестового файла конфига:
$f = fopen("./test.ini", "w");
for ( $i=1; $i<=1000; $i++ )
fwrite($f, "var_" . $i . " = \"" . md5(rand()) . "\"\n");
fclose($f);


Попробуем определить время доступа к произвольной переменной из конфига с помощью несложного тестового кода:
function getConfigVar($num) {

$config = parse_ini_file("./test.ini");
return $config["var_" . $num];

}

$start = microtime();

for ( $i=1; $i<=1000; $i++ )
$var = getConfigVar($i);

$end = microtime();

list($usec, $sec) = explode(" ", $start);
$start = (float)$usec + (float)$sec;

list($usec, $sec) = explode(" ", $end);
$end = (float)$usec + (float)$sec;

echo $end - $start;


Проведя замеры на тестовом сервере 10 раз и округлив результат я получил 2,67 секунды.

Сериализованные данные в файлах


PHP предлагает нам специальную технологию для хранения произвольных данных любых в текстовых файлах — сериализацию. Для нее существуют две специальные функции — serialize() преобразует данные любого типа в строку, а unserialize(), соответственно, восстанавливает данные из строки.

Создадим тестовый файл с помощью следующего кода:
for ( $i=1; $i<=1000; $i++ )
$data["var_" . $i] = md5(rand());
$f = fopen("./test.serial", "w");
fwrite($f, serialize($data));
fclose($f);

и соответственно изменим функцию getConfigVar:
function getConfigVar($num) {

$config = unserialize(file_get_contents("./test.serial"));
return $config["var_" . $num];

}
, оставив остальной код неизменным.

Проведя замеры 10 раз и округлив результат я получил 1,48 секунды. Выигрыш во времени — почти 2 раза!

Хранение в виде Plain PHP


Однако есть еще один способ, о котором шла речь в моем предыдущем топике. Конфиги можно хранить в виде кода на PHP, а для доступа — использовать конструкцию include().
Давайте посмотрим, даст ли это какой-то выигрыш в производительности?

Код для создания тестового файла конфига:
$f = fopen("./test.conf", "w");
fwrite($f, "<?php\n");
for ( $i=1; $i<=1000; $i++ )
fwrite($f, "\$config['var_" . $i . "'] = \"" . md5(rand()) . "\";\n");
fwrite($f, "return \$config;\n?>");
fclose($f);

Обратите внимание на последнюю строчку создаваемого файла — «return $config;».
Казалось бы — к чему здесь оператор возврата значения из функции? Весь секрет в том, что в PHP инструкция include также, как и функция, умеет возвращать значение, определенное в операторе return включаемого файла. Этот трюк позволит обойтись нам без глобальных переменных.

Тестируем:
function getConfigVar($num) {

$config = include("./test.conf");
return $config["var_" . $num];

}


Результат неожиданный — 5,21 секунды. Я лично думал, что этот способ окажется самым быстрым, однако чуда не произошло…

… а если закэшировать?



А теперь давайте попробуем взять самый медленный способ и применить к нему простейший алгоритм кэширования в памяти. Тестовая функция будет выглядеть так:
function getConfigVar($num) {

if ( !isset($GLOBALS['config_cache']) )
$GLOBALS['config_cache'] = include("./test.conf");

return $GLOBALS['config_cache']["var_" . $num];

}

Результат разительный — 0,054 секунды!

Для справки — первый метод после применения кэширования показал результат 0.052 секунды, второй — 0.051 секунды.

Я думаю, что выводы каждый сделает для себя сам.

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

Все приведенные в статье примеры искусственно придуманы и искуственно упрощены для лучшего понимания.
Tags:
Hubs:
Total votes 13: ↑4 and ↓9-5
Comments34

Articles