問題
.NETエージェントは、インストゥルメントされたメソッドからエージェントを呼び出すために必要なメソッド情報をキャッシュします。バージョン10.54.0以降、エージェントは.NET Frameworkと.NETまたは.NET Coreアプリケーションの両方でこのキャッシュを使用します。バージョン10.54.0より前は、エージェントはこれを.NET Frameworkアプリケーションにのみ使用していました。
キャッシュは以下の症状を引き起こす可能性があります:
- .NET フレームワーク:高スループットのアプリケーションは、高いスレッド競合を示しています。プロセスダンプとスタックトレースは、
AppDomain.GetData()への呼び出しで多くのスレッドがブロックされていることを示しています。 - .NETまたは.NET Core、エージェントバージョン10.54.0~10.56.0:アプリケーションは、エージェントバージョン10.53.xを使用していたときよりも多くのネイティブメモリを使用します。この増加は、アプリケーションがロードするアセンブリの数に伴って大きくなります。
原因
.NETエージェントは、メソッドを計装するためにメソッド・シグネチャ情報を必要とします。インストゥルメントされたメソッドが実行されるたびにリフレクション呼び出しが行われるのを避けるため、エージェントはこの情報をキャッシュします。キャッシュはCPU時間を節約するために、より多くのメモリを使用します。当社のテストでは、キャッシュを有効にした場合、アプリケーションの最大スループットが向上しました。
.NET Frameworkでは、エージェントはこのキャッシュの一部をAppDomainストレージに保存します。AppDomain.GetData()への呼び出しはグローバル・ロックを取得するため、一部の高スループットのアプリケーションではスレッドの競合が発生する可能性があります。
.NETおよび.NET Coreでは、エージェントのバージョン10.54.0~10.56.0は、インストゥルメントされたメソッドを持たないモジュールを含め、アプリケーションがロードするすべてのモジュールにエージェントのヘルパー・メソッドへの参照を追加します。ランタイムは、変更された各モジュールのメタデータのコピーをネイティブ・メモリに保持します。
エージェントの設定を変更する前に
上記の症状には多くの原因が考えられます。エージェントの設定を変更する前に、スレッドダンプまたはメモリの測定値を添えてNew Relicサポートにお問い合わせください。サポートは、エージェントのメソッドキャッシュが原因であるかどうかを確認できます。
解決
.NETまたは.NET Coreで.NETエージェント10.54.0~10.56.0を使用しており、上記で説明したネイティブメモリの増加が見られる場合は、10.56.0より新しいバージョンにエージェントを更新してください。これらのバージョンでは、エージェントはこれらの参照をSystem.Private.CoreLibと、インストゥルメントされたメソッドを持つモジュールにのみ追加します。
サポートがエージェントのメソッド・キャッシュが原因であることを確認し、エージェントを更新できない場合は、次の環境変数を使用してキャッシュを無効にすることができます:
NEW_RELIC_DISABLE_APPDOMAIN_CACHING=trueこの設定は.NETエージェントバージョン9.7以降で利用可能であり、.NETフレームワーク、.NET、および.NET Coreアプリケーションに適用されます。長期間有効にしたままにすることができます。
注意
この設定はマネージド・ヒープの使用量を減らすものではなく、遅いrequestsや高いCPU使用率を修正するものでもありません。キャッシュを無効にすると、インストゥルメントされたメソッドが実行されるたびにエージェントがリフレクションを使用するため、エージェントのオーバーヘッドが増加します。当社のテストでは、キャッシュを無効にすると、アプリケーションの最大スループットが低下しました。