Итак, проснулся я в хорошем настроении и решил наконец-то облегчить жизнь тем людям, которых раздражает кол-во запросов к базе у Друпала 5 при переводе. Для Друпал 4.7 я уже такое делал, пришла очередь пятого. Итак, без патча к сожалению не обошлось, можно и не надеяться.
файл common.inc
<?php
function t($string, $args = 0) {
global $locale;
//////////////////////////////////////////////////////////////
if (function_exists('locale_static') && $locale != 'en') {
$string = locale_static($string);
}
else
///////////////////////////////////////////////////////////////
if (function_exists('locale') && $locale != 'en') {
$string = locale($string);
}
if (!$args) {
return $string;
}
else {
// Transform arguments before inserting them
foreach ($args as $key => $value) {
switch ($key[0]) {
// Escaped only
case '@':
$args[$key] = check_plain($value);
break;
// Escaped and placeholder
case '%':
default:
$args[$key] = theme('placeholder', $value);
break;
// Pass-through
case '!':
}
}
return strtr($string, $args);
}
}
?>
Добавлены строчки, которые между вот такими полосками - ///////////////////////////////////////////////////////////////.
C патчами закончили. Приаатачиваю МОДУЛЬ, никаких теперь левых конвертеров
PS Как вы понимаете, модуль сырой и не особенно тестированный, так что просьба сбрасывать сюда вопросы и найденные баги и фичи.
Вложение | Размер |
---|---|
locale_static-5.x-1.1-dev.tgz | 2.48 КБ |
Комментарии
прошу простить мне мою лень, ставить новый сайт на локалхост долго.. дальнейший перевод через веб-админку друпала доступен? Если доступен, то куда переводы сохраняются, в бд?
Привет Самаре из Ульяновска)
да , всё что было, всё остаётся и переводы и заливаются в базу, только можно потом уже из базы сгенерить текстовый файл, из которого и будут браться переводы... Привет Ульяновску!!
Спасибо, красиво так получилось.
С алиасами так не выйдет - при большом количестве ссылок - файл будет большой.
Да, и перегенерацию перевода можно делать по крону.
О... спасибо, давай номер VISA баксов кину!
А от чего у тебя настроение поднимается ?
Там вот грозились функцию (system back) по замене в файлах t() на rassian вариант "накрапать", там может я тебе просто настроение подниму, раз ты такой умный и умелый ?
Спасибо! Спасибо! Спасибо! *убежала пробовать*
Интересно, действительно ли наблюдается прирост производительности при такой конфигурации?
Дело в том, что Друпал при генерации страницы единоразово грузит строки длиной менее 75 символов в память (в статический массив). Таким образом, для большинства вызовов функции t() обращений к базе не происходит. В основном нагрузка на БД происходит при работе в админке, т.к. длинные строки используются именно там.
Только что прикрутил на недоделанный сайт.
До включения / после (для админского входа)
главная - 4026.77ms / 1514.49 ms
статья - 1284.4ms / 1177.86 ms
(Чем бы еще раз в десять ускорить?
переписать t() на C я бы попробовал )
А несколько раз в разное время проверить? А собрать среднюю статистику? Как будет вести себя на загруженном сайте?
Скорее всего в данном случае разница с очень большой погрешностью. И репрезентативность практически 0...
Как говориться: "геморрой не стоит этих свеч"...
> переписать t() на C я бы попробовал )
Переписать - дело не хитрое. А дальше что?
IMHO тут в основном играет разница в скорости работы php и БД. У меня такое подозрение, что у моего хостера на 6 хостинговых серверов всего один сервер БД.
Могут быть и ещё и не такие дикие комбинации Посему - всё это хорошо только в теории и $5 решат многие проблемы с производительностью.
В любом случае - самое быстрое это то, что лежит в файлах both with or without t() , значит если основной russian надо менять все там на русский, а дальше у кого что, быстрей работает, либо перевод с файлов либо из базы, но что-то есть большие априорные сомнения, даже при отсутствие репрезентативности и хорошей корреляции, что запрос на каждый t() к базе есть быстрее чем из файлов SQL хорошо "держит" нагрузку - график растет медленно, не первичная нагрузка для обращения даже к одной записи есть достаточно ощутимая величина, а таких запросов и так часто по поводу перевода - не такие задачи задумывалось решать с помощью SQL...
On вт, 24/07/2007 - 13:14 sas@drupal.org says:
но что-то есть большие априорные сомнения, даже при отсутствие репрезентативности и хорошей корреляции, что запрос на каждый t() к базе есть быстрее чем из файлов
так нет же там запроса к базе на каждый t(). Один раз оно грузит все мелкие строки и потом ищет их в ассоциативном массиве. Лезет в базу только если не находит, и опять-таки, помещает найденное в массив, т.е. не более одного обращения к базе для строки.
Для сравнивающих производительность: считайте отдельно анонимов и залогиненных, и учитывайте, включен ли page cache
Один раз оно грузит все мелкие строки и потом ищет их в ассоциативном массиве.
Ух ты ... наверно не маленький массив ? А сколько интересно ему места надо, а если Вы сведущи то наверно знаете в что в этом "не маленьком" массиве и много чего еще помещается - "светлая" картина получается, да и только
sas@drupal.orgО... спасибо, давай номер VISA баксов кину!
А от чего у тебя настроение поднимается ?
Вот от таких предложений точно подымается.... Реквизиты в профиль кинул...
Ххочется услышать рационализаторские предложения, чего не хватает в модуле.....
Да, и кстати, у кого -нить работает Хук uninstall - я так и не смог его заставить заработать - глянул, он вообще не работает, у модуль aggregator вписано удаление таблиц при анинсталле - нифига не удаляет
On вт, 24/07/2007 - 15:52 sas@drupal.org says:
Ух ты ... наверно не маленький массив
в сериализованном виде в таблице cache массив занимает 215Кб с учетом того, что у меня грузятся строки до 90 байт включительно.
В любом случае это меньше, чем подгружать всю локализацию из файла. Насчет того, что быстрее, как уже говорил - не знаю.
Что касается помещается-не помещается, то важнее не "чтобы помещалось", а чтобы помещалось то, что чаще требуется. Только в этом случае общая производительность сможет вырасти.
Полный перевод от Vadbars занимает - 641 Kb, значит идут выгрузки - загрузки и обращения к базе.
Про "выгрузки-загрузки" - не понял, что это. А обращения к базе - идут, но не для каждой страницы - а по мере необходимости, не более того.
Касательно размеров: 641К - это только ядро, а еще переводы модулей - в хорошем сайте на мегабайт потянет
Вытаскивать это по мере надобности из базы или грузить при каждом обращении к странице - вопрос философский. Если жить на выделенном сервере, то наверное файловый вариант получше будет...
Но поскольку практика - критерий истины, я бы все-таки опирался на результаты сколько-нибудь продолжительного тестирования
Интересно, а можно както-то так сделать, чтобы в файл выгружались только переводы front-end, а back по-прежнему из базы брался? Или вообще английским остался.
конечно можно.
Можно почти все
Напильник в руки и... Или как-то можно авоматизировать?
файл и так весит не ахти , у меня 600кб при кол-ве полей в базе более 5000 - так что не понимаю стенаний по поводу большого размера файлов. По поводу кэша - не знаю, но вроде народ мерит производительность и она выросла , потому что у наших хостеров самое уязвимое место - это именно база, а не php - на это то всегда хвата ресурсов...
> у наших хостеров самое уязвимое место - это именно база, а не php
И как будто специально в подтверждение этого тезиса мой хостер около полуночи устроил время загрузки первой страницы сайта на Друпале >50 секунд. В то же время в другом окне броузера я вносил записи в каталог другого сайта, там же хостящегося, но сделанного на самопальном движке (два запроса к базе на страницу) - всё летало.
а как можно выложить модуль на Drupal.org ? Кто-нибудь выкладывал? Какой механизм в деталях? Выложат ли модуль в репозиторий при наличии патча ядра, кто как думает? Просветите, плиз, кто выкладывал или знает.....
По слухам, где то в профиле есть ссылка - отправить письмо с заявкой и обоснованием ...
Включил модуль у себя на сайте. Довольно шустро стало работать по ощущениям. Конечно, тесты хорошо бы было провести, но они что-то не вызывают доверия. Спасибо за модуль, прошлым я тоже пользовался. Хорошо бы написать Readme или что-то вроде инструкции по применению.
"а как можно выложить модуль на Drupal.org ? Кто-нибудь выкладывал? Какой механизм в деталях? Выложат ли модуль в репозиторий при наличии патча ядра, кто как думает?"
Это к vadbars'у, он может выкладывать, и больше всего об этом знает...
Здесь вот вся информация: http://drupal.org/contribute/development
Сначала надо получить CVS-аккаунт: http://drupal.org/cvs-account
Модуль выложат, там много модулей делают, которым патчи необходимы. Тот же Advanced Cache.
Спасибо, полезная штука
Кстати, вроде в 6-м друпале обещали как то сделать по другому локализацию
Если Друпал установлен в подпапке (не в корне сервера), то нужно заменить в locale_static.module:
$dir=$DOCUMENT_ROOT=$_SERVER['DOCUMENT_ROOT'].'/'.file_directory_path();
на
$dir=$DOCUMENT_ROOT=dirname($_SERVER["SCRIPT_FILENAME"]).'/'.file_directory_path();
Влад Савицкий
ага, согласен, спасибо,поправил
Вавилов Евгений, вы молодец.
Я еще не пробовал, но сама идея сделать нормальный способ хранения локализации, давно напрашивалась.
Не понимаю как друпаллеры с орга сами до этого никак не дойдут.
Давно сделан и работает
думаю, описание патча или правильный patch надо в архив приложить
Axel предлагал строки прямо в код вшивать, чтобы быстрее было. Мне кажется, что написать такой скриптик, который из РО-файла пропишет в код несложно. Чем такой вариант будет уступать статичному файлу перевода?
Я ещё раз настоятельно не рекомендую такой подход. Такие радикальные средства имеют смысл очень редко. Для повседневного применения для разгрузки БД будет идеален модуль сделанный jason32, либо адаптация gettext.
В своё время под некоторые версии 4.x делал патчи для использования библиотеки gettext.
Плюс gettext: можно без изменений использовать po-файлы переводов поставляемые с модулями. При индексации (создание mo-файлов) скорость поиска строк не хуже, чем для php-инклюдов. Минусы: нет возможности правки перевода через вебинтерфейс - только правкой po-файлов. Минусы решения предлагаемого locale_static: больше расход памяти, т.к. переводы из файла при include полностью затягиваются в память каждый раз.
Есть пара рац. предложений.
1. Сохранять в файл только те строки, которые менее N символов длиной, остальное грузить из базы. Достигая компромисса между размером файла и обращениями к базе.
2. Слегка изменить сам формат создаваемого php-файла, можно уменьшить его размер на 3-5%.
или использовать serialize/unserialize, которые работают быстрее, однако размер файла в таком случае увеличится примерно на 10%.
3. Использовать кэш. Если искомой строки нет в кэше , то она считывается из базы и добавляется в кэш-массив. Теоретически, через какое-то время активного пользования сайтом, он должен содержать самые часто используемые строки. Можно сохранять в файл именно их. Хотя в данном случае файл скорее всего будет не нужен, по-сути он и есть кэш.
В 6ке сделано так:
1. Если перевода нет, обращамся к базе и считываем все строки из кэша
2. Если их нет, считываем все строки длиной менее 75 символов и загоняем в кэш
3. Если искомой строки в массиве нет, считываем ее из базы (Здесь бы неплохо еще добавить эту строку в кэш, но в коде drupal этого не реализовано)
4. Если ее и там нет, значит вставляем ее непереведенный прототип в базу и очищаем кэш (хотя логичнее было бы добавить ее туда)
В 5ке примерно также, но есть неоптимизированные места вроде вызова locale_refresh_cache в locale
В общем логика была и есть одна - грузить в кэш все, что меньше 75 символов.
Так что грешить на множественные запросы к базе из-за модуля locale несправедливо.
В большинстве случаев запрос к переводам(к кэшу) на сессию один.
И заменять его считыванием 600-1000 килобайтным файлом, который php еще должен распарсить, мне кажется сомнительным удовольствием.
Я бы пошел по пути накопления в кэше статистически чаще используемых строк, а не строк длиной менее 75 символов, как сделано в drupal, хотя это тоже вопрос спорный.
А вообще все уже сломано до нас.
Пакет патчей advcache кэширует потенциально ресурсоемкие места, такие как конвертация путей в синонимы и обратно, поисковые запросы, таксономию, узлы, форум, комменты.
Патч File-based caching содает кэш в файлах, вместо базы.
Модуль boost позволяет создавать статические страницы в html.
Кто-нибудь пробовал сравнивать производительность кэша на БД и файлах ?
На мой взгляд, хранение кэша в базе не целесообразно, т.к. это просто блочные данные, без всякой структуризации.
В общем, может кого-нибудь заинтересует, идея locale_static вдохновила меня создать include
-based cache, как замену стандартному api кэша drupal.
Идея такова: все кэшируемые данные преображаются в статический php-код и сохраняются в файлах, которые затем загружаются директивой include. Т.к. php все включения держит в памяти, то ускорение заметно.
Таким образом, кэшируются переводы, таксономия, карта синонимов, меню и все что использует cache api.
пока провожу тесты
На первый взгляд скорость генерации страниц админки по сравнению с кэшем в БД возросла на порядок.
Думаю это будет верно при большом кол-ве оперативки и наличии eacceleratora
Нужно очень внимательно подходить к вопросу что кешировать!
имхо, например для ноды нужно хранить рендер тизера и тела, а коменты и ссылки хранить отдельно и генерить - они зависсят от прав доступа как и меню
Что кэшировать, думаю отслеживать по ключу и таблице, которые в качестве параметров передают использующие кэш, функции.
Загвоздка возникла в функции cache_clear_all, которая по маске ключа, очищает соответствующие записи в выбранной таблице кэшей.
Т.к. имя файла = некая функция(имя ключа, имя таблицы), то всякие маски и вилдкарды реализовать не просто. Пока, при удалении любого элемента кэша в любой таблице, очищается он весь, что сказывается на производительности.
По поводу сериализации:
В апи 6го drupal, кэш реализован более грамотно, в качестве данных ему передается не строка сериализованных данных, как в 5м, а сами данные.
И только в случае, если их тип не является строкой, происходит сериализация.
serialize/unserialize ресурсоемкие функции, особенно это заметно на массивах в 600-1000 кб.
В случае кэша на файлах, сериализация становится ненужной. В 6ке достаточно заменить cache.inc, в 5ке пришлось убрать serialize/unserialize во всем коде.
А вообще, с кэшем в друпале жесть какая-то. Зачем-то насоздавали однотипных таблиц, в каждой из которых различные группы модулей кэшируют данные со своими ключами.
Путаница получается и усложнение кода.
Логика конечно понятна, одна таблица - один файл. Когда ключей в таблице переваливает за некую отметку, дабы производительность при выборке кэша не упала, создаем новую таблицу.
Я конечно не спец, но по-моему, это от незнания sql. Есть всякие ключи, индексы, можно было б хотя бы создать отдельную таблицу ассоциаций ключ-номер.
По поводу таблиц - есть предположение, что это сделано специально, чтобы lock table который вызывается при записи в кеш не блокировал весь кеш, а только часть, иначе это станет "бутылочным горлышком", а так как кеш например для страниц очищается достаточно часто - получение переменных и меню будут ждать, пока очистится/обновится таблица - оно и так притормаживает на большой посещаемости!
lock table на самом деле не нужен для одиночной записи в базу. Что можно видеть на примере 6ки, там строки db_lock_table($table); db_unlock_tables(); убрали из кода.
Как написано в комментариях к cache_set, это сделано
1. для более быстрых выборок/вставок.
2. для разделения часто обновляемых и статичных данных.
3. якобы query кэш mysql работает лучше с множеством мелких статичных таблиц.
мне кажется, тут есть спорные моменты. как-то можно было по-другому. Не жесткое определение таблиц усложняет управление таким кэшом.
Может быть найдутся желающие испытать кэш на вложениях, поэтому привожу результат.
Модифицированный файл cache.inc для drupal 5
Установка: распаковать и скопировать cache.inc поверх существующего в папке includes. Вручную создать папку files/cache.
Настройки не требует, никаких своих ключей в базе не создает.
Данные в файлах кэшируются не все подряд.
То, какие таблицы кэшировать в файлах, а какие в базе, определяют ключи массива $keys в функции filecache_enabled.
По-умолчанию в файлах кэшируются таблицы cache,cache_node, cache_path, cache_taxonomy, остальные - как обычно, в БД.
Патч экспериментальный, возможны недоработки.
Но в любом случае, он поможет понять, как работает кэш, что следует вынести в файлы, а что оставить в базе данных.
Пожелания и сообщения о багах приветствуются.
Спасибо, интересно
Интересная статья появилась на Lullabot
Действительно простой способ перекрыть локализацию своим методом, актуально и для 5 и 6 версий
так такой же и реализован, просто специально усложнён... Или я что-то не понимаю.....