1


0

私はC#Windowsサービスを.NET Framework 3.5で実行しています。これは、増え続けるGCハンドルを示しています(Windows Server 2003でシステムモニタを使用して見られる)。

私はすべてのリソースが正しく処分されていることを確認しました、そして私のコードにはファイナライザーを持っていません。

'Large Object Heap size'、および '#Bytes in all Heaps’は比較的に静的な値であり、 '%Time in GC’はガベージコレクションが発生していることを示していることがわかります。

'Private Bytes’カウンターも増えています。

この症状が原因で、タスクマネージャの「メモリ使用量」が1日に約35 MB増加しています。これは、サービスが基本的にOracle 10gに対して単純なSELECTクエリを実行し、5秒ごとに.NET TraceSourceを使用するためです。 TraceSourceがWindowsのイベントログとテキストファイルを使って .NET Listeners objects.

私はこれが私の 'メモリ使用量’の増加に関連していると信じているので '#GCハンドル’が絶えず増加している理由を誰でも知っていますか?

6 Answer


2


OK - 並べ替えました。

NET TraceSourceクラスのソースコードを調べたところ、設計上、WeakReferencesの2つのリスト(TraceSourceオブジェクト用に1つ、スイッチ用に1つ)が所有されているようです。

RefreshAllメソッドをサポートするためにこれを行います。

これらのリストを手動で消去するにはReflectionを使用しなければなりませんでした。 そのため、RefreshAllメソッドを安全に使用することはできませんが、少なくともPrivate BytesとGC Handlesを増やすことはできません。

この問題を再現するには、TraceSourceオブジェクトを大量に作成して閉じるだけです。「リーク」が発生する可能性があります。


1


あなたのコードによって適切に参照されているアンマネージリソースを解放していません。

あなたは決まった声明をよく知っていますか? 安全でない方法でアクセスできるように、メモリを固定できます。 しかし、それを行う別の方法がありますが、これはおそらく安全ではないと主張することです。

var handle = System.Runtime.InteropServices.GCHandle.Alloc(myObject、System.Runtime.InteropServices.GCHandleType.Pinned);

上記の種類のコードは、まさにあなたの種類の問題を引き起こす可能性があるものです。 このピン留めされたメモリを明示的に「.Free()」しないと、このオブジェクトのガベージコレクションが発生しなくなり、メモリリークが発生します。

メモリリークの恐れがある何か他のことをしているのでなければ、このようなことがOracle 10gプロバイダでも発生していると思います。


1


それが価値があるもののために、我々はTraceSourceとSwitchの両方のために.NET 4.0でこの問題を修正しました。

TraceSourceのさまざまなインスタンスを作成しないでください(ソースごとに1つの静的インスタンスを作成し、それらをスレッド間で共有することをお勧めします)。ただし、サードパーティのライブラリを使用している場合は不可能です。あなたは修正できません。


0


あなたはODP.Netを使っていますか? ODP.Netは完全に管理されているわけではなく、ネイティブコンポーネントも持っています。 ActiveDirectoryなどの他のネイティブリソースを使用しますか。 たとえあなたが.Netアセンブリを持っていてもそれはADのようなもののためのCOMの上の薄い層です。 使用したADコードで大量のメモリリークが発生しました。 私はODP.Netでメモリの問題はありませんでしたが、私の会社のエンタープライズサービスはODP.Netで動作します。


0


private void TidyWeakReferences(System.Diagnostics.TraceSource source){

試してください{//スイッチのWeakReferences TidyList(source、typeof(System.Diagnostics.Switch).GetFields(BindingFlags.NonPublic | BindingFlags.Static))をクリアしてください。 //ソースのWeakReferencesをクリアしますTidyList(source、typeof(System.Diagnostics.TraceSource).GetFields(BindingFlags.NonPublic | BindingFlags.Static)); } {{* *ここでできることは何もありません* /}}

private void TidyList(System.Diagnostics.TraceSourceソース、FieldInfo [] info){

リストlist = null。

foreach(FieldInfo fi情報)

if(fi.Name == "スイッチ" | fi.Name == "トレースソース"){

list =(List)fi.GetValue(null); lock(list){for(int i = list.Count  -  1; i> = 0; i--){// GCがすでにこれらのオブジェクトを収集しているかどうかを確認します。if(!list [i] .IsAlive){ //停止しているので、リストから削除します(.NET Framework 4.0では修正が必要です)。list.RemoveAt(i); }}}}}


0


デバッグ経験へのこのリンクはこの議論に加えるべきです。 @thehowlerによって投稿された回避策を補完します。

基本的に、TraceSourceを新しく割り当てるたびに、ガベージコレクトされないWeakReferenceリストが追加されます。