Почему приложение Symfony2 тратит 70-90% своего времени на анализ YAML?

Как показано на выходе Webgrind ниже, мое приложение тратит большую часть времени обработки на синтаксический анализ YAML.

Выход Webgrind - синтаксический анализ YAML на 83.63%.

Примечание. Выход Webgrind находится в процентах. Таким образом, добавление «Total Self Cost» показывает, что 83,63 процента общего времени потрачено на обработку YAML.

Я видел эту связанную тему:

Приложения для Symfony2 YML по каждому запросу

Однако моя реализация использует класс ApcClassLoader, как показано ниже:

$loader = new ApcClassLoader('odr_dev', $loader); $loader->register(true); 

Кроме того, я проверил систему APC с помощью apc.php, и мои классы и страницы находятся в кэше APC и попадают в нее. Это происходит на PROD или DEV по любому запросу даже после заполнения кэшей.

Моя теория заключается в том, что у нас есть циклическая ссылка на сущность, и система не может успешно разобрать YAML для ее кеширования. Таким образом, он пытается разобрать YAML по каждому запросу.

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

Я думаю, что ваша проблема – это, вероятно, рекурсивные ресурсы YAML (или аналогичные). Вы видите 4000 + вызов метода Yaml\Parser::parse . При проверке моего собственного приложения (которое довольно сложно) при загрузке страницы с полностью пустым кешем я вижу только 166 запросов. И это сбрасывается до 2 вызовов для загрузки страниц с использованием теплого кеша.

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

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

Я думаю, что я и многие другие предполагали, что когда мы включим APC, он также будет использоваться доктриной для кэширования метаданных. Фактически, Doctrine по умолчанию использует свой кеш массива, если не указано иное.

На этой странице перечислены параметры конфигурации Doctrine:

http://symfony.com/doc/2.3/reference/configuration/doctrine.html

После добавления параметров кэширования к моему /app/config/config.yml как показано ниже:

 doctrine: dbal: driver: %database_driver% host: %database_host% port: %database_port% dbname: %database_name% user: %database_user% password: %database_password% charset: UTF8 orm: auto_generate_proxy_classes: %kernel.debug% auto_mapping: true result_cache_driver: type: memcached host: 127.0.0.1 port: 11211 instance_class: Memcached metadata_cache_driver: type: memcached host: 127.0.0.1 port: 11211 instance_class: Memcached query_cache_driver: type: memcached host: 127.0.0.1 port: 11211 instance_class: Memcached 

После исправления на той же странице нет взаимодействия с парсером YAML и загружается в 302 мс против 5851 мс для общего ускорения 19X. Кроме того, файл cachegrind перешел от 121 МБ до 3,4 МБ, и эти результаты в целом согласуются с рядом проб.

Вот тот же Webgrind, показывающий разницу:

Webgrind Fixed

Таким образом, в основном это была проблема конфигурации. Из того, что я видел в вопросах StackOverflow и других форумах, кажется, что здесь отключается о том, как работает кеширование. По сути, вам нужно явно включить его для кэширования Doctrine, как описано выше, или использует в основном бесполезный дефолт.

Symfony2 иногда может быть слишком «настраиваемым», и это один из примеров, когда мне никогда не приходило в голову, что он будет отдельно настраиваться. В этом отношении это мощная функция (возможность использовать отдельные кеши для вещей), но пока вы не поймете это, система полностью скомпрометирована с точки зрения скорости.