Skip to content

投稿

.Net Core のガベージコレクションの種類

2019年9月2日 • 8 分で読める

.Net Core のガベージコレクションの種類

モダン言語のメモリ管理は、しばしば後付けの考慮事項です。実質的には、メモリについてほとんど考えずにソフトウェアを書きます。これは私たちにとってうまく機能していますが、常に例外があります…

カリフォルニア州では、地域教育機関(LEA)に対する広範な財務報告要件があります。LEAは郡、地区、チャータースクール、または単一の学校です。ほとんどのLEAは独自の財務報告書を作成しており、通常はExcelを中心としているため、各報告書が異なるのは驚くことではありません。この問題を解決するため、カリフォルニア州教育委員会は財務報告書を生成するソフトウェアを委託しました。

私は開発チームの一員でした。

最初に確認したのはテストログです。Ed-Proのログは高いメモリ使用量を示していました。メモリリークがあるのでしょうか?あるエンジニアが、Ed-Proの計算が大量の短命メモリを使用していることに気づきました。メモリがすぐにクリーンアップされなければ、メモリリークのように見える可能性があります。

Ed-ProはMicrosoftのマルチプラットフォームフレームワークである.Net Coreの上に構築されています。.Net Coreでは、メモリは3つのタグに分割されています:短命(Gen0)、中程度の寿命(Gen1)、長命(Gen2)です。Gen0は迅速にスコープ外になる短命データ用で、Gen1はもう少し長く存在する中程度のメモリ用で、これもやがてスコープ外になり、Gen2はアプリケーションの寿命の間存在する可能性のある長命メモリです。Gen0メモリは常に回収され、Gen1はGen0よりも頻繁に回収され、Gen2はGen1よりもさらに頻繁に回収されます。

Ed-Proのメモリ使用量を理解する唯一の確実な方法は、それをプロファイルすることでした。以下はJetBrainsのdotMemoryを使用したスクリーンショットです。

予想通り、大量のGen0メモリ(青色)が見つかりました。ガベージコレクションが追いつけないほどの量でした。大量のメモリに対応する戦略により、ガベージコレクションはメモリ空間を増やす(アプリケーションの使用のためにより多くのメモリを追加する)こととそれをクリーンアップすることの間で振動しました。クリーンアップサイクル中、アプリケーションは応答しなくなります。

最初は困惑していました。GCの目的はメモリを整理することではないのでしょうか?.Netでのガベージコレクションがどのように機能するかを理解するのに役立つ2つの記事がありました:Mark Vinczeの記事Troubleshooting high memory usage with ASP.Net Core on KubernetesMicrosoftによるFundamentals of Garbage Collectionです。どちらも素晴らしい読み物で、Ed-Proのメモリ使用量に明確さをもたらしました。

ここで学んだことの要約です。.Netには2種類のガベージコレクションがあります:サーバーガベージコレクションとワークステーションガベージコレクションです。

サーバーガベージコレクションは2つの仮定をします:第1に、十分なメモリが利用可能であり、第2に、プロセッサはマルチコアで高速です。どちらも真実である可能性がありますが、仮想マシンとDockerの世界に住んでいるため、両方の仮定が偽である可能性が高いです。

サーバーガベージコレクションはメモリを蓄積させます。ある時点で、2つのことのいずれかを行います:メモリ空間を増やしてメモリを増やすか、孤立したメモリを解放するかです。メモリを解放することを選択すると、ガベージコレクションは高優先度スレッドでプロセスを開始します。高優先度スレッドはアプリケーションより高い優先度です。マシンが高速であれば、クリーンアップは気づかれないはずです。ただし、そうでない場合は、クリーンアップが完了するまでアプリケーションを停止させます。

ワークステーションガベージコレクションは異なる方法で動作します。アプリケーションと同じ優先度のスレッドでメモリを継続的に回収します。これは、アプリケーションと競合してリソースを使用することを意味し、アプリケーションの遅さを引き起こす可能性があります。利点は、アプリケーションのメモリ使用量を非常に低く保つことができることです。特に大量のGen0を使用する場合です。

デフォルトでは、.Net Coreがサーバーを検出すると、サーバーガベージコレクションタイプを実行します。これは私たちのアプリケーションの場合でした。ワークステーションガベージコレクションタイプを実行するには、プロジェクトファイルに次のスニペットを追加します:

  <PropertyGroup> 
    <ServerGarbageCollection>false</ServerGarbageCollection>
  </PropertyGroup>

Ed-Proにこの設定変更を加え、dotMemoryを使用して、ワークステーションガベージコレクションを有効にしてEd-Proのメモリをプロファイルし、前のテストと同じスクリーンをロードしました。結果は次のとおりです:

メモリ使用量は大幅に減少しました。Gen0の割り当ては事実上存在しません。グラフの違いを超えて、サーバーガベージコレクションのメモリ使用量は1ギガバイトに達しましたが、ワークステーションガベージコレクションはおよそ200メガバイトに達しました。

すべてのアプリケーションは異なります。私たちのアプリケーションは大量の一時データを使用したため、大量のGen0メモリを使用しました。あなたのアプリケーションは、Gen1やGen2などのより長命のメモリを活用する可能性があります。その場合、サーバーガベージコレクションは非常に理にかなっています。私のアドバイスは、異なる条件下でメモリをプロファイルして、メモリの使用方法を理解し、その後、アプリケーションに最適なモードを決定することです。

Author: Chuck Conway is an AI Engineer with nearly 30 years of software engineering experience. He builds practical AI systems—content pipelines, infrastructure agents, and tools that solve real problems—and shares what he’s learning along the way. Connect with him on social media: X (@chuckconway) or visit him on YouTube and on SubStack.

著者: Chuck Conwayは、ソフトウェアエンジニアリングの経験が30年近くあるAIエンジニアです。彼は実用的なAIシステム(コンテンツパイプライン、インフラストラクチャエージェント、実際の問題を解決するツール)を構築し、学んだことを共有しています。ソーシャルメディアで彼とつながってください: X (@chuckconway) または YouTubeSubStack で彼を訪問してください。

↑ トップに戻る

こちらもおすすめ