[ PHP ]クロージャを使用したデバッグログのオーバーヘッドを減らすようにします.


Thanks for your visiting.
I glad if you understand that my english level is beginner.
I would be very happy if you find and tell me any mistake made by me.


概要


この記事では、PHPを使用した場合は、デバッグログのオーバヘッドを減少させようとします.
匿名の機能がいろいろなケースと言語で役に立つので、この記事があなたのために役に立つならば、私はうれしく思います.
記事のセクション
  • 1 .デバッグレベルのログの問題
  • は、生産サービスにデバッグレベルのログを使用する場合のパフォーマンスの問題です.
  • 2 .閉鎖を用いて性能オーバーヘッドを低減する
  • 閉鎖の概念を簡単に紹介します.そして、問題を解決しようとしてください.
  • 3 .結論
  • 付録.
  • −−−−−−−−−−−デバッグレベルログを使用しなければならない−
    この記事は私の主観的意見を含んでいることをご理解ください.あなたが間違ったことや他の意見を見つけるなら、私はあなたにそれを送ってくれてうれしいです.

    デバッグレベルのログの問題


    1 - 1 .デバッグレベルのログを頻繁に行うのは良いことですか?


    デバッグレベルのログ記録を行うときにログを記録するデータについて操作する場合は注意してください.
    例:マージ配列、オブジェクトのメソッドを呼び出すデータを取得します.
    アプリケーションを変更したり維持したりするためのサービスにデバッグレベルのログを追加することは有用かもしれません.
    したがって、必要な環境だけでログを記録するために、各環境でThreadSharpを調整することで、デバッグレベルのログを使用することは実際には可能です.
    しかし、私はログにデータを使用することがあります.そして、データやオブジェクトをデバッグとしてダンプする傾向があるので、潜在的にデータについての操作を行うことができます.
    例は、非常に例であるかもしれません.
    // array_merge
    $logger->debug("request dump", array_merge($request->post, $request->get, $request->headers));
    
    // method call (with calculating)
    $logger->debug("processed data", $money->convertCurrencyTo('USD'));
    
    // instance dump
    $logger->debug("instance dump", serialize($someObject));
    
    正確に、デバッグレベルがロギング閾値から除外されるとき、それは効果がないです.
    もしそうならば、我々はデータの操作でデバッグログを使用しない最も良い解決ですか?

    1 - 2 .どのように解決するには?


    必要な場合のみ操作を行います.
    我々はこの問題のために上記のように接近する.
    PHPのクロージャコンセプトを使用します.

    2 .閉鎖を利用した性能オーバーヘッドの低減


    2 - 1 .PHPでのクロージャは何ですか?


    https://www.php.net/manual/en/class.closure.php
    PHPのクロージャは、匿名関数を表すクラスです.
    無名関数は名前を持たない関数であり、実行時に作成して呼び出すことができます.
    PHPでは、callableの型の変数に定義し、パラメータとして使用します.
    良い例がPHP公式文書にあるので、下記を参照してください.
    https://www.php.net/manual/en/functions.anonymous.php
    この記事では、そのpass as parameter and execution it only cases which is needed - similler to lazy execution -それは完璧ではありませんが、匿名関数は、関数型プログラミングへのsimillerです.
    これは、一流関数の仕様を参照してくださいあなたのために良いかもしれません.

    2 - 2 .デバッグによるデバッグログの書き込み方法


    以下のように書きましょう.
    public function debugLog($message, Closure $closureForContext=null)
    {
        // skip if logging threshold is upper from DEBUG on environment.
        // self::LOGGING_THRESHOLD refer to global setting of each environments.
        if (self::LOGGING_THRESHOLD !== Logger::DEBUG) {
            return;
        }
    
        // call Closure as function to get Context Array we need to do logging.
        $context = $closureForContext ? $closureForContext() : null;
        $this->monolog->debug(Logger::DEBUG, $message, $context);
    }
    

    2 - 3 .呼び出すコードを書く


    それを使用すると、データを提供するロジックとパラメータとしてクロージャに渡します.
    use ()構文では、スコープの変数を使用することができます.
    $exampleLogger->debugLog(
        "request dump", 
        function () use ($request) {
            return array_merge($request->post, $request->get, $request->headers);
        }
    );
    

    2 - 4 .説明する



    デバッグレベルのログを行う際に、データを提供するロジックは、匿名関数にするために必要な場合だけ呼び出されます.
    環境に対する環境の決定とメイクの論理の追加だけでは、生産環境でロジックが実行されないので、オーバーヘッドを減らすことができます.

    2 - 5 .単にパフォーマンスチェック


    極端な例であるかもしれませんが、クロージャを使用するかどうかの間に経過時間がどれだけ異なるかを見ることができます.
    私は、それが非常に単純な考えと行動で非常に良い影響をもたらす可能性があると思います.

    コンディション

  • PHP SymfonyとMonolog
  • でのログのthrosholdからのデバッグレベルを除く
  • は、microtime(true)を使用している関連コード実行のために経過時間を見積もります
  • は、同じ環境でループするために1000000回を実行します
  • logのコンテキストとして、arrayRange merge ()の結果をパラメータとして設定します.
  • array_merge($request->headers, $request->query, $request->post)
  • 症例による経過時間の結果


    -
    単にコンテキストを記録する
    閉鎖で
    1時間
    1.0609450340271
    0.1174901802063
    2時間
    1.056135892868
    0.1269911262512
    3時間
    1.2411420345306
    0.11956310272217
    平均
    1.11秒
    0.12 sec
    もしそれを解析するためのプロファイラを使用するなら、より良いかもしれません.

    3 .結論


    PHPのクロージャ(匿名関数)を使用して、実行の実行タイミングを制御してオーバーヘッドを減らすことができます.
    以上です.
    あなたがより多くを学ぶ必要があるならば、それはLazy Execution概念を参照するのが良いかもしれません.
    我々は正しい認識でそれを使って慎重にする必要があります、しかし、それは我々が強力なカップリングを減らして、高い再利用可能なモジュールを作るのを許すことができるので、生産性の向上とオーバーヘッドを減らすかもしれません.
    この記事では、それについて非常に小さい部分が言いました.
    あなたが私たちのために非常に有用である機能を実装する機能を実装する上での解決のあなたのアイデアを広くすることができれば私はうれしいです.

    付録.気づいていることについて


    この節では、あなたが私の誤った記述によって間違っているかもしれないと言います.

    A - 1 .デバッグレベルをログ出力するのは常に最善の方法ではありません


    私の意見は、いくつかのルールが定義されている場合、アプリケーションの品質を維持し、すべての環境で撮影を行うことに非常に役立つので、デバッグレベルのログを行うことは良いことです.
    しかし、それはチームとして開発に規則と品質を定めて、維持するのが難しいので、それは高い理想であるかもしれません.
    それで、それをするならば、我々は慎重にそれを考慮しなければなりません.そうでなければ、オーバーヘッドと多くの価値のないloggingsの困った問題に会うかもしれません.

    A - 2 .必ずしも良い方法ではなく、閉鎖です。


    クローズは、単にログをデバッグするために配列を渡すよりも、オーバーヘッドのほとんどをするでしょう.したがって、単にデバッグログについて配列を渡すだけでは、クロージャを使用しないほうが良いかもしれません.
    たとえば、クロージャを使用する場合は、コンテキストの切り替えを行う呼び出しクロージャ機能のコールスタックのクロージャ、作成、破棄のインスタンスを作成するためのメモリ割り当てを行います.
    しかし、ARRYRUNEマージのような重い操作を必要とするデータを使用してデバッグログを使用するときに非常に便利です.
    また、ソースコードやプログラムフローを分析することは困難になる場合もある.
    したがって、適切なケースにそれを使用する必要があります.

    A - 3 .PHPだけではなく、


    匿名関数は、様々なプログラミング言語を使用する概念です.
    いくつかの違いは.しかし、コンセプトは様々な言語で非常にsimillerです.ですから、他の言語にもっと役に立つようにしてください.