PHPでAOPを検証 <Ray.Aop使用>
以前の記事にコメントをもらったので、もう一度試してみようと検証しているところです。
自分が書いた記事では、システムの速度が遅くなったため原因を探してAOP周りの実装が影響していると判断し、実装を変更した旨を書いています。
AOP単体のライブラリで試していないため、正直本来の原因がわかっていない感じです。
コメントをもらった内容的には、「インターセプトのかかってないメソッドのAOPコストはゼロです」とのことだったので、AOPを使用していない部分に影響はない。という認識でいいのだと思います。
実際に以前の記事での状態は、AOPを使用した関数を通らない状態でも遅い状態になっていたため、AOP周りを外すという選択をしました。使い方が間違っているのか、設定がおかしいのか、等のAOP周りの検証までは詳しく行っていませんでした。
というわけで、AOP周りをもう一度試してみようと検証と試行錯誤を数日やっている感じになっているため、記事にしておこうと思います。
やろうとしていること
使用するライブラリ
- 以前の記事の状態の再現
- BEAR.Sundayでの挙動
- Ray.Aop単体での挙動
- laravelに自分で組み込めるか
dockerでphp7.4の環境を作り、docker上で動作確認しています。nginxを使用してwebでの挙動を確認しています。
以前の記事の状態の再現
前に書いた記事の状態はlaravelでRay.Aopをラップしたライブラリを使用していました。
Aop周りの挙動としては、関数にAnnotationを付与することで使用することができ、かなり便利でした。
ただし使用するクラス分のファイルがstorage/framework/aop/compile配下に作成されます。このファイルのinclude周りでメモリが消費され速度に影響しているものと考え、aopを断念しました。
get_included_files関数を呼び出して内容を確認したところ、compile配下のすべてのファイルが読み込み状態になりメモリが消費されていると判断しました。
もう一度試すためにサンプルプログラムを作り、100クラス作り試したところ同じような状態になったため、以前の状態の再現ができました。速度もBootingの部分でクラスを追加するごとに遅くなることも確認しました。
BEAR.Sundayでの挙動
使ってみたかったフレームワークでAOPを知ったきっかけのフレームワーク。
チュートリアルを参考に実行してみて、Benchmarkのlogを出力するところまで実施。php7.4で試したためAnnotationを使用。
$this->bindInterceptor( $this->matcher->any(), // どのクラスでも $this->matcher->annotatedWith(BenchMark::class), [BenchMarker::class] // BenchMarkerインターセプターを適用 );
ただわからなかったのは、Resource/Page配下やApp配下のクラスは動くけど、自前でDomain/UseCaseに作ったクラスで動作しませんでした。なにか設定があるんでしょうか。わかりませんでした。
compileファイルは/tmp配下に作成されていました。(バージョンを変えたら/var/tmp配下になりました)
検証したい内容はincludeされるファイルで影響する部分のみに限定されるのか、またクラスが増えることで速度に影響がでるのかどうか。というあたりです。
■ファイルinclude状況
get_included_filesを利用して確認しましたが、動作に影響する部分のみのincludeになっており、他のインターセプトの読み込みは行われていないことを確認
動かす関数のアノテーションを削除してみると読み込みもなくなっています
■classを増やしてみる
クラスを10個ぐらい増やして試してみましたが、速度的にもメモリ的にも増加する気配がない
includeファイルも増えていないことを確認
Ray.Aop単体での挙動
Ray.Aopのdemoを利用して検証
■ファイルinclude状況
BEAR.Sundayと同じ結果
■classを増やしてみる
BEAR.Sundayと同じ結果
laravelに自分で組み込めるか
laravelをそこまで理解できていないため、自分の実力では組み込みまで時間がかかりそう。たぶんやらない。
Ray.Aop自体が問題なさそうなので、書き方の問題っぽいのでちゃんと書けば問題なさそう。
結論
aop自体に問題があるわけではなさそう。ただしlaravelに使うのは当分諦めてみる。
やり方が悪いのか、バージョンが影響しているのか判断することもできていないが、自分のプロジェクトに使えるようにコードを組むことが想像できないためAOPを使わないでプロジェクトは進めると思います。
正直100クラス程度を読み込んだぐらいで使用メモリが膨れ上がったり、速度に影響でるとはあまり思っていないので、ちゃんとした原因を理解したいですが、ちょっと時間がかかりすぎているので一旦諦める感じにします。