Drupal → Производительность больших меню созданных с помощью Taxonomy Menu

13.11.2014

Случайно наткнулся на "фичу" — если в меню выводятся ссылки на термины, то на каждую ссылку друпал вызывает taxonomy_term_load(). Т.е. если вы выводите древовидное меню на 100 терминов, то получите 100 вызовов taxonomy_term_load() (каждая загрузка сущности это около 1 ms).

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

/**
 * Implements hook_query_TAG_alter(): translatable.
 */
function MODULENAME_query_translatable_alter(QueryAlterableInterface $query) {
  $tables = &$query->getTables();
  if (
    isset($tables['ml']['table'], $tables['m']['table']) &&
    $tables['ml']['table'] == 'menu_links' &&
    $tables['m']['table'] == 'menu_router'
  ) {
    $where = &$query->conditions();
    if (
      isset($where[0]['field'], $where[0]['value']) &&
      $where[0]['field'] == 'ml.menu_name' &&
      $where[0]['value'] == 'main-menu' // машинное имя меню
    ) {
      $query->addExpression('1', 'access');
    }
  }
}

Здесь мы альтерим запрос из функции _menu_build_tree() и добавляем новое поле access со значением 1. Ссылки с таким атрибутом не будут проходить проверку доступа и соответственно не будет дёргаться taxonomy_term_load().

До:

После:

Не забываем сбросить кэш.

P.S.: есть конечно и альтернатива — отказаться от модуля Menu и выводить ссылки ручками.

Написанное актуально для
Drupal 7
Похожие записи

Комментарии

Выходит нехилую прибавку в скорости можно получить в магазинах и каталогах большого размера.. Отлично!

А теперь попробуйте зайти на админ страницу, которая есть в главном меню под анонимным пользователем.

@servekon попробовал, ничего не произошло, должно быть что-то другое? я уж не буду спрашивать, что делает ссылка на админ страницу в меню, которое сгенерировал Taxonomy menu

@xandeadx да что-то я не обратил внимание, что это таксономия грузится. Для меня ситуация когда access выставляют вручную, примерно как для быка красная тряпка.

Так наверно для нод тоже самое будет. Для любых путей у которых в качестве аргумента используется какая либо сущность буде entity_load вызываться. Сущность нужна для того, чтобы проверить доступ к данному пути. Попробуй добавить в меню 100 ссылок на ноды.

с нодами почему-то не вызывается, мне уже лень разбираться почему)

Подскажите, что делать с кодом? :) Я имею в виду, править ли сам модуль Taxonomy Menu, или код добавить в свой модуль? или в сеттингс.пхп?

С такой же проблемой разбираюсь. 113 пунктов в меню...

Нашёл вариант, через hook_block_info_alter включить для этого блока кэш. Даже модуль для этого есть: https://www.drupal.org/project/blockcache_alter

Но это не решает полностью проблему. Кроме загрузки терминов, тормозит также темизация этого меню. xhprof говорит что вызовы theme_menu_link() отнимают времени в 5 раз больше чем вызовы taxonomy_term_load(). Кэширование на уровне блока не помогает, потому что в кэш попадает render массив, который потом все равно темизировать надо.

Добавить комментарий