グループの友人は 2 か月前に質問をしました。彼はこう言いました。「彼らの会社のプロジェクトのモジュールのパフォーマンスがオンラインで非常に悪いです。問題は長い間見つかっていません。上司は彼に怒りながら尋ねました。彼はこう言いました。」分析のためにすべてのクラス メソッドの実行時間を記録しており、現在のプロジェクトのパフォーマンスに影響を与えることはできません。「上司は、パフォーマンスに影響を与える特定の場所を分析するためにこの情報を記録し、プロジェクトが一定期間実行された後に削除するように彼に依頼しました。時間の。この要件により、2 つの問題が生じます。1 つ目は、このモジュール内のすべてのクラス メソッドの実行時間を監視する方法です (パフォーマンス自体は非常に悪いですが)。分析する 2 つの質問:
1. このモジュールのすべてのクラスメソッドの実行時間を監視する方法
この問題について彼が最初に考えたのは、すべてのクラス メソッドの処理前に時間を記録するコードを追加し、データを返す前に実行時間を計算して、ログを記録することでした。この方法は実行可能である必要があり、パフォーマンスに大きな影響を与えることはありませんが、プログラマは怠け者であり、彼らは皆非常に賢いので、それが実装されている場合はプログラマーではありません。これを削除すると、変更するコードの量が多すぎて、意味のない技術的な作業が長時間繰り返されることになります。次に、これを再度削除するとクラッシュします。もちろん、私の友人は誰もそんなことをしなかったので、私はこの奇妙なニーズについて学びました。このようなタスクを解決するには、__call() と __callStatic() を使用する必要があります。php5.3 より前では、静的メソッドを 1 つずつ追加するしかありませんでした。 .3 では、__callStatic() マジック メソッドが追加されています。これら 2 つのマジック メソッドは、クラス メソッドが存在しない場合にのみ役立つのではないかと疑問に思う人もいるかもしれません。どうすればこの要件を達成できるのでしょうか。この質問のコードは後で見ていきます。以下の 2 番目の質問を分析してみましょう。
2. 現在のプロジェクトのパフォーマンスに影響を与えずに完了するにはどうすればよいですか
なぜこの問題があると言えるのですか?以前に要件を分析したときに確かに存在していましたが、最初の質問に回答したときに解決策がすでに述べられていたため、__call() と __callStatic() を使用してクラス メソッドをオーバーロードするのは実装が比較的簡単で、既存のメソッドにも適していると思います。プロジェクトのパフォーマンスへの影響は最小限です。
この質問では主に他のいくつかの方法について説明します。実際には、xdebug、xhprof など、パフォーマンス分析を実現するための拡張機能が多数あります。xdebug はパフォーマンスの低下が大きく、正式な環境での使用には適していないことが知られています。 xhprof はパフォーマンスの低下が比較的小さいため、正式な環境で使用できます。では、なぜ xhprof を使用しないのでしょうか?ポイントは 3 つあります: 1. パフォーマンスの低下が若干大きくなります。 2. ログの記録形式が柔軟性に欠けるため、ログ分析に問題が発生します。 3. 一部の関数がカウントできず、重大なエラーが発生します (call_user_func_array など)。
解決策が決まったので、まずデモを見てみましょう
りー
上記のデモ クラスには、通常のメソッドと静的メソッドの 2 つのメソッドがあり、ビジネス層がそれを呼び出す方法は次のとおりです。
りー原則の 1 つは、クラスの外部のコードを変更せず、それを実現するためにクラスのみを調整することです。以下では、__call() と __callStatic() を使用してクラス メソッドをオーバーロードします。れーれー
このコードでは、__call() メソッドと __callStatic() メソッドを追加しました。ビジネス層の以前のコードは変更されておらず、呼び出された場合に使用する呼び出しメソッドが存在するため、これら 2 つのメソッドを追加しただけでは意味がありません。メソッドは存在せず、クラス自体を変更するだけです。メソッド名の前にアンダースコアを追加することしかできません (このルールは自分で決定します)。そして、これら 2 つのメソッドを呼び出すと、2 つのメソッドの実行時間は出力。
この実装ではまだ多くのコード変更があり、各クラスを追加する必要がありますが、これは非常に面倒です...実際、手元にあるツールを使用して実装するのは簡単です。これを表現するのは良い方法です。2 つのメソッドは基本クラスに書き込まれ、すべてのクラスがこの基本クラスを継承します。コンストラクターとデストラクターを除くクラス メソッド名の置換については、エディターを使用して直接バッチで置換でき、後で元に戻すこともできます。
注: 継承を使用して実装された場合、__callStatic() メソッドの __CLASS__ を調整する必要があります。
これは、ビジネス層がクラス メソッドを見つけられないように、クラス メソッドの前にアンダースコアを追加することで実装されています。実際、この例はメソッドの可視性を調整することによって実装することもできますが、可視性の実装方法には次のような欠点があります。
1. 調整後に元に戻したい場合は、クラスメソッドの表示が間違っている可能性が高く、どのメソッドが調整されたのかがわかりません。2. 可視性の調整はクラスのパブリック メソッドに対してのみ有効であり、プロテクト メソッドやプライベート メソッドに対しては無効です
もちろん、クラスのパブリック メソッドのパフォーマンスのみを記録する場合は、変更メソッドの可視性を使用してこれを実現できますが、メソッドが変更されたという注意にマークを追加することを忘れないでください。このクラスを継承するクラスが存在する場合、このメソッドにアクセスする方法がないため、パブリックからプライベートに変更されます。
」