非常に大きな応答 (1 GB) で単一のサービス呼び出しを行う WCF クライアント アプリケーションがあります。このサービス コールを行うと大量のメモリ (500MB) が使用されることがわかりました。このメモリは、コードによって応答オブジェクトが参照されなくなっても、再利用されることはないようです。
メモリ プロファイラーを使用して、メモリ使用量の多くが PooledBufferManager インスタンスによって作成されたバイト配列にあることを確認しました。
私が使用しているプロキシ/クライアントは Visual Studio によって自動生成されているため、System.ServiceModel.ClientBase< TChannel > から派生したクラスです。
次の構成でカスタム バインディングを使用しています。
<customBinding>
<binding name="foo"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:01:00"
sendTimeout="00:01:00">
<transactionFlow/>
<reliableSession ordered="true" inactivityTimeout="00:02:00"/>
<security authenticationMode="SecureConversation" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
<secureConversationBootstrap messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
<localClientSettings maxClockSkew="23:59:00"/>
</secureConversationBootstrap>
<localClientSettings maxClockSkew="23:59:00"/>
</security>
<mtomMessageEncoding>
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
</mtomMessageEncoding>
<httpTransport maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"/>
</binding>
</customBinding>
人々の周りを読んで、これに対するいくつかの解決策について話しています。
- バッファリングではなくストリーミング応答モードに切り替えますが、これはTCP WCF接続用であり、私のようなHTTP用ではないと思います.
- maxBufferPoolSize をゼロに設定してバッファー プールを無効にします。これを httpTransport 要素に設定しても、私には何の効果もないようです。
- 適切な BufferManager/PooledBufferManager で Clear() を呼び出します。私が持っている ClientBase 派生インスタンスのコンテキストから、これを呼び出すオブジェクトが見つかりません。デバッガーを使用して適切な PooledBufferManager インスタンスを見つけることができ、プライベートな innerChannelFactory フィールドを多くのレベルで深く掘り下げましたが、これはコードから操作するには役に立ちません。
- GC.Collect() を手動で呼び出すと、未処理の 500MB のうち約 50MB が回収されるようです。
この 1 回限りのサービス コールで使用されたメモリをできるだけ多く再利用するには、どうすればよいでしょうか? この時点で、メモリを再利用するために強制終了できる専用プロセスでサービス呼び出しを行う寸前です。