Как ускорить обработку шаблона в Symfony2?
У меня есть приложение symfony2, которое отображает около 6000 объектов базы данных.
Я оптимизировал запросы ORM (propel), и запросы к базе данных теперь очень быстрые. Остается контроллер Symfony и движок рендеринга шаблонов.
Есть ли способ ускорить рендеринг (например, переход на php-шаблоны?) Могу ли я получить более подробную информацию о профилировании, чем из профилировщика symfony?
Здесь выдержка из данных профилировщика.
Изменить: я профилировал свой код с помощью xDebug и обнаружил, что генерация объектов очень дорога. Создание тысяч объектов PHP из строк базы данных в PropelObjectFormater->getAllObjectsFromRow
занимает большую часть времени.
На изображении показана ветка, которая занимает 95% времени вычислений, что составляет ~ 2,8 секунды. Поиск базы данных занимает ~ 0,5 секунды, рендеринг - 1 секунду, а форматирование занимает больше всего времени ~ 1,5 секунды.
Я не уверен, какое влияние оказывает длина файла, содержащего класс PHP, но Propel генерирует много кода (у моего самого сложного базового класса объекта есть почти 10 тыс. Строк кода), поэтому это может замедлить создание объекта.
Я думаю, что использование форматера массива (таким образом, минуя шаг создания объекта) было бы решением, но это несколько портило цель ORM.
Ответы
Ответ 1
Когда в режиме производства, отображение шаблона Symfony2 Twig фактически выполняется с использованием кэшированных шаблонов, что означает, что это шаблон PHP; шаблон Twig, скомпилированный в чистый PHP-код. В режиме dev он, конечно, не кэширует такие шаблоны, а компилирует их каждый раз. Подробнее об этом читайте в документах.
Некоторое время PHP займет некоторое время, чтобы скомпилировать страницу с таким большим количеством данных, даже если шаблон является обычным кодом инфузии PHP-HTML, который имеет тенденцию работать быстрее всего. - Возможно, вы захотите изучить обычное кеширование HTTP, например, Varnish, если эта страница - это то, что не нужно визуализировать из базы данных каждый раз.
Что касается профилирования. Что-то вроде XDebug должно предоставить вам более подробную информацию о профилировании, чем то, что встроено в Symfony2.
Ответ 2
6K итераций - это много работы.
Идея №1:
Можете ли вы реализовать разбиение на страницы данных? Это кажется весьма разумным...
Идея №2 (толстый клиент):
Внедрите механизм JavaScript
шаблонов. Затем ваш контроллер должен вернуть JSON
для того, чтобы JS
мог пойти, хотя и полностью отобразить его.
Даже в этой ситуации часто приходится полагаться на скорость браузера, чтобы быстро сделать циклы 6K. Вам нужно будет выполнить паузы между ними (например, после каждой 150-й итерации), чтобы браузер не перешел в невосприимчивый режим...
Ответ 3
Похоже, вам нужно использовать расширение PHP twig, которое было сделано для вашей ситуации.
Из документов:
И с этого момента Twig автоматически скомпилирует ваши шаблоны, чтобы воспользоваться расширением C. Обратите внимание, что это расширение не заменяет PHP-код, но предоставляет только оптимизированную версию метода Twig_Template :: getAttribute().
Я лично не получил практически никакого видимого влияния, когда я попробовал год назад для своего проекта. Поделитесь своим опытом, если вы его используете.
Ответ 4
Здесь вы задаете два вопроса:
1) как ускорить отрисовку шаблона?
Профайлер говорит, что запросы кастинга бросали рендеринг, я думаю, что вы забыли соединение, предпочтительнее выполнить один большой запрос (возможно, кэшируемый) перед рендерингом и просто использовать результаты запроса в уровне представления.
2) Как получить более подробные данные профилирования?
Я могу предложить установить xhprof для профилированного профиля, вы можете использовать этот отличный комплект: https://github.com/jonaswouters/XhprofBundle. Xhprof отслеживает php-вызовы и строит статистику выполнения времени и графика визуальных вызовов. Я использую его для определения того, какие результаты процесса я должен хранить в кеше.
Ответ 5
Я закрепил представление в redis.
При визуализации представления Twig будет получать данные по запросу, ожидая, что запрос занимает некоторое время. Таким образом, быстрый способ отображения, который никогда не является запросом. В моем проекте, когда какое-то место не меняется, поэтому я кэшировал html-код этой части, используя функцию renderView в контроллере.
Ответ 6
Основываясь на @jperovic ответе:
Как он сказал, вы можете создать API для выброса данных JSON и поместить работу на стороне клиента. Кроме того, возможно, вам не нужно отображать все 6000 объектов одновременно? Такая ленивая загрузка дополнительных данных через вызовы ajax могла бы помочь.
На стороне базы данных кешируйте результаты и каждый раз разбивайте кеш, чтобы увидеть, есть ли какие-либо новые данные. Или если данные должны постоянно обновляться: независимо от того, какая часть приложения будет обновляться, данные также отправят запрос, чтобы сообщить вашему API, что он должен сломать кеш.