А если локализация Друпала без базы?

Главные вкладки

Аватар пользователя jason32 jason32 7 сентября 2006 в 11:27

Мда, отследил я , сколько запросов идет от Друпал к базе с переводом( да и основным текстом) и ужаснулся.На главной например у меня подсчитывает 560 запросов, и это еще только пока, так как никакого функционала ещё нет. Как же это серверы то терпят? А если 2000 пользователей? Что, никто не пробовал перевести это всё из базы в текстовые файлы? Кто нить пробовал и не вышло или никто и не пытался? Если я это сделаю - это кому-нибудь тут понадобится? Костыль, конечно, я посмотрел - там переписать пару функция да пару конвертеров изобразить простеньких - из .ро файлов .Это пока никто из программеров не добрался до Друпала или все скрывают ?

Комментарии

Аватар пользователя dyp@drupal.org dyp@drupal.org 7 сентября 2006 в 12:22

Обсуждалось уже.
http://drupal.ru/node/2118
Переводы кэшируются.
Некоторые правда переводят прямо в модулях.
Ходят слухи что axel делал модуль для переводов без баз. Но он молчит.
http://drupal.ru/node/2118#comment-9637

Аватар пользователя jason32 jason32 7 сентября 2006 в 13:31

Да темка интересная, спасибо за ссылку. Я провел один простой эксперимент - подсчитать, куда же в основном в смысле таблиц в базе лазиет Друпал.И выяснилась достаточно странная вещь - больше всего запросов даже не на locale идет ( хотя там запросы двойные - то есть сразу одним запросом в две базы лезет), а на url_alias - по 60 запросов за раз, хотя у меня счас алиасов этих всего 12.Вотгде поле для улучшения.Для примера статистика некоторых страниц( моя, а не devel? который нихрена не считает)
главная -

Quote:
(кол-во запросов к таблицам,относящимся к нодам)count sql-node: 80
(кол-во запросов к таблицам,относящимся к locale)count sql-locale: 0
(кол-во запросов к таблицам,относящимся к кэшу)count sql-cache: 16
(кол-во запросов к таблицам,относящимся к url)count sql-url: 85
(кол-во запросов к таблицам,относящимся к категориям) count sql-
category: 37
остальные обращения к базе) count other: 46
( всего запров) count sql-all: 264

добавить категорию
Quote:
count sql-node: 111
count sql-locale: 5
count sql-cache: 6
count sql-url: 82
count sql-category: 71
count other: 59
count sql-all: 334

добавить Запись в дневнике
Quote:
count sql-node: 111
count sql-locale: 4
count sql-cache: 6
count sql-url: 81
count sql-category: 72
count other: 59
count sql-all: 333

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

P.S Подсчитывалось всё втупую, путем правки кода.
Считалось кол-во обращения в функцию _db_query($query, $debug = 0) из
database.mysql.inc , которая собственно и делает запросы. Там проверялся запрос на содержания имен баз.

Аватар пользователя dyp@drupal.org dyp@drupal.org 7 сентября 2006 в 14:10

Quote:
а на url_alias - по 60 запросов за раз

генерируется функцией l(). C ее помощью формируются все ссылки в друпале кроме тех которые сделанны напрямую через html. если в баз ть хоть один алиас будут запрашиавться все если нет, то небудет.
Как придумаете поделитесь.

Аватар пользователя jason32 jason32 7 сентября 2006 в 14:41

чё тут думать - лезть в код и править
файл [b]path.inc[/b]
Вместо

 function drupal_init_path() {
  if (!empty($_GET['q'])) {
    $_GET['q'] = drupal_get_normal_path(trim($_GET['q'], '/'));
  }
  else {
    $_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage', 'node'));
  }
}

ставить

function drupal_init_path() {
        global $map_alias;
   $c=count($map_alias);
        if (empty($c))
        {              
         $sql = "Select src,dst FROM {url_alias} ";
         $res=db_query($sql);
    while( $row=db_fetch_array($res))
    {  
          $map_alias[$row['src']]=$row['dst'];
        }
  }
  if (!empty($_GET['q'])) {
    $_GET['q'] = drupal_get_normal_path(trim($_GET['q'], '/'));
  }
  else {
    $_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage', 'node'));
  }
}

вместо

function drupal_lookup_path($action, $path = '') {
  static $map = array();
  static $count = NULL;
  if ($count === NULL) {
    $count = db_result(db_query('SELECT COUNT(pid) FROM {url_alias}'));
  }
  if ($action == 'wipe') {
    $map = array();
  }
  elseif ($count > 0 && $path != '') {
    if ($action == 'alias') {
      if (isset($map[$path])) {
        return $map[$path];
      }
      if ($alias = db_result(db_query("SELECT dst FROM {url_alias} WHERE src = '%s'", $path))) {
        $map[$path] = $alias;
        return $alias;
      }
      else {
        $map[$path] = $path;
      }
    }
    elseif ($action == 'source') {
      if ($alias = array_search($path, $map)) {
        return $alias;
      }
      if (!isset($map[$path])) {
        if ($src = db_result(db_query("SELECT src FROM {url_alias} WHERE dst = '%s'", $path))) {
          $map[$src] = $path;
          return $src;
        }
      }
    }
  }
  return FALSE;
}

ставим

function drupal_lookup_path($action, $path = '') {
        global $map_alias;
  static $map = array();
  if ($action == 'wipe') {
    $map = array();
  }
  elseif ($path != '') {       
    if ($action == 'alias') {
      if (!isset($map_alias[$path])) $map_alias[$path]=$path;
      return  $map_alias[$path];        
    }
    elseif ($action == 'source') {
      if (is_array($map_alias) and $alias = array_search($path, $map_alias)) {
        return $alias;
      }
      else   return False;
    }
  }
  return FALSE;
}

В итоге получаем один запрос к базе вместо 60-70.

Аватар пользователя kiev1 kiev1 10 октября 2006 в 4:38

А что на Drupal.org говрят по этму поводу - если так все просто - то это серьезный баг в друпале - представьте - 70 лишних запросов на страницу - не думаю что там такой ляп пропустили...
в общем отправил на http://drupal.org/node/88544 - посмотрим что скажут

Аватар пользователя mozaic mozaic 5 марта 2008 в 5:40

Решил попробовать Ваше решение в 6-1 версии Друпала - и вот что получается: 1-й кусок кода можно заменить - он без изменений, а вот во втором есть изменения - там добавилась еще $path_language = '' и т.д.

Можете переделать ваше решение для 6-й версии?

Заранее спасибо ...

Аватар пользователя jason32 jason32 7 сентября 2006 в 15:52

Мда , переводы кешируются, ага, только не всегда, они там сбрасываются, вот при сложном редактировании контейнера обнаружил новый рекорд:

count sql-node: 21
count sql-locale: 580
count sql-cache: 51
count sql-url: 2
count sql-category: 16
count other: 49
count sql-all: 719

719 запросов, из них 580 - locale.
Для того, чтобы сработало на локалке на pentium 2.8 - пришлось увеличить max_execution_time( Максимальное возможное время выполнения сценария ) до двух минут.

Аватар пользователя rgb rgb 7 сентября 2006 в 17:22

Quote:
Мда , переводы кешируются, ага, только не всегда, они там сбрасываются,..

Когда чего-то на сайте меняется (админом, в основном), то все кэши (или часть их) сбрасываются. Но ведь это не штатный режим работы сайта? Т.е. основную часть времени - они (кэши) используются.

Про max_execution_time: да, есть такое дело.

Аватар пользователя coyote coyote (не проверено) 7 сентября 2006 в 16:15

Сделал такое, в local.module исправил ф-ю local на

function locale($string) {
        // Задаем текущий язык проекта
        putenv("LANG=ru_RU");

        // Задаем текущую локаль (кодировку)
        setlocale (LC_ALL,"ru_RU");

        // Указываем имя домена
        $domain = 'messages';

        // Задаем каталог домена, где содержатся переводы
        bindtextdomain ($domain, "./locale");

        // Выбираем домен для работы
        textdomain ($domain);

        // Если необходимо, принудительно указываем кодировку (эта строка не
        // обязательна, она нужна, если вы хотите выводить текст в отличной от
        // текущей локали кодировке).
        bind_textdomain_codeset($domain, 'UTF-8');

  return _($string);
}

В корне друпала создаю папки locale/ru_RU/LC_MESSAGES/
в папку LC_MESSAGES ложим .po и .mo файлы с переводом. Вроде работает, и базу за переводом не лезет.

Аватар пользователя jason32 jason32 7 сентября 2006 в 16:40

Quote:

…правда с множественными формами глючит, может кто доделает.

Поясни, что имеется ввиду - не очень пока привык к терминологии

Аватар пользователя coyotle coyotle 7 сентября 2006 в 16:50

Не переводит слова в множественном числе.
Например показывает "На данный момент в онлайне 0 users, 0 guests."
а если все слова в единственном числе пишет нормально "На данный момент в онлайне 1 пользователь, 1 гость."
Или "1 неделя 6 days назад", "2 weeks 1 день назад"...
Не разобрался как работать с множественными формами.

Аватар пользователя rgb rgb 7 сентября 2006 в 17:13

Quote:
Сделал такое, в local.module исправил ф-ю local на...

Замечтально, только зачем же putenv() .. bind_textdomain_codeset(..) при каждом-то запросе? Может лучше тогда добавить в locale.module обработку hook_init() и туда запихнуть инициализацию?

Ну и если пошла такая пляска... Вот сюда ещё можно глянуть: может оказаться ползным. Это модуль для Дрюпала 4.6, который и реализует перевод через gettext. Правда статус этого молуя - "экспериментальный".

Аватар пользователя jason32 jason32 8 сентября 2006 в 9:30

Quote:
вот кстати чувак тоже озадачился алиасами, я правда не разобрался в чем суть, но может поможет

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

Аватар пользователя jason32 jason32 8 сентября 2006 в 9:35

Quote:
Когда чего-то на сайте меняется (админом, в основном), то все кэши (или часть их) сбрасываются. Но ведь это не штатный режим работы сайта? Т.е. основную часть времени - они (кэши) используются.

Это смотря какого сайта.Сайты с активным коммьюнити как раз и нагрузят этот кэш мама не горюй

Аватар пользователя rgb rgb 8 сентября 2006 в 9:55

Quote:
Сайты с активным коммьюнити как раз и нагрузят этот кэш мама не горюй

Возможно. Я пока не изучал этот вопрос...

Аватар пользователя dyp@drupal.org dyp@drupal.org 8 сентября 2006 в 10:40

Quote:
Да он тоже самое сделал, только несколько хуже

а нельзя этот код впихнуть в ядро, если он лучше. Или есть какие-то грабли?

Аватар пользователя jason32 jason32 8 сентября 2006 в 11:34

Quote:
а нельзя этот код впихнуть в ядро, если он лучше. Или есть какие-то грабли?

Да ради бога, впихивайте - предложите разработчикам,я по английскому не говорю.

Аватар пользователя jason32 jason32 8 сентября 2006 в 12:10

Quote:
Возможно. Я пока не изучал этот вопрос…

А вообще - какого чёрта кеш в базе делает? Это то чья была светлая идея? В чём смысл?

Аватар пользователя rgb rgb 8 сентября 2006 в 23:00

Quote:
А вообще - какого чёрта кеш в базе делает...

Чья идея - думаю можно узнать подняв архив переписки разработчиков и ознакомившись с историей изменения исходников Wink

Отчего кэш в БД? Могу предположить, что разработчикам:

  • не хотелось бороться с ограничениями ОС и файловой системы
  • хотелось сделать более переносимую и масштабируемую реализацию
  • хотелось получить гибкость в управлении кэшем (вспоминаем cache_clear_all('menu:', TRUE); например)

Ну и к тому же БД и так используется, так что кэш в БД - это не очень большие дополнительные расходы при таком раскладе (повторюсь: тут мне надо ещё разобраться - а вдруг окажется, что файловые операции будут вообще медленее?! не забываем про всякие-разные проверки наличия, доступа, про блокировки...)

Подчеркну, что это мои измышления (IMHO, то есть...)

Кстати, а Вы не смотрели в сторону проекта файлового кэша? (не помню как модуль называется..) и ещё на drupal.org есть раздел, о том, как переводить страницы в статику и кэшировать их таким образом. Не пробовали? (Ссылок не дам - лень сейчас искать Lol

Аватар пользователя kiev1 kiev1 10 сентября 2006 в 1:36

Где-то я читал что Dries говорил что выигрыш по сравнению с базой не стоит тех сложностей так как блоки все равно из базы берутся и для зарегистрированных пользователей тоже все из базы, правда не учитывали локализацию.

Аватар пользователя jason32 jason32 11 сентября 2006 в 9:16

Quote:
Где-то я читал что Dries говорил что выигрыш по сравнению с базой не стоит тех сложностей так как блоки все равно из базы берутся и для зарегистрированных пользователей тоже все из базы, правда не учитывали локализацию.

Выход вижу один - отключать locale ( чтоб всё бралось через include() ) и заодно( это второй этап, менее очевидный)вырубать кеш, потому что всё равно предполагается, что в основном на сайте зарегистрированные пользователи будут.

Аватар пользователя B.X B.X 25 сентября 2006 в 21:42

[b]чё тут думать - лезть в код и править
файл path.inc[/b]

так как это рабочий хак? на самом деле уменьшает запросы к БД? или он ещё экспериментальный и не работает нормально?
[b]Добавлено:[/b]
на самом деле работает... очень быстро стало всё обрабатываться... странички прямо за мгновение открываются... тормоза исчезли при добавлении постов... класс...

Аватар пользователя PC_M@niac PC_M@niac 30 сентября 2006 в 16:43

Странные результаты показывает модуль devel Smile
До установки патча на главной странице было 326 запросов за 87мсек и 3.3с на всю страницу.
После установки стало 210 запросов за 84 мсек и 3с на всю страницу.
Странно не то что слабый эффект дало а то что визуально страница стала открываться как минимум в два раза быстрее! Сайт почти без графики и быстро грузится даже на медленном канале и раньше напрягало вольяжное открытие стартовой даже с хорошей выделенки, теперь всё ок!
Биг тебе человеческий tnx Smile

Аватар пользователя B.X B.X 30 сентября 2006 в 17:19

этот devel сам много кушает, полагаться на него нельзя, тесты надо проводить какими-нибудь сторонними способами...

Аватар пользователя smile smile 2 октября 2006 в 13:07

реально раза в два (визуально) работает быстрее. джейсон, мега-респект!

напрягает только одна тема: после новой версии опять придется в этом всем разбираться.

Аватар пользователя jason32 jason32 11 октября 2006 в 16:43

Quote:
А что на Drupal.org говрят по этму поводу - если так все просто - то это серьезный баг в друпале - представьте - 70 лишних запросов на страницу - не думаю что там такой ляп пропустили…

Да понятно, что скажут. Скажут, что при большом количестве алиасов запрс будет слишком большим( там много маленьких запросов заменяется одним большим), что приведет к большому расходу памяти. Но для небольших сайтов( ИмХО меньше 10000 алиасов) всё это несущественно.

Аватар пользователя kiev1 kiev1 11 октября 2006 в 23:30

с mysql кешем тоже прям беда - не работает он так как надо - автоматически ничего не хранит и тут-же забывает, а если включить время жизни например 15 минут - то по прошествии их все забывается и странички опять начинают дико тормозить, при чем на обслуживание этого "кеша" в mysql и обратно гоняются огромные массивы, друпал в плане кеша просто разочаровал - может его вообще выкинуть из друпала? слишком много он ресурсов отбирает.

Аватар пользователя buddha buddha 23 января 2007 в 13:59

действительно, заметно быстрее стало постить материал.

не возражаешь если я об этом напишу в рассылке про Друпал?

Аватар пользователя OnlyKaramba OnlyKaramba 13 декабря 2008 в 21:08

Мега респект тебе и уважуха, jason32!

Я было начал сам переписывать path.inc а потом нашол твой код. Это то, что мне было надо. У меня на бисер.инфо около 10 строк в url_alias а запросов туда по 100 штук на каждой странице.

Недавно я поставил модуль-патч Модуль кеширования алиасов путей
от seaji. Вначале мне показалось, что работает хорошо а потом выяснилось что не очень.

Ешё раз спасибо!

Аватар пользователя Paldru Paldru 20 августа 2009 в 23:10

Ребята, поставил этот хак. Сайт стал летать, но почему-то перестали работать алиасы страницы профиля. При логине на сайт страница профиля грузиться, а при последующем обновлении страницы выдает 404. Друпал 6.13

Аватар пользователя jason32 jason32 30 августа 2009 в 8:13

"Paldru" wrote:
Ребята, поставил этот хак. Сайт стал летать, но почему-то перестали работать алиасы страницы профиля. При логине на сайт страница профиля грузиться, а при последующем обновлении страницы выдает 404. Друпал 6.13

Неудивительно, потому что писалось ещё для 5-ки и на 6-м Друпале не тестировалось

Аватар пользователя WARpholomey WARpholomey 31 августа 2009 в 16:45

Да, переводы в Drupal это больная тема) В принципе сейчас ценой долгих мучений заставил таки расширение PHP Gettext заработать под Windows. Есть свои нюансы, но вполне можно сделать кросс-платформенное решение. Этот недописанный модуль для 4-и совсем неплох, единственное конечно что в Drupal столько поменялось, что его легче переписать. Сейчас пытался сравнить производительность системы, если:

  • Использовать полный перевод из базы данных.
  • Использовать скомпилированный файл переводов.

Точно сказать не могу, что быстрее, но (imho) второй способ более правильный. Ведь Gettext в принципе и рассчитан на компиляцию переводов после их редактирования.

Так что задам такой вопрос: кому-нибудь кроме меня нужно, чтобы я написал модуль для Drupal 6, который заменит функциональность модуля Locale и позволит работать с файлами .mo напрямую, вместо базы данных? Сейчас у меня это хак, но если кому-то будет нужен, сделаю модуль.

Аватар пользователя jason32 jason32 31 августа 2009 в 17:55

"WARpholomey" wrote:
Сейчас у меня это хак, но если кому-то будет нужен, сделаю модуль.

Ты хочешь заработать или помочь сообществу?

Аватар пользователя WARpholomey WARpholomey 31 августа 2009 в 22:37

Помочь сообществу. Моего в модуле толком не будет, разве я изобрел Gettext?) Конечно бесплатно... Просто это кому-то кроме меня нужно? Если нужно, сделаю модулем.

Аватар пользователя jason32 jason32 2 сентября 2009 в 12:57

"WARpholomey" wrote:
Помочь сообществу. Моего в модуле толком не будет, разве я изобрел Gettext?) Конечно бесплатно... Просто это кому-то кроме меня нужно? Если нужно, сделаю модулем.

Думаю что нужно, все будут в восторге, давно такие запросы были