Posted at
SymfonyDay 22

autowireされたTranslatorInterfaceの行方


発端

symfonyのcommandで作ったバッチでメモリ不足発生。本番環境では発生しない。

自分にとって「またか」の現象です。その都度対策はしているので、今回は新たな原因があるのでしょう。

さっそく原因を調べていきます。調査過程は省略しますが、translatorの呼び出しで少しづつメモリが減っていることがわかりました。


追跡

translatorは普通にTranslatorInterfaceでautowireしています。

debug:autowiringコマンドで何が注入されているか見てみます。

> php bin/console debug:autowiring translator

Autowirable Services
====================

The following classes & interfaces can be used as type-hints when autowiring:
(only showing classes/interfaces matching translator)

---------------------------------------------------
Symfony\Component\Translation\TranslatorInterface
alias to translator.data_collector
---------------------------------------------------

prod環境では結果が変わることに注意です。

> php bin/console debug:autowiring translator --env=prod

Autowirable Services
====================

The following classes & interfaces can be used as type-hints when autowiring:
(only showing classes/interfaces matching translator)

---------------------------------------------------
Symfony\Component\Translation\TranslatorInterface
alias to translator.default
---------------------------------------------------

translator.data_collector, translator.defaultが実際どのクラスなのか、debug:containerコマンドで調べます。

> php bin/console debug:container translator.data_collector                                  

Information for Service "translator.data_collector"
===================================================

---------------- -------------------------------------------------------
Option Value
---------------- -------------------------------------------------------
Service ID translator.data_collector
Class Symfony\Component\Translation\DataCollectorTranslator
(略)

> php bin/console debug:container translator.default

Information for Service "translator.default"
============================================

---------------- -------------------------------------------------------
Option Value
---------------- -------------------------------------------------------
Service ID translator.default
Class Symfony\Bundle\FrameworkBundle\Translation\Translator
(略)

dev環境では Symfony\Component\Translation\DataCollectorTranslator がautowireされることがわかりました。

このクラスのコードを見た瞬間、メモリが消費されていく原因がわかりました(笑)


対応

services:

Symfony\Component\Translation\TranslatorInterface: '@translator.default'

もしくは、コマンドを--no-debugで実行する

一番最後で核心をついてしまいましたがsymfonyのコンテナはvar/cache以下に(envのパターン)×(debug or no-debug)の組み合わせ別にphpファイルにコンパイルされているのです。

いろいろ寄り道をした気がしますが、symfonyのサービスコンテナとautowireの内部に一歩踏み込んだとは思います。