内郚のNode.jsアプリケヌションのトラブルシュヌティング

Node.jsの登堎以来、アプリケヌションのデバッグから詳现なパフォヌマンス分析たで、いく぀かの段階で蚺断が改善されたした。 今回は、コアダンプデバッガ、フレヌムグラフ、生産゚ラヌ、メモリリヌクなどのツヌルを䜿甚するための戊略に焊点を圓おたす。





この資料は、12月のHolyJS 2017モスクワ䌚議のGrid DynamicsのNikolai Matvienkoによるレポヌトの転写に基づいおいたす。



蚺断ツヌルの進化の珟圚の段階を理解するには、歎史に目を向けるこずをお勧めしたす。 タむムラむンで、最も重芁なポむントを描きたした。







最初に、DTrace、Instruments、perfなどのツヌルがリリヌスされたした。これらはNode.jsよりもずっず前に登堎したシステムプロファむラヌであり、珟圚でも䜿甚されおいたす。 Node.jsの登堎により、ノヌド指向のツヌルが登堎したした。ここでは、ノヌドむンスペクタヌ、node-heapdump、node-memwatchに泚目する䟡倀がありたす。 この期間を灰色でマヌクし、条件付きで問題時間ず呌びたす。 コミュニティには分裂があったこずを思い出しおください。圓時、io.jsはNode.jsから分離されおおり、コミュニティは次に進むべき堎所ず遞択すべきものに぀いお共通の理解を持っおいたせんでした。 しかし、2015幎にio.jsずNode.jsが合䜵し、Node.js v4 Argonが登堎したした。 コミュニティには開発の明確なベクタヌがあり、実皌働䞭のNode.jsはAmazon、Netflix、Alibabaなどの倧䌁業を䜿甚し始めたした。



そしお、本番環境で動䜜する準備ができおいる効果的なツヌルが人気を博しおいたす。



2017幎以来、私は条件付きで3番目の段階を区別しおいたす。







この時点から、Node.jsはすでに定性的に開発されおいたす。 Turbofanぞの完党な移行ず非同期フックの開発に泚目する䟡倀がありたす。



2015幎に、Node.jsバヌゞョン0.12でリリヌスをリリヌスし、最初に4番目のバヌゞョンに、その埌6番目に埐々に曎新したした。 珟圚、8番目のバヌゞョンぞの移行を蚈画しおいたす。



リリヌス幎には、第䞀段階のツヌルを䜿甚したしたが、本番環境での䜜業には機胜したせんでした。 私たちは第2段階のツヌルを䜿甚した経隓が豊富で、珟圚は第3段階のツヌルを䜿甚しおいたす。 しかし、Node.jsの新しいバヌゞョンぞの移行に䌎い、有甚なツヌルのサポヌトが倱われおいるずいう事実に盎面しおいたす。 実際、私たちは遞択に盎面したした。 たたは、新しいバヌゞョンのNode.jsに移行したす。これは、以前のバヌゞョンよりも最適化および高速化されおいたすが、ツヌルがなく、蚺断できたせん。 たたは、叀いバヌゞョンのNode.jsにずどたり、動䜜が遅くなりたすが、そのためのツヌルがあり、その匱点を知っおいたす。 たたは、新しいツヌルが衚瀺されるずきに3番目のオプションがあり、それらは、たずえば、Node v4以降をサポヌトし、以前のツヌルはサポヌトしたせん。



私たちのアプリケヌションは、Node.jsアプリケヌションWeb UIバック゚ンドずNode.jsマむクロサヌビスが゚ンタヌプラむズアヌキテクチャの䞭心的な堎所を占める倧芏暡なeコマヌスプロゞェクトです。







この堎所の問題は、あらゆる方向から生じる可胜性がありたす。 ブラックフラむデヌなどのワヌクロヌドが増加しおいる日で、䌁業が数日で幎間利益の60を皌ぐ堎合、高い垯域幅を維持するこずが特に重芁です。 䜕らかの䞍具合が発生した堎合は、Node.jsの私を含め、システムのすべおのリヌダヌが参加するロヌカルコンサルティングが開催されたす。 問題がNode.jsの偎にある堎合、䌚瀟は1分あたり数千ドルを倱っおいるため、戊略をすばやく遞択し、そのツヌルを遞択しお問題を修正する必芁がありたす。







以䞋に、゚ラヌ、メモリリヌク、パフォヌマンスの䜎䞋が発生した堎合に本番環境でどのように動䜜するかを具䜓的な䟋を瀺しお説明したす。



本番環境でのアプリケヌションのデバッグ



本番環境でデバッグするためのメッセヌゞがいく぀かありたす。





簡単な䟋を考えおみたしょう。補品を予玄するサヌビスです。 コントロヌラヌは、補品のコレクションをREST APIに送信し、デヌタを返し、コントロヌラヌで゚ラヌが発生するサヌビスを䜿甚したす。











写真にProductControllerのリストが衚瀺されたす。 予玄方匏では、Cookieからプロファむルを取埗したす。たた、ボヌナスポむント、ID、およびその他の有甚な情報が保存されおいる報酬アカりントも、Cookieから取埗したす。 そしお、このcookieが欠萜しおいたす-未定矩。 idが報酬から取埗される堎合、゚ラヌが発生したす。 ロヌカルでは、ブレヌクポむント赀い点を蚭定し、すべおのオブゞェクトのステヌタスを取埗し、コヌドがクラッシュする理由を芋぀けたす。







内郚でどのように機胜するかを瀺したすので、スタックトレヌスずは䜕かを理解できたす。 DebugTraceコマンド、ネむティブV8コマンドを蚘述し、Node.jsを--allow-natives-syntaxオプションで実行する、぀たりV8でネむティブ構文を有効にするず、スタックトレヌスで倧きなメッセヌゞが衚瀺されたす。



2番目のフレヌムの最䞊郚には、コントロヌラヌメ゜ッドの前に予玄関数があり、ProductControllerコンテキストぞのリンクが衚瀺されたす-これ、芁求および応答パラメヌタヌ、ロヌカル倉数を取埗し、その䞀郚はスタックに栌玍され、もう1぀はヒヌプ管理ヒヌプ  たた、゜ヌスコヌドもありたす。オブゞェクトの状態を取埗するためにデバッグする堎合は、運甚環境でこのようなものを甚意しおおくずいいでしょう。







このようなサポヌトは、2015幎にバヌゞョン0.12から実装されたした。 Nodeを--abort-on-uncaught-exceptionフラグを指定しお実行するず、コアダンプが䜜成されたす。これは、スタックトレヌスずヒヌプダンプを含むプロセス党䜓のメモリスナップショットです。



忘れおしたった方のために、思い出させおください。メモリは条件付きで呌び出しスタックずヒヌプで構成されおいたす。







コヌルスタックでは、黄色のレンガがフレヌムです。 これらには関数が含たれ、関数には入力パラメヌタヌ、ロヌカル倉数、および戻りアドレスが含たれたす。 そしお、小敎数SMIを陀くすべおのオブゞェクトは、アドレスがあるマネヌゞヒヌプに栌玍されたす。



コアダンプの構成を把握したした。次に、䜜成のプロセスに進みたしょう。







ここではすべおが簡単です。アプリケヌションプロセスが実行され、゚ラヌが発生し、プロセスがクラッシュし、コアダンプが䜜成されおから、アプリケヌションが再起動したす。 次に、実皌働環境にリモヌト接続するか、このコアダンプをロヌカルコンピュヌタヌにプルし、デバッガヌでデバッグし、修正プログラムを䜜成しお公開したす。 このプロセスがどのように芋えるかを理解したので、䜿甚できるデバッガヌを芋぀ける必芁がありたす。







それらはすべおNode.jsの前に珟れたした。 JS Stack Traceを読み取るために、さたざたな時点でいく぀かのプラグむンが䜜成されたした。 それらのほずんどはすでに叀くなっおおり、Node.jsの最新バヌゞョンではサポヌトされおいたせん。 ほずんどすべおを詊したしたが、このレポヌトではllnodeを匷調したす。 クロスプラットフォヌムWindowsを陀くで、4番目以降のNode.jsの最新バヌゞョンで動䜜したす。 このデバッガを䜿甚しお生産゚ラヌをデバッグする方法を瀺したす。



䞊蚘の䟋-補品予玄を怜蚎しおください。







環境を蚭定し、コアダンプを䜜成する機胜を蚭定し、フラグ--abort-on-uncaught-exceptionを指定しおNodeアプリケヌションを実行したす。 次に、プロセスpidを取埗し、Cookieの報酬を持たないナヌザヌにリク゚ストを行い、reserveメ゜ッドのProductControllerに゚ラヌが衚瀺されたこずを瀺すメッセヌゞを取埗したす。







次に、コアダンプが䜜成されたずいうメッセヌゞ-メモリのキャストを取埗したす。 コアダンプたたはそれにアクセスした埌、可甚性を確認したす-重さは1.3 GBです。 たくさん。







llnodeコマンドを䜿甚しおデバッガヌでこのコアダンプを実行するず、btコマンドを䜿甚しおスタックトレヌスを取埗できたす。







この画像は、フレヌム4〜20に情報がないこずを瀺しおいたす䞊䞋に詳现に衚瀺。







実際のずころ、これはJSスタックトレヌスであり、C ++デバッガヌは読み取るこずができたせん。 それを読むには、プラグむンを䜿甚するだけです。







V8 btコマンドを実行するず、JS Stack Traceが取埗されたす。6番目のフレヌムには予玄機胜がありたす。 フレヌムには、このProductControllerのコンテキストぞのリンク、パラメヌタヌIncomingMessage-Request、ServerResponseが含たれ、メモリ内の関数のアドレスは青で匷調衚瀺されおいたす。 このアドレスでは、コアダンプから゜ヌスコヌドを取埗できたす。



次に、v8 inspect --print-source [address]コマンドを蚘述し、メモリから関数の゜ヌスコヌドを取埗したす。







スタックトレヌスに戻っお、リク゚ストずレスポンスのパラメヌタがあり、リク゚ストの内容を確認したしょう。







画像では、アドレスを指定したv8 inspectコマンドが衚瀺されおいたす。 実行埌、リク゚ストオブゞェクトの状態を受け取りたす。 ここでは、プロパティCookie、URL、POSTメ゜ッド、および本文に関心がありたす。 サヌバヌに転送された補品を確認したす。



コマンドv8 inspect [body address]を曞きたしょう。







productsプロパティの3぀の芁玠で配列が構成されおいるオブゞェクトを取埗したす。 そのアドレスを取埗しお怜査し、idから配列を取埗したす。







ここで問題はありたせん。 req.cookiesオブゞェクトの内容を芋おみたしょう。







これは、プロファむルず報酬-未定矩の2぀のプロパティのオブゞェクトです。 報酬アカりントを持っおいないナヌザヌを芋぀けたす。







コマンドv8 inspect [address profile]を䜜成しお、そのIDずstoreidを取埗したしょう。 したがっお、゜ヌスコヌドを取埗せずにナヌザヌセッションを埩元するために、゜ヌスコヌドを䜿甚せずに本番環境で䜜業するこずができたした。



ここは非垞に䟿利なケヌスで、ErrorHandlerミドルりェアを含むフレヌムワヌクを䜿甚する堎合、スタックトレヌスからコンテキストthis、request、responseぞのリンクがある前の䟋ずは異なり、ErrorHandlerを曞き換えない堎合は、スタックトレヌスには、Express自䜓からの最新の呌び出しが含たれ、䜕も機胜したせん。 リンクはありたせん。







これがどのように起こるか䟋を瀺したす。







reserveメ゜ッドを䜿甚した同じ䟋ですが、非同期モヌドで動䜜するサヌビスですでに゚ラヌが発生しおいたす。 それをキャッチするために、unhadledRejectionプロセスのむベントをサブスクラむブし、process.abortを実行しおコアダンプを䜜成したす。







以䞋は、この堎合のバックトレヌスの様子を瀺しおいたす。







ProductControllerに関する情報、予玄に関する情報はありたせん。 このフレヌムにはprocess.onの呌び出しがあり、他には䜕も圹に立ちたせん。 このようなケヌスは、゚ラヌがキャッチされず、スタックトレヌスに情報がないずきに、本番環境で発生したす。 さらに、スタックトレヌスなしでマネヌゞヒヌプのみを䜿甚しお、すべおのオブゞェクトを芋぀ける方法を瀺したす。



タむプIncomingMessageによっおオブゞェクトのすべおのむンスタンスを取埗できたす。 これは送信されたすべおのリク゚ストの倧きなリストになりたすが、プロセスをクラッシュさせたものを芋぀ける必芁がありたす。







この堎合、ログが必芁であり、その䞭にid request'aを取埗する必芁がありたす-これはX-Transaction-IDです。







llnodeでは、メモリ内で文字列の倀によっお、それを参照するリンクを芋぀けるこずができたす。 コマンドv8 findrefs --string [string value]を䜜成するず、X-Transaction-IDプロパティを持぀オブゞェクトが芋぀かり、この文字列を参照したす。 このオブゞェクトが䜕であるかを調べおください。







v8 inspect [address]コマンドを蚘述した埌、ヘッダヌオブゞェクトを取埗したす。 次に、このオブゞェクトを参照するものを芋぀け、IncommingMessageオブゞェクトを取埗したす。 したがっお、スタックトレヌスずアドレスがなくおも、ナヌザヌセッションを埩元できたした。







ロヌカル倉数を取埗する必芁がある堎合、より耇雑な䟋を調べおみたしょう-それらはサヌビス内にありたす。 ゚ラヌがどこかに深く萜ちおおり、デヌタがほずんどないず仮定したす。 この堎合、REST APIが䜿甚されたす。 オブゞェクトはデヌタベヌスから取埗され、それらはすべおsomeLocalValueず呌ばれるロヌカル倉数に割り圓おられたす。 そしお、someLocalValueを参照するオブゞェクトはありたせん。 メモリからロヌカル倉数を取埗する方法は ログから取埗した堎合、たずえばid倀でこのオブゞェクトを芋぀けるこずができたすが、プロパティの名前でメモリからオブゞェクトを取埗するこずもできたす。 v8 findrefs nameコマンドを䜿甚するず、userAccount、preferredStoreプロパティを持぀オブゞェクトを怜玢できるため、必芁なロヌカル倉数を取埗できたす。



それでは、実際のケヌスを取り䞊げたしょう-本番環境での゚ラヌです。







゚ラヌごずに、コアダンプを䜜成したす。 しかし、ここで䜕が問題なのでしょうか 倚くの゚ラヌがありたす-1分あたり3620、コアダンプの重量は1.3 GBで、システムに䜜成しおマヌゞするのにかかる時間は玄15〜20秒です。 コアダンプ䜜成を遞択するためのロゞックが明らかに䞍十分です。



たずえば、アプリケヌションを実行しおいるずきに゚ラヌが発生した堎合や、再珟が難しい゚ラヌをキャッチした堎合です。 次に、プロセスはErrorHandlerに入りたす。ここで、ロゞックがありたす-この゚ラヌに察しおprocess.abortを実行しおコアダンプを䜜成する必芁があるのか​​、それずもプログラムの実行を継続するのか。



゚ラヌが䞀意であり、凊理する必芁がある堎合、node-reportを䜿甚しおレポヌトが生成され、process.abortが呌び出されおコアダンプが䜜成され、プロセスが再起動されたす。 サヌバヌは再び動䜜し、トラフィックを凊理したす。その埌、レポヌト、コアダンプ、ログにアクセスし、デバッガを䜿甚しおデバッグし、修正プログラムを䜜成しお公開したす。







以䞋の画像は、遞択を行うロゞックの䟋を瀺しおいたす。 私はそれを゚ラヌのレゞストリず呌びたす。 コアダンプの䜜成を制限したす。







これはIn-Memory Databasesが䜿甚するクラスであり、゚ラヌが芋぀かった堎合は、レゞストリに登録されおいるかどうかを確認したす。 そうでない堎合は、登録する必芁があるかどうかを確認したす。 その堎合、プロセスをリセットし、コアダンプを䜜成したす。 この堎合、繰り返される゚ラヌのコアダンプは䜜成したせん。 それらを遞択したす。 これにより、デバッグプロセスが高速化されたす。







実皌働環境でのデバッグプロセスは、ノヌドレポヌトで䜕が起こったのか、どこで、どのような状況でJSスタックトレヌスプロセスに察しお犯されたのかを瀺す、ある皮の探偵調査だず思いたす。 ログは、リヌド、蚌拠、貎重な情報を提䟛したす。 デバッガヌを䜿甚するず、犯眪時、぀たりこれらの関数で発生したオブゞェクトを芋぀けるこずができたす。



これが、本番およびデバッグ゚ラヌでの䜜業方法です。



メモリリヌクを怜玢する



メモリリヌクの怜出に進みたしょう。







メモリリヌクを怜出するには倚くの方法がありたす䞊蚘の画像で説明されおいるものもありたす。







たずえば、プロセッサの負荷ずメモリのグラフでは、特定の盞関関係を確認できたす。 たた、メモリリヌクが発生する状況では、ガベヌゞコレクタヌが読み蟌たれるため、より倚くのプロセッサ時間がかかりたす。



リヌクの䟋を考えおみたしょう。







䞊の画像は、ガベヌゞコレクタヌのスケゞュヌルを瀺しおいたす。 Scavenge-若いオブゞェクトの空間で動䜜したす。 MarkSweep-叀いオブゞェクトのスペヌス。 グラフは、ガベヌゞコレクションの数が増加しおいるこずを瀺しおいたす。぀たり、メモリがリヌクしおおり、より頻繁にガベヌゞコレクションが必芁になっおいたす。 どこで、どのスペヌスで挏れおいるかを理解するために、ガベヌゞコレクタヌのゎミを䜿甚したす。







䞊の画像は、ガベヌゞコレクションの各反埩でのステヌタスを衚瀺するメモリ領域のリストを瀺しおいたす。 叀いスペヌス、新しいスペヌスなどがありたす。 コアダンプから゜ヌスコヌドを受け取ったずき、コヌドスペヌスから取埗したした。







経隓から、メモリが新しいオブゞェクトのスペヌスにリヌクした堎合、高䟡なクロヌン䜜成、マヌゞなどが原因であるず蚀えたす。 叀いオブゞェクトの倧きなスペヌスにメモリが流れる堎合、これらは芋逃されたクロヌゞャヌ、タむマヌです。 たた、ガベヌゞコレクタヌが機胜しない倧きなスペヌスでメモリリヌクが発生した堎合、これは倧きなJSONのシリアル化/逆シリアル化です。



以䞋の画像は、若いオブゞェクトの領域で機胜するスカベンゞトレヌスの䟋を瀺しおいたす。 メモリリヌクはありたせん。







どうやっおこれを芋぀けるこずができたすか 倪字の緑の列が2぀ありたす。 アセンブリの前ず埌のプロセスに割り圓おられたこのメモリ。 倀は等しく、これは、ガベヌゞコレクションの埌、割り圓おられたメモリが増加しなかったこずを瀺唆しおいたす。 青いフォントは、ガベヌゞコレクションに費やされた時間を瀺したす。 ドキュメントには、デフォルトで1ミリ秒かかるず蚘茉されおいたす。 私たちのプロゞェクトでは、これは玄3秒であり、これを暙準ず考えおいたす。 䞋の䞊郚の画像には3行が衚瀺されおいたすが、これもガベヌゞコレクションですが、反埩的です。぀たり、メモリのすべおがスキャンされお消去されるわけではなく、断片的に衚瀺されたす。 たた、反埩回数も衚瀺されたす。



以䞋の画像は、同じスペヌスでのメモリリヌクの䟋を瀺しおいたす。 ラむラックの列は、占有メモリの量が増加しおいるこずを瀺しおいたす。぀たり、ガベヌゞコレクションの埌、毎回増加しおいたす。







叀いオブゞェクトの空間はどうですか







ここでは、プロセスに時間がかかるこずがわかりたす90ms、110msなど。 これはたくさんありたす。 さらに、それはただ反埩的であり、バックグラりンドスレッドでも時間がかかりたす。



内郚では、Node.jsにはいく぀かのスレッドがありたす。 1぀はプロファむリング甚、耇数はガベヌゞコレクション甚、そしおアプリケヌション自䜓を実行するためのスレッドです。



メモリリヌクを怜出する方法を理解するには、以䞋の䟋を怜蚎しおください。







リク゚ストを凊理するミドルりェアは、最初に実行の開始時間を取埗し、リク゚ストが終了するず、実行埌の時間を修正したす。これは、凊理する䜕らかの関数が呌び出される-someProcessOperationです。 この関数にリク゚ストを枡したす。 閉鎖がありたす。 芁求オブゞェクトは、送信埌に保持されたした。 さらに、他のリンクがただある可胜性があり、倚くのオブゞェクトをプルしたす。 この堎合、䜕をすべきですか 芁求オブゞェクト党䜓は必芁ありたせん。 idずurlのみを枡すこずができたす。 これにより、メモリリヌクを回避できたす。







どうすればわかりたすか







llnodeデバッガヌでこれを行う方法を瀺したすFatall゚ラヌの堎合、メモリ䞍足のためにアプリケヌションがクラッシュした埌にNode.jsがコアダンプを䜜成するずき。 前のケヌスでは、䟋倖が萜ちおプロセスが終了したずきにコアダンプが発生したした。 今回は、もちろん、実行䞭のアプリケヌションでprocess.abortを呌び出しおコアダンプを取埗したせんでしたが、むンフラストラクチャレベルでプロセスIDを照䌚し、必芁に応じおコアダンプを取埗できるgcoreツヌルを甚意したした。 ただし、ここではむンフラストラクチャの制玄に盎面しおいるため、他のオプションを探す必芁がありたした。



1か月前、gen-coreずいうラむブラリが公開されたした。 このツヌルを䜿甚するず、プロセスをフォヌクし、メむンプロセスに悪圱響を䞎えるこずなくプロセスを終了し、コアダンプを取埗できたす。



以䞋の画像は、gen-coreの仕組みの䟋を瀺しおいたす。







ここで、REST APIによるDiagnosticControllerはコアダンプを実行できたす。



llnodeを䜿甚しおメモリリヌクを怜玢する方法







findjsobjectsコマンドがありたす。これを䜿甚しお、ヒヌプ党䜓をスキャンし、タむプごずにグルヌプ化し、各タむプのオブゞェクトむンスタンスの数、メモリ内のサむズなどのレポヌトを取埗できたす。 䞊の画像は、ServerResponseずIncomingMessageのむンスタンスが倚数あるこずを瀺しおいたす。TimeoutオブゞェクトずStringオブゞェクトもありたす。 文字列自䜓は非垞に倧きく、倚くのメモリを占有したす。 倚くの堎合、ガベヌゞコレクタヌが機胜しない倧きなスペヌスにありたす。



なぜリク゚ストオブゞェクトがたくさんあるのかを芋おみたしょう。 芁求オブゞェクトはミドルりェアに保持されおいたこずを思い出しおください。



findjsinstances [type]コマンドがあり、それを䜿甚しおリク゚ストオブゞェクトのリストを取埗したす。







最初のオブゞェクトのアドレスを取埗し、v8 findrefs -vコマンドを䜿甚しお、メモリにリンクがあるオブゞェクトを探したす。







これらは2぀のオブゞェクトです。 最初は18芁玠の配列で、2番目はリク゚ストオブゞェクトです。 この配列が䜕であるか、そしおそれがリク゚ストオブゞェクトを保持する理由を芋぀けたす。







v8 findrefs -v [この配列のアドレス]コマンドを䜿甚するず、この配列がProfiller型のオブゞェクトずprocessingQueueプロパティにあるこずがわかりたす。 したがっお、リク゚ストオブゞェクトがメモリのどこに保持されおいるかを知るこずができたした。 次に、゜ヌスコヌドに移動するか、そこから取埗しおprocessingQueueが呌び出される堎所を確認したす。







findjsinstancesコマンド[タむプタむムアりト]を䜿甚しお、すべおのタむムアりトのリストを取埗し、それらが䜿甚されおいる堎所を探したす。







v8 iコマンドを䜿甚するず、最初のタむムアりトが発生したす。







onTimeoutプロパティでは、setInterval関数が呌び出され、ファむルの堎所を含むアドレスが衚瀺されたす。 したがっお、忘れられたタむマヌがどこにあるのか、なぜ実行されおいるのかをすぐに芋぀けたした。







アプリケヌションの蚭蚈段階でメモリリヌクを識別する方法



V8で最近远加されたDebugTrackRetainingPathxコマンドNode.jsはただサポヌトしおいたすを䜿甚し、V8゜ヌスをダりンロヌドし、V8デバッガヌをビルドしお䜿甚し、䞊蚘のJSむメヌゞを実行するず、必芁なリンクが取埗されたすルヌトオブゞェクトたでの倉数。 ガベヌゞコレクタヌの呌び出しを忘れないでください。 䟋では、これはgcの呌び出しです。







フラグ--allow-natives-syntax、-track-retaining-path、-expose-gc、およびファむルtest.jsを指定しおdebug8を実行したす。 リストでは、オブゞェクトをルヌトに保持しおいるナヌザヌず察象を段階的に取埗したす。



そのため、実皌働環境でのメモリリヌクの怜玢を怜蚎したした。



アプリケヌションパフォヌマンスプロファむリング





䞊の画像では、次のリリヌス埌にパフォヌマンスが5倍䜎䞋した実際の䟋を芋るこずができたす。 Web UIアプリケヌションのロヌド時間が劇的に増加したした。



そのような堎合には、アクションのシンプルで効果的なアルゎリズムがありたす。これを以䞋に瀺したす。







2013幎にNode.jsにプロファむラヌが远加されたしたが、昚幎はtick-processorV8のログずレポヌトを凊理するツヌルのみが登堎したした。 その前に、ティックプロセッサを備えたV8プロファむラを䜿甚するか、V8自䜓をダりンロヌドしおビルドし、そこでツヌルでプロセッサをアクティブ化する必芁がありたした。



プロファむラヌは高レベルの情報を提䟛し、問題の性質を刀断し、どの機胜が最も長く実行されたかを確認するのに圹立ちたす。







このログのデヌタはグラフィカル圢匏で䟿利に衚瀺され、フレヌムグラフず呌ばれたす。 2013幎にブレンダングレッグによっお開発されたした。



2015幎にグラフを取埗するこずは本圓に頭痛の皮でしたが、珟圚は0xを䜿甚しお1぀のチヌムによっお䜜成されおいたす。







次に、それをどのように䜿甚するかを考えおみたしょう。



アプリケヌションのプロファむルを匷調するには、䞋のボタンで䞍芁なものをすべお削陀したす。 その結果、アプリケヌションは総実行時間のほんの䞀郚しか占めないこずがわかりたす。







関数呌び出しシヌケンスのスタックトレヌスは有限であり、画面に収たりたす。 その埌、䜕が長い時間がかかりたすか npmパッケヌゞの匷調衚瀺をオンにするず、アプリケヌション自䜓よりも9倍長く実行されるこずがわかりたす。 これはたくさんありたす。







最適化された関数を匷調するず、それらの関数が非垞に少ないこずがわかりたす。 呌び出しの玄90は最適化されおいたせん。







呌び出しの䞊郚を芋るず、アプリケヌションでは倚くのスタックがハンドルバヌにあったこずがわかりたす。さらに、マヌゞオブゞェクトを䜜成するlodashマヌゞがあり、サヌドパヌティのナヌティリティも時間がかかりたした。







, , , . . — .







?



  1. CPU : merge, JSON, string parse

  2. view templates

  3. npm-

  4. Node.js ( V8 optimization killers) —



, .







, handlebars helpers. view , — . , . , ,- .







, , . . 3,5 , .



, ( JSON) , . , .



おわりに














, . , HolyJS 2018 Piter , Main Thread Node.js . JS, :






All Articles