Начало темы тут
http://otvety.google.ru/otvety/thread?fid=1087e401a3de8214000494ed0f616379&source=email&tid=1087e401a3de8214
Напомню - вопрос был в том, где оптимальнее по скорости хранить кэш шаблонов - в файлах или в БД.
На днях я провёл тестирование, а по сути простое считывание содержимого всего кэша из файлов и из БД, после чего сравнил затраченное время. Так вот. Общее количество файлов составило 173 штуки, суммарная длина их примерно 450 кБ.
Время, потраченное на считывание шаблонов из файлов составило ~ 0.08 секунд;
Время, потраченное на считывание шаблонов из БД составило ~ 0.001 секунд.
Таким образом, в моём опыте время доступа и считывания шаблонов из БД в 80 (!) раз меньше, чем время доступа и считывания из файлов.
Кто-то может это объяснить ?
Примечание:
К_АНТОН:
Я понимаю Вашу логику и в принципе с ней согласен, но факты говорят об обратном.
И одно из объяснений, как мне кажется, заключается в том, что если из файлов приходится считывать всякий раз заново, то таблица БД (однажды считанная из файла) хранится целиком в памяти и, таким образом, доступ к ней намного быстрее, чем к файлу.
И похоже на то, что кэш MySQL не стирается из ОЗУ между запросами PHP.
Примечание:
Хорошо, вечером я кину сюда свой тестовый код, а также повторю опыт на внешнем хостинге.
Примечание:
Добрый вечер. Сперва приведу тестовый код, затем напишу результаты тестирования на реальном хостинге.
class upgTest extends uCustomObject {
function onAfterChild() {
$t1 = microtime(true);
$i = 0;
$this->getDv($_SERVER['DOCUMENT_ROOT'].'/testt/', $i); // В этой папке свалены все файлы шаблонов проекта
$t2 = microtime(true);
echo 'FILESYSTEM = '.($t2 - $t1).'<br>'; // Выводим сколько времени потратили на перебор всех файлов
$q = 'select id from `testtab`';
$res = $this->sql($q);
foreach ($res as $d) {
$q = 'select txt from `testtab` where id = "'.addslashes($d['id']).'"';
$rr = $this->sql($q);
$this->testWork($rr[0]['txt']);
}
$t3 = microtime(true);
echo 'MYSQL = '.($t3 - $t2).'<br>';
}
function getDv($dirpath, &$i) {
$dir = new RecursiveDirectoryIterator($dirpath);
while ($dir->valid()) {
$file = $dir->getFilename();
if (($file != '.') && ($file != '..')) {
if (is_dir($dirpath.'/'.$file)) {
$this->getDv($dirpath.'/'.$file, $i);
} else {
$pfile = $dirpath.'/'.$file;
// Load file and process
$str = file_get_contents($pfile);
$this->testWork($str);
}
}
$dir->next();
}
}
function testWork($str) {
echo strlen($str).'<br>';
}
}
Тест запускается вызовом метода onAfterChild(). Файлы перебираются итеративно, для каждого файла в выходной поток пишется длина его содержимого (по идее это должно гарантировать, что содержимое из файла считывается).
Те же самые файлы записаны в таблице testtab: id, path, txt; в txt хранится полное содержимое каждого файла. Сперва мы читаем список id-шников, затем перебираем в цикле все id-шники, вытаскиваем содержимое и точно так же выводим длину содержимого.
Хочу сказать, что при тестировании на локалхосте я накосячил в прошлый раз, поэтому скорость MySQL была "слегка" завышена. Реальные данные для локалхоста таковы
LOCALHOST test
----------------------
FS MySQL
0,080 0,045
0,079 0,042
0,080 0,037
0,081 0,046
то есть всегда имеем скорость с БД почти в 2 раза выше, чем с FS.
Теперь аналогичные данные с реального виртуального хостинга.
VIRTUAL HOSTING
-----------------------------
FS MySQL
0,028 0,055
0,029 0,012
0,027 0,012
0,057 0,016
0,040 0,007
0,028 0,015
Как мы видим, зависимость приблизительно сохраняется - в подавляющем большинстве случаев MySQL в два раза быстрее FS.
Отсюда я делаю вывод:
чтение файлов шаблонов из MySQL в испытуемых системах как правило в 2 раза быстрее, чем чтение из файловой системы. Однако, в других случаях (например, когда БД находится на другом физическом компе) возможна обратная ситуация.
Кажется, для себя я обрисовал следующий план действий:
1. Делаю кэширование шаблонов в БД.
2. Делаю флаг, переключив который в конфиге можно сделать кэширование в файловой системе.
Какие будут комментарии, уважаемые программеры ?
Примечание:
2 Yorie:
Да, данная строка меня слегка насторожила. Поэтому я провёл очень много рефрешей, в том числе и с перерывами и с посещением других страниц (чтобы забить кэши другой инфой), однако подобных данных получить повторно не удалось.
Кэш шаблонов в моём случае - это массив, который движком обрабатывается и оттуда разная инфа берётся для построения внешнего вида компонента. В одной из недавних тем я просил совета по поводу разных способов хранения этого массива с целью выяснить максимально шустрый способ
http://otvety.google.ru/otvety/thread?tid=457115638a48ba60&table=%2Fotvety%2Fuser%3Fsort%3Dwsmopts%26order%3Dwsnod%26start%3D0%26userid%3D06573115922173826867%26tab%3Dwtmtoa
как мы выяснили в итоге, лучше всего хранить не код, который deeval'ить потом, а сериализованный массив. Именно так я и буду делать.
Примечание:
2 Yorie:
Возможно, результаты тестов в вашем случае обусловлены тем, что вы читаете из файла не всё содержимое, а только первую строку (используя fgets() ). Попробуйте считывать файл в строку функцией file_get_contents().
P.S. Отчасти этим может объясняться и такая разница по памяти.
Примечание:
2 NetRain:
Загрузить, конечно, можно. Вот только тонкость в том, что загрузка может пагубно повлиять и на файловую систему и на MySQL-сервер. И предсказать какие реальные условия будут, наверное, невозможно....
Насчёт memcache - идея отличная, я её уже думал, просто на виртуальных хостингах оно обычно отсутствует.