Zend\Di\Di определения и память
В моем приложении ZF2 я использую Zend\Di\Di
создать все мои экземпляры класса. Определения DI сканируются с использованием Zend\Di\Definition\CompilerDefinition
и кешируется с помощью APC. Это позволяет избежать сканирования классов во время выполнения с использованием медленного отражения. Если при создании экземпляра возникает исключение (из-за устаревших определений DI), код повторно сканируется, определения кэшируются и экземпляр создается снова.
Это очень удобно во время разработки, поскольку нет необходимости писать или изменять фабричные методы / замыкания для новых классов или измененных конструкторов. Мои конструкторы следуют определенному соглашению (только аргументы с подсказками типа и единственный массив $params), чтобы гарантировать, что внедрение зависимости работает без указания дополнительных параметров конструктора.
До сих пор это работает хорошо, избегает ошибок (без устаревших заводских методов) и ускоряет разработку. Однако отсканированные определения в настоящее время составляют 1,8 МБ (сериализованный массив) в APC и продолжают расти. Так как они должны загружаться из кэша при каждом запросе, я боюсь, что память будет исчерпана, если за короткое время будет слишком много запросов. У меня нет настроек нагрузочного тестирования, чтобы имитировать это, хотя.
Я знаю, что рекомендуемый способ - использовать Zend\ServiceManager и писать фабричные закрытия для каждого класса вместо использования Zend\Di\Di. Но я представляю, что это много работы и довольно раздражает в процессе разработки.
Вы рекомендуете рефакторинг к Zend\ServiceManager в этой ситуации?
2 ответа
Это именно то, что я раскрыл в своем блоге о Zend\Di
и RAD.
В то время как Zend\Di
это хорошо для разработки, это огромное узкое место в производстве и памяти. Даже если вы кешируете определения, он все равно использует ReflectionClass
а также call_user_func_array()
манипулировать вашими экземплярами. Он также должен выполнить множество окружающих операций, которые необходимы для выравнивания параметров впрыска: просто взгляните на количество обращений к array_merge
во время создания объекта через Zend\Di
,
Я написал модуль для обработки компиляции Zend\Di\Di
Менеджеры экземпляров для замыканий: OcraDiCompiler. Он нуждается в некоторой очистке, но его работа состоит в том, чтобы генерировать фабрику / замыкания кода путем отслеживания логики реализации Zend\Di
Внутренности. Если вы хотите немного "оживить" его, я был бы рад помочь в этом, поскольку он находится в моем списке TODO, но с низким приоритетом прямо сейчас.
В любом случае, перемещение логики реализации на фабрики / закрытие ServiceManager
это не так много работы, как вы ожидаете, так что не пугайтесь и попробуйте: вам может понравиться.
Я написал модуль ZF2, чтобы помочь вам решить эту проблему: https://github.com/aimfeld/ZendDiCompiler
ZendDiCompiler - это модуль Zend Framework 2, который использует автоматически сгенерированный заводской код для внедрения зависимостей. Это экономит вам много работы, так как больше не нужно писать фабричные закрытия Zend\ServiceManager и обновлять их вручную.
ZendDiCompiler сканирует ваш код (используя Zend\Di) и автоматически создает фабричные методы. Если фабричные методы устарели, ZendDiCompiler обновляет их в фоновом режиме. Таким образом, вы разрабатываете быстрее, избегаете ошибок из-за устаревших заводских методов и получаете отличную производительность на производстве!