Pull to refresh

Поиграем в CacheGraph?

Reading time3 min
Views675
imageПредположим у Вас есть сайт. Предположим вы его оптимизировали по самое «немогу», но всеравно хочеться больше.
Лично мне хотелось, но долгое время не получалось.
Когда я победил тормознутость базы кэшированием запросов, тормознутость блоков — кэшированием блоков, а целые страницы кэшировать я не мог…
Cайт конечно стал работать много быстрее, но начал тормозить уже… мемкэшед?


Сколько у Вас было запросов к базе данных?


Наверное после начала использования кэшеров запросов стало мало.
А сколько у вас запросов к кэшерам?
Дальнейшее относиться только в системам использующим несколько серверов memcached. Если у вас не мемкэшед, либо один сервер — эффект будет минимален.

Немного предыстории


Как говорят философы — все развивается по спирали.
Три года назад я был обычным гейм-девелопером в маленькой студии, 70% времени я просиживал за оптимизацией отлавливая задержки VTunом.
Как известно — одна из главных проблем разработки видеоигр — минимизация DIP. Если по русски — вы что-то рендерите на видеокарте, а процессор при этом ждет синхронизации либо ответа, в общем простаивает…
Получалось что отрендерить монстра на 10к треугольников и на 1к треугольников по времени одинаково.
Существовало много разных путей и хитростей чтобы избежать синхронизации, либо уменьшить задержки…
Один из помощников в этом деле был SceneGraph — дерево рендеринга.
Суть проста — по возможности рендерим похожие обьекты вместе, чтобы между рендерингами изменять поменьше разных переменых.

Прошло три года, сижу я на хабре и читаю как фейсбук пропачил свой мемкешед…
Внезапно глаза зацепляются за выражение… and implement application-level flow control for multi-gets (gets of hundreds of keys in parallel)
Тут меня и зацепило…

Как обычно работают шаблонизаторы?
Берут шаблон и ПО ОЧЕРЕДИ заменяют нужные места значениями которые предварительно ПО ОЧЕРЕДИ были заданы значения.

Представим следующее

<a href='{OBJECT_HREF}'>{OBJECT_LABEL}</a>

и желательно это в цикле раз 100…
Также будем считать что переменные мы берем из кэша.
Это будет мммм 200 запросов?
Если с разными хитрыми тэгами( спасибо еще раз smira ) — то 400+
Если задача не нравиться, и Вы бы весь данный блок положили бы в кэш — тогда давайте будем считать что у нас на странице таких блоков 5, и один вдруг решил перегенериться…

Давайте сделаем рендер нашей странички, как это любят делать движки игр — много проходным
Проход1 — собираем шаблон, собираем использованные ключи, их «места» в шаблоне заменяем на некие якори…
Проход2 — одной пачкой(muti-get) запрашиваем все ключи.
Проход3 — собираем тэги ключей, одной пачкой запрашиваем.
Проход3 — определяем какой кэш жив, какой нет. Для неживых ПАЧКОЙ запускаем проход1

Как это работает


У нас есть 5 блоков, по 100 элементов в каждом.
В проход2 запрашиваем 5 ключей — значения 5ти блоков
В проход3 запрашиваем их тэги( будем считать их больше пяти)
будем считать что два блока expired
Проход3 запускает проход1 для двух блоков. Дальше будет проход 2 который запросит сразу 200 ключей от двух блоков…

Результат — в случае если все блоки «живы» мы заместо 10(5 блоки +5 тэги) запросов делаем 2, по 5 в пачке.
Если кэш блока мертв мы делаем два запроса(100 значения+100 тэги(если они есть)) заместо 200…

Но как бы это обвернуть.
Обвернуть это можно в обычное дерево. В Граф. В CacheGraph.
Обходим дерево, собираем неизвестные ключи, покуда они есть, пачкой запрашиваем и ползем по дереву дальше.
В конце большой str_replace якорей в шаблоне на полученные значения ( либо еще один обход дерева с подставлением значений, как кому нравиться)

Результат — минимизация обращений к асинхронным источникам, минимизация времени ожидания синхронизации и ответа. Ускорение работы.
ОЧЕНЬ серьезное ускорение работы в некоторых задачах

Бонус: если кэшируемые элементы сделать standalone, то дерево можно серилизовать и обходить например С++…
В случае окончания времени жизни кэша можно, опять же пачкой, запустить php с просьбой сгенерить standalone блоки…

Что лично я могу сказать об этом?


Пошел как-то Кащей Бессмертный топиться. Бросился в бурную реку с самого высокого моста… Потом под поезд… Потом спрыгнул с небоскреба… Потом сиганул в бассейн с соляной кислотой… Потом проглотил цианистый калий… Развлекался Кащей, в общем, как мог!
Tags:
Hubs:
Total votes 69: ↑61 and ↓8+53
Comments24

Articles