問題タブ [buffer-manager]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - System.ServiceModel.Channels.BufferManager はスレッドセーフですか?
の静的メンバーを使用してバッファー マネージャーを作成しますBufferManager.CreateBufferManager
。この新しく作成されBufferManager
たものは、複数のスレッドによって使用されます。
lock
withを使用する必要がありますかTakeBuffer()
、ReturnBuffer()
またはそれは設計上スレッドセーフですか?
c# - WCFクライアントアプリのBufferManager/PooledBufferManagerがメモリを浪費するのを防ぐにはどうすればよいですか?
SOAPを介して多数のサービスと通信し、数日間実行した後にOutOfMemoryExceptionがスローされるWCFクライアントアプリケーション(私は作成しておらず、まだあまり詳しくない)を分析すると、.netのPooledBufferManagerがアプリのメモリが不足し、OOMEが発生した場合でも、未使用のバッファを解放することはありません。
これはもちろん仕様に準拠しています:http://msdn.microsoft.com/en-us/library/ms405814.aspx
バッファプールがガベージコレクションによって再利用されると、プールとそのバッファは[...]破棄されます。
以下の質問の1つだけに自由に答えてください。私にはたくさんの質問があり、いくつかはより一般的な性質であり、いくつかはアプリでのBufferManagerの使用に固有のものです。
(デフォルトのプールされた)BufferManagerに関する最初のいくつかの一般的な質問:
1) GCがある環境では、OOMEにつながる場合でも、未使用のメモリを保持するBufferManagerが必要なのはなぜですか?私は知っています、BufferManager.Clear()があります。これを使用して、すべてのバッファーを手動で取り除くことができます。つまり、BufferManagerにアクセスできる場合です。私がアクセスできないように見える理由については、さらに下を参照してください。
2)「このプロセスは、バッファを使用する必要があるたびにバッファを作成および破棄するよりもはるかに高速です」というMSの主張にもかかわらず、GC(およびそのLOHなど)に任せて最適化するべきではありません。代わりにGC?
3) BufferManager.Take(33 * 1024 * 1024)を実行すると、64Mのバッファーが取得されます。これは、PooledBufferManagerが後で再利用するためにそのバッファーをキャッシュするためです。これは、私の場合はそうではないため、純粋なメモリの浪費-たとえば、34M、50M、または64Mが必要です。それで、HttpsChannelFactoryによって使用される(デフォルトでは、私が推測する)このような潜在的に非常に無駄なBufferManagerを作成することは賢明でしたか?特に、アプリケーションが10秒TOPSごと、通常はさらに数秒または数分ごとに通信するWCFおよびネットワークサービスについて話している場合、メモリ割り当てのパフォーマンスがどのように重要であるかがわかりません。
ここで、アプリケーションでのBufferManagerの使用に関連するいくつかのより具体的な質問があります。このアプリは、いくつかの異なるWCFサービスに接続します。それらのそれぞれについて、接続が同時に発生する可能性があるため、http接続用の接続プールを維持します。
1つのヒープダンプ内の単一の最大オブジェクトを検査します。これは、初期化時にアプリで1回だけ使用され、その後は必要ない64Mバイトの配列です。これは、サービスからの応答が初期化時にのみ大きいためです。これは、最適化(ディスクへのキャッシュなど)の対象となる可能性がありますが、私が使用した多くのアプリケーションでは一般的です。WinDbgでのGCルート分析により、次の結果が得られます(独自のクラスの名前を「MyServiceX」などにサニタイズしました)。
BufferManagerによって管理される他のバイト配列のgcルートを見ると、他のサービス('MyServiceX'ではない)が異なるBufferPoolインスタンスを持っていることがわかります。したがって、それぞれが独自のメモリを浪費しており、無駄を共有していません。
4)ここで何か間違ったことをしていますか?私は決してWCFの専門家ではないので、さまざまなHttpsChannelFactoryインスタンスがすべて同じBufferManagerを使用するようにすることはできますか?
5)または、さらに良いのは、すべてのHttpsChannelFactoryインスタンスにBufferManagerをまったく使用しないように指示し、GCに「メモリの管理」というひどい仕事をするように依頼することでしょうか。
6)質問4)と5)に答えられない場合、すべてのHttpsChannelFactoryインスタンスのBufferManagerにアクセスし、それらに対して手動で.Clear()を呼び出すことができますか?これは最適なソリューションにはほど遠いですが、すでに役立ちます、私の場合、前述の64Mだけでなく、64M + 32M + 16M + 8M + 4M +2Mを1つのサービスインスタンスで解放します。それだけで、メモリの問題が発生することなくアプリが長持ちします(いいえ、BufferManager以外にメモリリークの問題はありませんが、コース中に大量のメモリを消費し、大量のデータを蓄積します何日もかかりますが、それはここでは問題ではありません)
.net - BufferManager の実際の使用例
OutOfMemoryException の一番下に到達しようとすると、WCF のバッファリングされた TransferMode で使用される .net のBufferManagersが、文字通り数百メガバイトを浪費する責任があることがわかりました ( WCF クライアントで BufferManager / PooledBufferManager を防ぐ方法に関する質問と自分の回答を参照してください)アプリはメモリを浪費していませんか?詳細と、単に「バッファリング」から「ストリーミング」に切り替えるだけでそれを修正する方法について)。
WCF はさておき、BufferManagers は、必要なときにバイト配列を割り当て、GC に依存してそれらをクリーンアップし、参照が範囲外になったらリサイクルするという、通常行うよりも優れたパフォーマンスの代替手段として発明されました。
私の質問は次のとおりです:実際のアプリで BufferManagers を使用して、手動で .Clear() BufferManager (必要な場合) を実行する不便さを正当化するために、パフォーマンスの面で顕著な違いを生み出した人はいますか?
もしそうなら、1 バイトのバッファを手動で作成し、それへの参照を保持するだけでは、その特定の問題は解決されないのでしょうか?
c# - 一度使用した WCF HTTP クライアントの PooledBufferManager をクリアするにはどうすればよいですか?
非常に大きな応答 (1 GB) で単一のサービス呼び出しを行う WCF クライアント アプリケーションがあります。このサービス コールを行うと大量のメモリ (500MB) が使用されることがわかりました。このメモリは、コードによって応答オブジェクトが参照されなくなっても、再利用されることはないようです。
メモリ プロファイラーを使用して、メモリ使用量の多くが PooledBufferManager インスタンスによって作成されたバイト配列にあることを確認しました。
私が使用しているプロキシ/クライアントは Visual Studio によって自動生成されているため、System.ServiceModel.ClientBase< TChannel > から派生したクラスです。
次の構成でカスタム バインディングを使用しています。
人々の周りを読んで、これに対するいくつかの解決策について話しています。
- バッファリングではなくストリーミング応答モードに切り替えますが、これはTCP WCF接続用であり、私のようなHTTP用ではないと思います.
- maxBufferPoolSize をゼロに設定してバッファー プールを無効にします。これを httpTransport 要素に設定しても、私には何の効果もないようです。
- 適切な BufferManager/PooledBufferManager で Clear() を呼び出します。私が持っている ClientBase 派生インスタンスのコンテキストから、これを呼び出すオブジェクトが見つかりません。デバッガーを使用して適切な PooledBufferManager インスタンスを見つけることができ、プライベートな innerChannelFactory フィールドを多くのレベルで深く掘り下げましたが、これはコードから操作するには役に立ちません。
- GC.Collect() を手動で呼び出すと、未処理の 500MB のうち約 50MB が回収されるようです。
この 1 回限りのサービス コールで使用されたメモリをできるだけ多く再利用するには、どうすればよいでしょうか? この時点で、メモリを再利用するために強制終了できる専用プロセスでサービス呼び出しを行う寸前です。
wcf - WCF BufferManager ReturnBuffer とクリア
WCF サービスで BufferManager を使用しています。IDisposable を実装する BufferManager をラップする独自のクラスを作成しました。現在、私の Dispose メソッドは次のようになっています。
私の質問:これは、マネージャーによって取得されたすべてのバッファーで ReturnBuffer を呼び出すのと同じことを達成しますか?
背景として: 次のメソッドで BufferManager を使用しています。
私がこれを行っている理由は、サービスを破壊する OutOfMemory 例外を取得し続けたためです。
ホスト サーバーには 3 GB のメモリがあります。サービスは InstanceContextMode.Single モードであるため、画像は一度に 1 つずつ処理されます。画像はバイト配列として受信されます - 最大のものは 100MB かもしれませんが、通常ははるかに小さくなります - 変換され、バイト配列として返されます。多くのものがラージ オブジェクト ヒープに置かれ、画像のサイズはかなり異なります。
問題がヒープの断片化であるかどうか疑問に思っています。
ドキュメントの各ページが変換されると、ディスク上の一時ファイルに追加されます。変換後、変換されたファイル全体をディスクからバイト配列に読み取り、それをクライアントに返します。
標準の File.ReadAllBytes メソッドは、ファイルから読み取るときに新しいバイト配列を作成します。これは、作業している画像サイズのために必然的に LOH になります (これが起こると思います)。ReadAllBufferedBytes メソッドを作成して同じことを行いましたが、バイト配列をバッファリングし、BufferManager が破棄されたときにバッファを返せるようにしました。
もう 1 つの質問は、これをすべて行う必要があるかどうかです。
azure - Azure Storage BufferManager は何をしますか? また、いつどのように実装しますか?
cloudBlobClient.BufferManagerに関する MSDN のドキュメントには、このバッファー マネージャーが大規模なアプリケーションのパフォーマンスを向上させることが記載されています。
私の理解では、このバッファー マネージャーは、多くの小さなトランザクション (多くの Azure テーブル エンティティ呼び出しに見られるように) の GC への負荷を軽減します。
次に、デスクトップの使用に関するリファレンスを読みましたが、デスクトップ/モバイルの使用プロファイルでは、GC の断片化が発生する可能性が低いようです。
IBufferManager インターフェイスは、System.ServiceModel.dll の BufferManager クラスに基づいてパターン化されているため、デスクトップ クライアントは、フレームワークによって提供される既存の実装を簡単に活用できます。
質問
IBufferManager の唯一の目的は、GC の負荷を軽減することですか?
このキャッシュの恩恵を受けるのは、どのワークロード (テーブル、キュー、BLOB) ですか?
IBufferManager を実装する必要がある (測定可能な) 条件は何ですか?
BufferManager はスレッドセーフですか? 必要に応じて割り当てるバッファーのランタイム サーバー側プールを使用できますか?
この bufferManager をどのように実装する必要がありますか? (例: スレッド、IDisposable、静的メソッドの事前割り当て、Redis)