JVM 関連の例外は、最前線の開発者にとって常に頭痛の種でした。なぜなら、ビジネス コードの場合、JVM の動作は基本的にブラック ボックスだからです。例外が発生した場合、直感的に問題を確認して見つけることは困難です。だからこそ、その内部ロジックを研究する必要があるのです。 この記事では、最近のオンライン JVM メモリ リークの例を使用して分析します。 パート1 オンラインサーバーが警報を発令ある日、同僚が助けを求めて私に来ました。あるシステムでは、何の警告もなく一連のアラームが発生していることが判明しました。旧世代のマシンのメモリ使用量がしきい値を超えました。 1.1 まずはパフォーマンスを見る 旧世代のメモリ使用量 7 月中旬までは、メモリ使用量は比較的正常であり、各 GC で古い世代のオブジェクトの大部分をリサイクルできたことがわかります。 月の中旬以降、旧世代のメモリが徐々に増加し、解放できなくなります。明らかに、これはオブジェクトが正常にリサイクルされていないことが原因であるはずです。 メモリリーク〜 1.2 何をすべきか 新しく立ち上げたプロジェクトでこのような問題が発生した場合、影響は比較的小さいため、コードを直接ロールバックして出血を止めることが最優先となります。 しかし、このプロジェクトは明らかに何日もオンラインになっており、その間にどれだけの要求があったかは不明です。また、最近のトラフィックの増加により問題が発生しているため、トラフィックが顧客に開放されたことを意味します。 ロールバックは不可能なので、急いで問題を特定し、オンラインで修正してください。 パート2 位置決めの問題一般的な手順:
ただし、ダンプされたファイルは 10G を超えて大きすぎるため、MAT は基本的に無力であり、手動で分析するために印刷することしかできません。 2.1 問題コードを見つける jmap 結果ビュー 幸いなことに、異常な物体は非常に明白です。 Point オブジェクトと GeoDispLocal オブジェクトのインスタンスは数百万あります。まず、これら 2 つのオブジェクトがコード内でどのように使用されるかを見てみましょう。
それらはすべて現在のキャッシュ CacheMap に格納されており (メモリ リークの一般的な原因は、静的コレクションによって保持され、リサイクルできないことです)、ダンプ ファイル内の CacheMap.Entry も非常に高くなります。 CacheMap が最優先の容疑者です。まず、このキャッシュ クラスがどのようなものかを見てみましょう。
内部的には LRU 機能を備えたマップに依存します。どのように実装されますか?
内部的には、LinkedHashMap を使用して実装された LRU キャッシュです。コメントによると、容量制限があり拡張性のないMAPを構築するのが目的だそうです(Baiduで調べたらネット上の実装と全く同じですね~)。では、実際の状況は本当に想像通りなのでしょうか? 2.2 LinkedHashMap によって実装された LRUMap は便利ですか? 容量と拡張に関する設定を見てみましょう。なぜ設計者は LRUMap が拡張しないと考えるのでしょうか?
実際の使用法に応じてインスタンス化してみましょう。
LRU 条件関数がオーバーライドされるため、サイズが 6000 を超えると LRU 置換が実行されます。したがって、理論上、サイズが 8110 に達することはありません。 同時読み取り/書き込み競合を解決するにはどうすればよいでしょうか?
同時実行時の読み取り/書き込み競合を解決するために、設計者はクエリおよび変更メソッドにロックを追加しました。パフォーマンスを考慮するために、読み取り/書き込みロックが使用されました。つまり、読み取りロックは get 中に追加され、書き込みロックは put/remove 中に追加されました。 全体的な設計により、LRUMap の固定容量と同時操作の問題がうまく解決されているように見えますが、真実は何でしょうか? 実際、この問題はずっと以前から分析されてきました[1]。これは、LinkedHashMap が読み取り/読み取り操作を実行するときに、LRU を維持するために要素を変更するため、つまり、要素をリンク リストの末尾に移動するためです。これは読み取り書き込み同時実行の問題につながりますが、この説明は漠然とした感じがするので、これに基づいて読み取り書き込み同時実行の問題をより詳しく説明することにしました。 2.3 LinkedHashMap メモリリーク解析 読み取り/書き込みロックが追加されても機能しないのはなぜですか? ここでは、読み取り/書き込みロックの概念と適用可能なシナリオを明確にする必要があります。読み取り/書き込みロックを使用すると、複数のスレッドが読み取りロックを共有できるため、書き込みよりも読み取りが多い状況に適しています。 (読み取り操作によってストレージ構造が変更されないことが前提です) したがって、get 操作で問題が発生します。 LinkedHashMap の get 操作は、LRU 機能を実装するために書き直されます。取得後、現在のノードはリンク リストの末尾に移動されます。 さあ、同志たち、これは明らかに書き込み操作なので、読み取りロックを追加することはまだ役に立ちますか? つまり、複数のスレッドが入り込み、変更が行われると、どのような影響があるのでしょうか?同時実行の問題は発生しないでしょうか? 次に、ノード移動コードを比較して、マルチスレッドでの同時実行の問題を詳細に分析します。 最後に到達したらノードを移動する 実際の逆アセンブリ分析は次のとおりです。マルチスレッドの状況でメモリ リークが発生する理由は次のとおりです。 タイムスライスでのマルチスレッドの取得実行 スレッド 1 が最初の 2 つのステートメントを実行した後、タイム スライスを放棄したことがわかります。スレッド 2 が p.after=null を実行すると、タイム スライスが再度放棄されました。このように、a は次の <2,B> ノードになるはずでしたが、マルチスレッドでは null になりました。最終的に、次の 2 つのノードがリンク リストから除外され、削除操作がそれらに到達できず、メモリ リークが発生しました。 認証コードはここには掲載しません。ご興味がございましたら、ぜひご自身でお試しください。 パート3の要約問題が特定されたので、このメモリ リークをどのように修正すればよいでしょうか? 読み取り/書き込みロックはミューテックス ロックに変更できます。あるいは、分散ストレージを直接使用した場合、速度はどのくらい遅くなるのでしょうか?これは便利で簡単で、マシンのメモリを節約するために LRUMap を自分で構築する必要がありません。 すべてのエッセイは面接のためだけのものではなく、あらゆるオンラインの問題のトラブルシューティングの基礎となります。八本足のエッセイの役割を誤解しないでください。 。 。 この記事はWeChatの公開アカウント「Coder's Technical Journey」から転載したものです。以下のQRコードからフォローできます。この記事を転載する場合は、Coder’s Technology Road のパブリック アカウントにお問い合わせください。 |
>>: クラウドネイティブはクラウドコンピューティングの質的変化を促進し、デジタル変革への道を提供します
企業では、ほとんどの製品マネージャーが実際の業務で競合製品の分析を行うことはほとんどありません。マー...
前回、Baiduがアルゴリズムを大幅に変更して以来、Baiduのアルゴリズムはますます高度化し、手動...
AMPとはAMP は、正式名称を Accelerated Mobile Pages といい、Goog...
最近、私はseowhyフォーラムでソフト記事の執筆経験をシェアしている著者を見ました。その文章は非常...
2018 年のダブル イレブン期間中、cmivps は次のような素晴らしいプロモーションを実施しまし...
arkecxは、日本の東京データセンターで日本のクラウドサーバー(日本のvps)を提供しています。デ...
1. kube-controller-managerはネットワークセグメントを管理するkube-co...
碑文:周知のとおり、IT 業界において最も重要なユーザー エクスペリエンスは、インターフェイス ユー...
長い間マーケティングを勉強してきたあなたは、何か大きなことをする準備ができているに違いありません。あ...
現在のテクノロジーの新しいトレンドに対する理解が不足していることに懸念や不満を感じている人もいます。...
ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービスまず、Paipaiwo ...
過去1年を振り返ると、SEO業界は活況を呈しています。現在でもSEOに関わる業界は数多くありますが、...
bandwagonhost から悪いお知らせがあります。低価格で IPv4 を入手できない、または低...
ネットワーク環境がますます複雑になるにつれて、従来の HTTP プレーンテキスト伝送プロトコルによっ...
月収10万元の起業の夢を実現するミニプログラム起業支援プラン現在、短編動画は現代人の生活に欠かせない...