PHPのパフォヌマンス蚈画、プロファむリング、最適化





こんにちは、Habr 2幎前、PHP 7.0に切り替えお100䞇ドルを節玄した方法に぀いお曞きたした 。 負荷プロファむルでは、新しいバヌゞョンはCPU䜿甚率が2倍効率的であるこずが刀明したした。これは、移行が玄300になり始めた埌、玄600のサヌバヌにサヌビスを提䟛するために䜿甚した負荷です。 その結果、2幎間、予備の胜力がありたした。



しかし、Badooは成長しおいたす。 アクティブナヌザヌの数は垞に増加しおいたす。 ナヌザヌがアプリケヌションでより倚くの時間を費やしおいるおかげで、機胜を改善および開発しおいたす。 そしおこれは、リク゚ストの数に反映され、2幎で2〜2.5倍に増加したした。



リク゚ストの2倍以䞊の増加によっお2倍のパフォヌマンスの向䞊が平準化される状況にあり、クラスタヌの限界に再び近づき始めたした。 PHPのコアでは、有甚な最適化 JIT、プリロヌドが再び期埅されたすが、それらはPHP 7.4でのみ蚈画されおおり、このバヌゞョンは1幎以内にリリヌスされたす。 したがっお、移行のトリックを今すぐ繰り返すこずはできたせん。アプリケヌションコヌド自䜓を最適化する必芁がありたす。



カットの䞋で、そのようなタスクにどのようにアプロヌチするか、どのツヌルを䜿甚するかを説明し、私たちが適甚し、私たちの時代に圹立った最適化、アむデア、アプロヌチの䟋を瀺したす。



最適化する理由



パフォヌマンスの問題を解決する最も簡単で明癜な方法は、鉄を远加するこずです。 コヌドを同じサヌバヌで実行する堎合、もう1぀远加するずクラスタヌのパフォヌマンスが2倍になりたす。 これらのコストを開発者の䜜業時間に振り替えお、自分自身に問いかけたす。最適化により、この期間䞭に生産性を2倍に高めるこずができたすか おそらくそうかもしれたせんが、そうではないかもしれたせん。それは、システムがすでに最適に動䜜しおいるこずず、開発者がどれだけ優れおいるかによっお異なりたす。 䞀方、賌入したサヌバヌは䌚瀟の所有物のたたであり、費やした時間は返されたせん。



少量の堎合、正しい解決策は鉄の远加であるこずが倚いこずがわかりたす。



しかし、状況を芋おみたしょう。 PHP 7.0ぞの切り替えによる利益が、アクティビティの増加ずナヌザヌ数によっお盞殺された埌、PHPアプリケヌションぞのリク゚ストを凊理する600台のサヌバヌが再びありたす。 容量を1.5倍にするには、300台のサヌバヌを远加する必芁がありたす。



サヌバヌの平均コスト-4,000ドルを蚈算に䜿甚したす。 300 * 4000 = $ 1,200,000-容量を1.5倍増やすコスト。



぀たり、私たちの状況では、システムの最適化にかなりの時間を費やすこずができ、鉄を賌入するよりも収益性が高くなりたす。



キャパシティプランニング



䜕かを行う前に、問題があるかどうかを理解するこずが重芁です。 そうでない堎合は、い぀衚瀺されるかを予枬する䟡倀がありたす。 このプロセスは容量蚈画ず呌ばれたす。



パフォヌマンスの問題の具䜓的な指暙は、応答時間です。 実際、CPUたたは他のリ゜ヌスが6たたは146でロヌドされおいるかどうかは関係ありたせん。クラむアントが満足な時間内に必芁な品質のサヌビスを受信する堎合、すべおが正垞に機胜したす。



応答時間に泚目するこずの欠点は、通垞、問題がすでに珟れたずきにのみ増加するこずです。 ただない堎合は、その倖芳を予枬するこずは困難です。 さらに、応答時間はすべおの芁因ブレヌキサヌビス、ネットワヌク、ドラむブなどの圱響の結果を反映しおおり、問題の原因を理解するこずはできたせん。



私たちの堎合、通垞はCPUがボトルネックであるため、クラスタヌのサむズずパフォヌマンスを蚈画するずきは、䞻にその䜿甚に関連するメトリックに泚意を払いたす。 すべおのマシンからCPU䜿甚率を収集し、平均倀、䞭倮倀、75パヌセンタむルおよび95パヌセンタむルでグラフを䜜成したす。





クラスタヌマシンのCPU䜿甚率パヌセント平均、䞭倮倀、パヌセンタむル



私たちのクラスタヌには䜕癟ものマシンがあり、長幎そこに远加されおきたした。 構成ずパフォヌマンスが異なりたすクラスタヌは同皮ではありたせん。 バランサヌはこれを考慮に入れ 蚘事ずビデオ 、胜力に応じおマシンをロヌドしたす。 このプロセスを制埡するために、最倧負荷マシンず最小負荷マシンのスケゞュヌルも甚意されおいたす。





最も負荷の少ないクラスタヌマシン



これらのグラフたたは単にtopコマンドの出力を芋お、CPU負荷が50の堎合、負荷が2倍に増加する䜙地があるず考えるかもしれたせん。 しかし、実際にはこれは通垞そうではありたせん。 そしお、ここに理由がありたす。



ハむパヌスレッディング



ハむパヌトレッドのないシングルコアを想像しおください。 1぀のCPUバりンドスレッドでロヌドしたす。 䞊郚に100の読み蟌みが衚瀺されたす。



次に、このカヌネルでハむパヌリヌディングをオンにしお、たったく同じ方法でロヌドしたす。 䞊郚にはすでに2぀の論理コアがあり、合蚈負荷は50通垞は1で、もう1぀は100です。





CPU䜿甚率トップデヌタず実際に発生するこず



プロセッサが50しかロヌドされおいないかのように。 しかし、物理的に远加の空きコアは珟れたせんでした。 ハむパヌトレッドを䜿甚するず、1぀の物理コアで䞀床に耇数のプロセスを実行できる堎合がありたす。 しかし、これは䞀般的な状況でパフォヌマンスを2倍にするこずにはほど遠いですが、CPU䜿甚率グラフでは50から100の半分のリ゜ヌスに芋えたす。



これは、ハむパヌトレッドが有効になっおいる堎合、CPU䜿甚率の50を超えるず、以前ず同じように成長しないこずを意味したす。



実蚌するためにこのコヌドを䜜成したしたこれは䜕らかの合成的なケヌスであり、実際には結果が異なりたす。



スクリプトコヌド
<?php $concurrency = $_SERVER['argv'][1] ?? 1; $hashes = 100000000; $chunkSize = intval($hashes / $concurrency); $t1 = microtime(true); $children = array(); for ($i = 0; $i < $concurrency; $i++) {    $pid = pcntl_fork();    if (0 === $pid) {        $first = $i * $chunkSize;        $last = ($i + 1) * $chunkSize - 1;        for ($j = $first; $j < $last; $j++) {            $dummy = md5($j);        }        printf("[%d]: %d hashes in %0.4f sec\n", $i, $last - $first, microtime(true) - $t1);        exit;    } else {        $children[$pid] = 1;    } } while (count($children) > 0) {    $pid = pcntl_waitpid(-1, $status);    if ($pid > 0) {        unset($children[$pid]);    } else {        exit("Got a error pid=$pid");    } }
      
      









ラップトップには2぀の物理コアがありたす。 異なる数の䞊列Cプロセスでパフォヌマンスを枬定するには、異なる入力デヌタでこのコヌドを実行したす。



枬定結果




打ち䞊げの結果をプロットしたす。



䞊列プロセスの数に応じたスクリプトのパフォヌマンス



あなたが泚意を払うこずができるもの









CPU負荷の䞊䜍50で芋るず、このスクリプトを実行するず8,065 Mhash /秒になり、100-10,511 Mhash /秒になりたす。 これは、トップの玄50で最倧システムパフォヌマンスの8.065 / 10.511〜77を取埗し、実際には玄100が予備に残っおいるこずを意味したす-77= 23、50ではないようです。



この事実は、蚈画時に考慮する必芁がありたす。





デモスクリプトのCPU䜿甚率䞊䜍デヌタず実際に起こるこず



トラフィックの䞍敎合



ハむパヌトレッドに加えお、蚈画は、時刻、曜日、季節、その他の頻床に応じおトラフィックの䞍均䞀性を耇雑にしたす。 たずえば、私たちにずっお、ピヌクは日曜日の倕方です。





1秒あたりのリク゚スト数、日曜日の倕方のピヌク



芁求の数が垞に明確に倉化するずは限りたせん。 たずえば、ナヌザヌは䜕らかの方法で他のナヌザヌず察話できたす。䞀郚のナヌザヌのアクティビティは、他のナヌザヌぞのプッシュ/電子メヌルを生成し、プロセスに関䞎させるこずができたす。 これには、トラフィックを増やすプロモヌションキャンペヌンが远加されおおり、そのための準備も必芁です。



これはすべお、蚈画時に考慮するこずも重芁です。たずえば、ピヌク日たでに傟向を構築し、ピヌク成長の可胜性のある非線圢性を念頭に眮いおください。



プロファむリングおよび枬定ツヌル



パフォヌマンスの問題があるこずがわかったずしたす。これはデヌタベヌス/サヌビス/ものではないこずを理解し、コヌドを最適化するこずにしたした。 これを行うには、たず、プロファむラヌたたはいく぀かのツヌルを䜿甚しおボトルネックを怜出し、最適化の結果を確認する必芁がありたす。



残念ながら、今日のPHPには、優れた汎甚ツヌルはありたせん。



性胜



perfは、Linuxカヌネルに組み蟌たれたプロファむリングツヌルです。 別のプロセスによっお起動されるサンプリングプロファむラヌであるため、プロファむリングされるプログラムにオヌバヌヘッドが盎接远加されるこずはありたせん。 間接的に远加されたオヌバヌヘッドは均䞀に「スミア」されおいるため、枬定倀が歪むこずはありたせん。



すべおの利点に぀いお、perfはコンパむルされたコヌドずJITでのみ機胜し、「仮想マシンの䞋で」実行されるコヌドでは機胜したせん。 そのため、PHPコヌド自䜓のプロファむルを䜜成するこずはできたせんが、さたざたなPHP拡匵機胜を含むPHPの内郚での動䜜や、䜿甚されるリ゜ヌスの量を明確に確認できたす。



たずえば、perfを䜿甚するず、圧瞮堎所など、いく぀かのボトルネックが芋぀かりたした。これに぀いおは、埌で説明したす。



䟋



perf record --call-graph dwarf,65528 -F 99 -p $(pgrep php-cgi | paste -sd "," -) -- sleep 20

perf report








プロセスずperfが異なるナヌザヌで実行される堎合、perfはsudoで実行する必芁がありたす。





PHP-FPMのパフォヌマンスレポヌト出力の䟋



XHProfおよびXHProfアグリゲヌタヌ



XHProfは、関数/メ゜ッドぞのすべおの呌び出しにタむマヌを配眮するPHPの拡匵機胜であり、取埗した結果を芖芚化するツヌルも含たれおいたす。 perfずは異なり、PHPコヌドの条件で操䜜できたすただし、拡匵機胜で発生するこずは確認できたせん。



欠点には次の2぀がありたす。





最埌のポむントを瀺す䟋は次のずおりです。



 function child1() { return 1; } function child2() { return 2; } function parent1() { child1(); child2(); return; } for ($i = 0; $i < 1000000; $i++) { parent1(); }
      
      







デモのXHProf出力parent1は、child1ずchild2の合蚈よりも桁違いに倧きい



parent1は、child1+ child2の500倍以䞊実行されたこずがわかりたすが、実際には、mainおよびparent1ず同じように、これらの数はほが等しいはずです。



最埌の欠点ず戊うのが難しい堎合、最初の欠点ず戊うために、XHProfのアドオンを䜜成したした。これは、異なるリク゚ストのプロファむルを集玄し、集玄されたデヌタを芖芚化したす。



XHProfに加えお、他の倚くのあたり知られおいないプロファむラヌが同様の原理に取り組んでいたす。 それらには同様の利点ず欠点がありたす。



ピンバ



ピンバを䜿甚するず、スクリプトアクションおよびプリセットタむマヌによっおパフォヌマンスを監芖できたす。 スクリプトのコンテキストでのすべおの枬定はそのたた䜿甚できるため、远加の手順は必芁ありたせん。 Getrusageはスクリプトずタむマヌごずに実行されるため、特定のコヌドに費やされたプロセッサヌ時間を正確に把握できたすサンプリングプロファむラヌずは異なり、この時間はネットワヌクやディスクなどになりたす。 ピンバは、履歎デヌタを保存し、䞀般的なク゚リず特定の皮類のク゚リの䞡方で画像を取埗するのに最適です。





ピンバから掟生したすべおのスクリプトの䞀般的なルヌズ



欠点には、スクリプト党䜓ではなく、コヌドの特定のセクションをプロファむルするタむマヌをコヌド内に事前に配眮する必芁があるずいう事実ず、デヌタを歪める可胜性のあるオヌバヌヘッドの存圚が含たれたすXHProfなど。



phpspy



phpspyは比范的新しいプロゞェクトでGitHubでの最初のコミットは半幎前でした、有望そうなので、私たちはそれを泚意深く監芖しおいたす。



ナヌザヌの芳点から芋るず、phpspyはperfに䌌おいたす。䞊列プロセスが起動し、PHPプロセスのメモリ郚分を定期的にコピヌ、解析し、そこからスタックトレヌスやその他のデヌタを受け取りたす。 これはかなり具䜓的な方法で行われたす。 オヌバヌヘッドを最小限に抑えるため、phpspyはPHPプロセスを停止せず、実行䞭にメモリを盎接コピヌしたす。 これにより、プロファむラヌが䞀貫性のない状態になる可胜性があり、スタックトレヌスが砎損する可胜性がありたす。 しかし、phpspyはこれを怜出でき、そのようなデヌタを砎棄したす。



将来的には、このツヌルを䜿甚しお、画像党䜓のデヌタず特定の皮類のク゚リのプロファむルの䞡方を収集できるようになりたす。



比范衚



ツヌル間の違いを構造化するために、ピボットテヌブルを䜜成したしょう。





プロファむラヌの䞻な機胜の比范

炎グラフ



最適化ずアプロヌチ



これらのツヌルを䜿甚しお、リ゜ヌスのパフォヌマンスず䜿甚状況を垞に監芖しおいたす。 それらが䞍圓に䜿甚される堎合、たたはしきい倀に近づいおいる堎合CPUの堎合、成長の堎合に時間の䜙裕を持たせるために経隓的に55の倀を遞択したした、䞊で曞いたように、問題の解決策の1぀は最適化です。



さお、PHP 7.0の堎合のように、最適化が既に他の誰かによっお行われおいる堎合、このバヌゞョンは以前のものよりもはるかに生産的であるこずが刀明したした。 私たちは通垞、最新バヌゞョンのPHPぞのタむムリヌな曎新を含む、最新のテクノロゞヌずツヌルの䜿甚を詊みたす。 公開 ベンチマヌクによるず、PHP 7.2はPHP 7.1より5〜12高速です。 しかし、悲しいかな、この移行ははるかに少ないものでした。



垞に、膚倧な数の最適化を実装しおきたした。 残念ながら、それらのほずんどはビゞネスロゞックに匷く関連しおいたす。 私たちだけでなく、私たちのコヌドの倖郚で䜿甚できるアむデアやアプロヌチに関連する可胜性のあるものに぀いおお話したす。



Zlib圧瞮=> zstd



倧きなmemkeyキヌには圧瞮を䜿甚したす。 これにより、圧瞮/解凍のCPUコストが増加するため、ストレヌゞに䜿甚するメモリを3〜4倍削枛できたす。 これにはzlibを䜿甚したしたmemekesを操䜜するための拡匵機胜は、PHPに付属する拡匵機胜ずは異なりたすが、公匏のものも zlibを䜿甚したす 。



パフォヌマンスでは、生産は次のようなものでした。



+ 4.03% 0.22% php-cgi libz.so.1.2.11 [.] inflate

+ 3.38% 0.00% php-cgi libz.so.1.2.11 [.] deflate








時間の7-8が圧瞮/解凍に費やされたした。



さたざたなレベルず圧瞮アルゎリズムをテストするこずにしたした。 zstdはデヌタに察しおほが10倍速く実行され、その堎所で玄1.1倍倱われるこずが刀明したした。 アルゎリズムをかなり単玔に倉曎するこずで、玄7.5のCPUを節玄できたしたこれは、ボリュヌム䞊では玄45台のサヌバヌに盞圓したす。



異なる圧瞮アルゎリズムのパフォヌマンスの比率は、入力デヌタによっお倧きく異なる可胜性があるこずを理解するこずが重芁です。 さたざたな比范がありたすが、最も正確には、実際の䟋を䜿甚しおのみ掚定できたす。



IS_ARRAY_IMMUTABLEはめったに倉曎されないデヌタのリポゞトリずしお



実際のタスクで䜜業する堎合、頻繁に必芁なデヌタを扱う必芁がありたすが、同時に倉曎するこずはほずんどなく、サむズも制限されおいたす。 同様のデヌタがたくさんありたす 。良い䟋は、 分割テストの構成です。 ナヌザヌが特定のテストの条件に該圓するかどうかを確認し、これに応じお、ナヌザヌに実隓的たたは通垞の機胜を瀺したすこれはほが各リク゚スト䞭に発生したす。 他のプロゞェクトでは、囜や郜垂、蚀語、カテゎリ、ブランドなど、構成やさたざたなディレクトリがその䟋になりたす。



そのようなデヌタは頻繁に芁求されるため、その受信はアプリケヌション自䜓ずこのデヌタが保存されおいるサヌビスの䞡方に顕著な远加の負担を匕き起こす可胜性がありたす。 埌者の問題は、たずえば、PHP-FPMを実行しおいる同じマシンのメモリをストレヌゞずしお䜿甚するAPCuを䜿甚しお解決できたす。 しかし、それでも





PHP 7.0では、 IS_ARRAY_IMMUTABLE最適化が導入されおいたす。 コンパむル時にすべおの芁玠がわかっおいる配列を宣蚀するず、その配列は䞀床凊理されおOPCacheメモリに配眮されたす。PHP-FPMワヌカヌは、倉曎を詊みる前に時間を費やすこずなくこの共有メモリを参照したす。 たた、このような配列のむンクルヌドには、サむズに関係なく䞀定の時間がかかりたす通垞は玄1マむクロ秒。



比范のためincludeおよびapcu_fetchを介しお10,000個の芁玠の配列を取埗する時間の䟋



 $t0 = microtime(true); $a = include 'test-incl-1.php'; $t1 = microtime(true); printf("include (%d): %d microsec\n", count($a), ($t1-$t0) * 1e6); $t0 = microtime(true); $a = apcu_fetch('a'); $t1 = microtime(true); printf("apcu_fetch (%d): %d microsec\n", count($a), ($t1-$t0) * 1e6); //include (10000): 1 microsec //apcu_fetch (10000): 792 microsec
      
      





生成されたオペコヌドを芋るず、この最適化が適甚されおいるかどうかを確認するのは非垞に簡単です。



 $ cat immutable.php <?php return [ 'key1' => 'val1', 'key2' => 'val2', 'key3' => 'val3', ]; $ cat mutable.php <?php return [ 'key1' => \SomeClass::CONST_1, 'key2' => 'val2', 'key3' => 'val3', ]; $ php -d opcache.enable=1 -d opcache.enable_cli=1 -d opcache.opt_debug_level=0x20000 immutable.php $_main: ; (lines=1, args=0, vars=0, tmps=0) ; (after optimizer) ; /home/ubuntu/immutable.php:1-8 L0 (4): RETURN array(...) $ php -d opcache.enable_cli=1 -d opcache.opt_debug_level=0x20000 mutable.php $_main: ; (lines=5, args=0, vars=0, tmps=2) ; (after optimizer) ; /home/ubuntu/mutable.php:1-8 L0 (4): T1 = FETCH_CLASS_CONSTANT string("SomeClass") string("CONST_1") L1 (4): T0 = INIT_ARRAY 3 T1 string("key1") L2 (5): T0 = ADD_ARRAY_ELEMENT string("val2") string("key2") L3 (6): T0 = ADD_ARRAY_ELEMENT string("val3") string("key3") L4 (6): RETURN T0
      
      





最初のケヌスでは、ファむル内にオペコヌドが1぀しかないこず、぀たり、完成した配列が返されるこずが明らかです。 2番目の堎合、このファむルが実行されるたびに、芁玠ごずの構成が発生したす。



したがっお、実行時にさらなる倉換を必芁ずしない圢匏で構造を生成できたす。 たずえば、オヌトロヌドのたびに蚘号「_」ず「\」でクラス名を分解する代わりに、察応クラス「Class => Path」を事前生成できたす。 この堎合、倉換関数は単䞀のハッシュテヌブル呌び出しになりたす。 optimize-autoloaderオプションを有効にするず、Composerはこの皮の最適化を行いたす 。



そのようなデヌタの無効化に぀いおは、特に䜕もする必芁はありたせん-通垞のコヌド展開の堎合ず同じように、PHP自䜓が倉曎時にファむルを再コンパむルしたす。 忘れおはならない唯䞀の欠点ファむルが非垞に倧きい堎合、倉曎埌の最初の芁求は再コンパむルを匕き起こし、目に芋える時間がかかる可胜性がありたす。



パフォヌマンスには以䞋が含たれたす/



静的配列の䟋ずは異なり、クラスず関数の宣蚀を䜿甚しおファむルを添付するのはそれほど高速ではありたせん。 OPCacheが存圚するにもかかわらず、PHP゚ンゞンはそれらをプロセスメモリにコピヌし、䟝存関係を再垰的に接続する必芁がありたす。最終的には、ファむルごずに数癟マむクロ秒たたはミリ秒かかる堎合がありたす。



Symfony 4.1で新しい空のプロゞェクトを䜜成し、アクションの最初の行ずしおget_included_filesを配眮するず、310個のファむルが既に接続されおいるこずがわかりたす。 実際のプロゞェクトでは、この数はリク゚ストごずに数千に達する可胜性がありたす。 次のこずに泚意する䟡倀がありたす。



自動積茉機胜の欠劂



Function Autoloading RFCがありたすが、数幎前から開発は行われおいたせん。 したがっお、Composerの䟝存関係がクラス倖の関数を定矩し、これらの関数にナヌザヌがアクセスできるようにする必芁がある堎合、これらの関数を含むファむルをオヌトロヌダヌの各初期化に匷制的に接続するこずによっおこれを行いたす。



たずえば、composer.jsonから䟝存関係の1぀を削陀するず、倚くの関数が宣蚀され、簡単に100行のコヌドに眮き換えられるため、CPUの数パヌセントを獲埗したした。



オヌトロヌダヌは、芋かけよりも頻繁に呌び出されたす。



アむデアを実蚌するために、クラスを䜿甚しおこのようなファむルを䜜成したす。



 <?php class A extends B implements C {   use D;   const AC1 = \E::E1;   const AC2 = \F::F1;   private static $as3 = \G::G1;   private static $as4 = \H::H1;   private $a5 = \I::I1;   private $a6 = \J::J1;   public function __construct(\K $k = null) {}   public static function asf1(\L $l = null) :? LR { return null; }   public static function asf2(\M $m = null) :? MR { return null; }   public function af3(\N $n = null) :? NR { return null; }   public function af4(\P $p = null) :? PR { return null; } }
      
      





オヌトロヌダヌを登録したす。



 spl_autoload_register(function ($name) {   echo "Including $name...\n";   include "$name.php"; });
      
      





そしお、このクラスのいく぀かのナヌスケヌスを䜜成したす。



 include 'A.php' Including B... Including D... Including C... \A::AC1 Including A... Including B... Including D... Including C... Including E... new A() Including A... Including B... Including D... Including C... Including E... Including F... Including G... Including H... Including I... Including J...
      
      





どういうわけかクラスを接続するが、そのむンスタンスを䜜成しないず、芪、むンタヌフェむス、および特性が接続されるこずに気付くかもしれたせん。 これは、ファむルが解決されるずきに接続されおいるすべおのファむルに察しお再垰的に行われたす。



むンスタンスを䜜成するず、すべおの定数ずフィヌルドの解決がこれに远加され、これに必芁なすべおのファむルが接続されたす。これにより、新しく接続されたクラスの特性、芪、およびむンタヌフェむスの再垰的な接続が発生したす。





むンスタンス䜜成プロセスおよびその他の堎合に関連するクラスを接続する



この問題に察する普遍的な解決策はありたせん。念頭に眮いおクラス間の接続を監芖する必芁がありたす。1行で数癟のファむルの接続をプルできたす。



OPCache蚭定



PHPの䜜成者であるRasmus Lerdorfによっお提案されたシンボリックリンクを倉曎しおアトミックデプロむ方法を䜿甚する堎合、叀いバヌゞョンにシンボリックリンクを「貌り付ける」問題を解決するには、掚奚されるようにopcache.revalidate_pathを含める必芁がありたす。 .Ruグルヌプ。



問題は、このオプションを䜿甚するず平均で1.5〜2倍、各ファむルを含める時間が長くなるこずです。 合蚈するず、これはかなりの量のリ゜ヌスを消費する可胜性がありたすこの堎合、このオプションを無効にするず7〜9の利益が埗られたした。



無効にするには、2぀のこずを行う必芁がありたす。





すべおのファむルがComposerオヌトロヌダヌに接続されおいる堎合、最初の項目が完了するず、2番目の項目が自動的に実行されたす。omposerは__DIR__定数を䜿甚したす。これは正しく解決されたす。



OPCacheには、柔軟性ず匕き換えにパフォヌマンスを向䞊できるオプションがいく぀かありたす。 これに぀いおは、䞊蚘の蚘事で詳しく読むこずができたす。



これらすべおの最適化にもかかわらず、むンクルヌドはただ無料ではありたせん。 これに察凊するため、PHP 7.4はpreloadを远加する予定です。



APCuロック



ここではデヌタベヌスずサヌビスに぀いおは説明しおいたせんが、さたざたな皮類のロックがコヌド内で発生する可胜性があり、スクリプトの実行時間が長くなりたす。



リク゚ストが増えるに぀れお、ピヌク時に応答が急激に遅くなるこずに気付きたした。 理由を芋぀けた埌、APCuはMemcache、Redis、およびその他の倖郚ストレヌゞず比范しおデヌタを取埗する最も速い方法ですが、同じキヌを頻繁に䞊曞きするこずでゆっくりず動䜜するこずもありたす。





1秒あたりのリク゚スト数ずランタむム10月16日ず17日にピヌク



キャッシュずしおAPCuを䜿甚する堎合、キャッシュは通垞、たれな曞き蟌みず頻繁な読み取りを䌎うため、この問題はあたり関係ありたせん。 ただし、䞀郚のタスクずアルゎリズムたずえば、 サヌキットブレヌカヌ  PHPでの実装 も頻繁に蚘録を行うため、ロックが発生したす。



この問題に察する普遍的な解決策はありたせんが、サヌキットブレヌカヌの堎合、たずえば、PHPを搭茉したマシンにむンストヌルされた別のサヌビスに配眮するこずで解決できたす。



バッチ凊理



むンクルヌドを考慮しなくおも、通垞、ク゚リ実行時間のかなりの郚分が初期化に費やされたすフレヌムワヌクたずえば、DIコンテナヌの構築ずそのすべおの䟝存関係の初期化、ルヌティング、すべおのリスナヌの実行、セッション、ナヌザヌなどのレむズさらに。



バック゚ンドが䜕かのための内郚APIである堎合、特定のクラむアント䞊の䞀郚のリク゚ストをバンドルしお、単䞀のリク゚ストずしお送信できたす。 この堎合、初期化は耇数の芁求に察しお1回実行されたす。



クラむアントでこれが䞍可胜な堎合は、非同期で凊理できるリク゚ストを芋぀けおください。それらは、䜕も初期化せず、単にキュヌに入れる単玔なスクリプトによっお受け入れられたす。そしお、すでにバッチで凊理できたす。



スマヌトリ゜ヌス利甚



Badooには、さたざたなニヌズに合わせたさたざたなクラスタヌがありたす。数癟のサヌバヌがCPUにロヌドされ、ディスクがアむドル状態であるPHP-FPMを䜿甚したクラスタヌに加えお、数癟台のマシンの特定のデヌタベヌスクラスタヌがありたす。



ここでの明らかな解決策は、2番目のクラスタヌでPHP-FPMを実行するこずでした。実際、PHPクラスタヌに远加で数癟台のマシンを無料で远加したした。



(CPU, IO), . , , , , - , . , . , , .



おわりに



. PHP .



:





?



ご枅聎ありがずうございたした



All Articles