symfony のルーティング処理のダイエット

prod モードではデフォルトで、ルーティングの設定のみでなく、設定から生成される sfRoute クラスでコンパイルを行った状態のインスタンスシリアライズされ、キャッシュされます。
したがって、prod モードでは実行時のコンパイル処理のオーバーヘッドは気にしなくてもよさそうです。

ただし、最大でルーティング設定の個数分のマッチング処理が行われることと、ルーティング設定 1 つにつき 1 つの sfRoute オブジェクト(または sfRoute の派生オブジェクト)が必ず生成されて配列としてすべて保持していることから、無駄にルーティング設定の個数を増やすことはそれだけでメモリを無駄に消費していたり、symfony の実行速度を遅くしてしまいます。

パターンに * を使うか、変数にマッチする条件を正規表現で上手く指定してやることで、複数のパターンを 1 つにまとめられる可能性があります。内部的には最終的に preg_match が実行されることには変わりないので、積極的に正規表現を使ってパターンをまとめるようにすると良いのではないでしょうか。

例:

  • /Dir1/page/ja
  • /Dir1/page/en

という 2 つのページがあって、1 つのアクションで内部的に ja と en を拾って切り替える場合

pat1:
  url: /Dir1/page/ja
  param: { module: module1, action: action1, lang: ja }

pat2:
  url: /Dir1/page/en
  param: { module: module1, action: action1, lang: en }

を、

pat1:
  url: /Dir1/page/:lang
  param: { module: module1, action: action1 }
  requirements: { lang: ja|en }

としても同等です。(あまり面白い例でなくてすみません・・・。)

sfRouteのコンパイル済み正規表現の確認

実際にパターンがどのような正規表現コンパイルされているのかを確認しながら、routing.yml の最適化を行うとよさそうです。

ルーティングの確認には、symfony コマンド「app:routes」を使用します。

$ ./symfony app:routes frontend
>> app       Current routes for application "frontend"
Name                  Method Pattern
homepage              ANY    /
route1                ANY    /Dir1/Dir2/:param1/:param2
:

この app:routes タスクに、ルーティング設定名をオプションで指定すると、そのルーティング設定の詳細(コンパイル済み正規表現を含む)を確認することができます。

$ ./symfony app:routes frontend route1
>> app       Route "route1" for application "frontend"
Name         route1
Pattern      /Dir1/Dir2/:param1/:param2
Class        sfRoute
Defaults     action: 'actionname'
             module: 'modulename'
:
Regex        #^
             /Dir1
             /Dir2
             /(?P<param1>param\d)
             /(?P<param2>.*)
             $#x
:


※Jobeet 5日目でも、ルーティングのこのデバッグについて触れられていますね・・。
※→symfony 1.x legacy website Route Debugging のところ。