Dubrowsky
Хроники одного дупла
Блогово  →  WebDev  → 

Кэширование отработки модуля в системе на PHP + XML

01 Февраля 2008 года

Представим, что у нас есть система, в которой каждый модуль собирает кусок XML-дерева. Потом результат каким-то образом проворачивается через XSLT-процессор и отдается юзеру. У нас есть желание закэшировать результат работы модуля средствами файловой системы. Собственно, я придумал 3 способа как это сделать и набросал небольшой тестик. Подробности под катом.

Собственно, вот тут можно пощупать работающий тест и поглядеть исходники. Сильно не мучать :) Для теста мы написали модуль testModule, который создает XML-поддерево, содержащее меню. Для простоты данные, из которых формируется меню, мы записали в private-member уже в структурированном виде, но вообще надо представить, как будто они берутся из БД и это типа долго :) Для каждого из способов кэширования я написал cache-класс, который подставляется в модуль. Метод run() модуля сначала пытается получить уже собранный узел от Cache'а, если не получает - формирует узел заново (ну, т.е. у нас просто перегоняет готовый массив в DOM, а в реальности он должен сначала вытаскивать его из базы данных), при этом кэш-класс записывает то, что он должен кэшировать. Действия ("action") модуля выполняются двумя методами: первый собирает структуру (должен называться action_getStructure), второй перегоняет ее в XML (называется action_structure2XML), где "action" - название действия. Если не использовать кэширование структуры, их можно объединить. В нашем примере тестируется единственный action "show_menu", соответственно используются методы show_menu_getStructure() и show_menu_structure2xML(); Теперь о способах кэширования. В классе Cache мы определяем всякие общие операции, типа передачи модуля и действия, с которыми работает кэш. От этого класса наследуются наши тестируемые пациенты: 1. Кэширование структуры, class structureCache Тут мы кэшируем не XML, а собранную структуру объектов/массивов. Соответственно, структура каждый раз вытаскивается из файла, unserialize'ится и перегоняется в DOM вызовом метода action_structure2XML() из кэш-объекта. У этого способа есть одно преимущество: он годится, когда XML должен меняться в зависимости от каких-то параметров. Например, если нужно текущему пункту меню выставить атрибут "is_current" - это делается сразу же при построении поддерева, а в остальных случаях придется уже собранное поддерево модифицировать. 2. Кэширование документа, class docCache В этом случае при кэшировании создается новый пустой DOMDocument. В него импортируется узел, созданный модулем, и сохраняется целиком документ (при этом его documentElement - это как раз корень поддерева модуля). Соответственно, при извлечении данных из кэша XML-данные загружаются в пустой документ, и его корневой элемент импортируется в основной документ. 3. Кэширование фрагмента, class fragmentCache Этот класс работает примерно как предыдущий, но вместо экспорта-импорта узла используется documentFragment. При сохранении кэша вызывается метод saveXML($node) основного документа, где $node - это элемент, сформированный модулем - таким образом можно сохранить в XML-строку отдельный DOMElement (спасибо CatManZero за совет на phpclub.ru - я раньше об этой фиче не знал). При загрузке кэша в рабочем документе создается documentFragment, при помощи метода appendXML в него помещается наше сохраненное поддерево, и кэш-класс возвращает этот фрагмент в модуль. По-хорошему, тут надо бы придумать, как возвращать DOMElement, ну да не так это важно. 4. Прогон без кэширования Для сравнения я добавил один прогон без использования кэша. Для "натуралистичности" в метод action_getStructure() добавлен рассчет 5000! - это чуть меньше 0.002 сек., что примерно соответствует времени выполнения не очень тяжелого SQL-запроса :)


Как организованы тесты можно посмотреть в исходниках. Собственно, выполнение модуля прогоняется по 1000 раз с кэш-объектами разных классов, и еще раз вообще без кэша. Класс Test сохраняет результаты, а затем отрисовывает график при помощи Google Chart API - если кому интересно, могу как-нибудь рассказать подробнее об этой штуковине. Самым быстрым оказался способ с загрузкой через documentFragment. Он же, кажется, самый правильный. Время загрузки при сериализации структуры будет увеличиваться при усложнении дерева быстрее, чем в при других способах. Время работы без кэша сильно зависит от сложности операций при сборке структуры. Если вдруг кто-нибудь повторит это безобразие, используя memcached вместо файловой системы - будет круто :)

Камменты

Mikhail Starovojt03.02.2008, 06:37#
Использовать файловую систему для кеширование - глупо по-умолчанию. Так как чтениею/запись файлов затратная по времени и ресурсам операция.

memcached как минимум.

Мне кажется тест не показательный: надо исключать по возможности процессинг большого кода и оставлять примитивы и их сравнивать на разных серверах и разных запросах.
Николай Дубровскийон самый03.02.2008, 06:57#
Спасибо за комментарий!

Использовать файловую систему для кеширование - глупо по-умолчанию


Например, совсем недавно мне удалось разгрузить VDS, используя кэширование ФС, потратив минимум времени. Да, memcached дал бы лучший результат, но часто нужен не лучший - нужен приемлемый ;) Так что насчет "глупо" не соглашусь.

Кроме того, способ хранения сериализованных данных - это не то, о чем был тест. Собственно, можно было бы читать данные не из ФС, а сохранить в переменной кэш-объекта. Интересовала скорость вставки поддерева разными способами.

надо исключать по возможности процессинг большого кода и оставлять примитивы

А где там большой код-то? :) Взаимодействуют 4 метода 2 классов. На фоне 1К итераций процессинг не занимает ничего.

Впрочем, можно и на примитивах проверить.
Спасибо за тестик, но конечно его не мешало бы подкорректировать
alexf200007.02.2008, 02:51#
Можно пойти на компромисс - использовать файловую систему в памяти, tmpfs. Это гораздо гибче - код будет работать там где нет memcached, а там где есть tmpfs - разницы в производительности практически не будет.
Николай Дубровскийон самый07.02.2008, 15:05#
Анатолий Фролов,
Подкорректирую, есть идеи. Но пока что некогда :(

alexf2000,
Спасибо за наводку. Покурю эту мысль :)
Kseniya06.01.2010, 20:06#
да наводка реально неплоха!

Написать коммент: памятка постеру

 

Крутые посты wtf??? →

27.06.2012 · 37 камментов · рейтинг 8.26
28.04.2008 · 44 каммента · рейтинг 7.65
23.01.2013 · 21 каммент · рейтинг 6.4
28.03.2008 · 24 каммента · рейтинг 5.63
19.01.2008 · 20 камментов · рейтинг 5.11

Последне камменты

11.03.2023  ТЫ ЛОХОткрываем внешние ссылки в новом окне: target="_blank" на JS/jQuery: Я вот позавчера ночью на фейсбуке обозвал всех муд...
26.02.2023  Чего бы еще почитать:Обновленное Блогово - год в эфире!: А где? коментарии ну ладно! порно жопа
24.02.2023  ДубрОткрываем внешние ссылки в новом окне: target="_blank" на JS/jQuery: CRage, "таргет=бланк в коде" - это хорошо, но найт...
14.02.2023  АлинаWinSCP и опция Ignore permission errors: Спасибо!
02.02.2023  Весёлый случайОткрываем внешние ссылки в новом окне: target="_blank" на JS/jQuery: Осталось только поудалять "таргет бланк" через .re...

Статсы