2013-02-01 41 views
1

我在我的WCF服務中使用BufferManager。我創建了自己的類來包裝實現IDisposable的BufferManager。現在我的Dispose方法是這樣的:WCF BufferManager ReturnBuffer與清除

public void Dispose() 
    { 
     this.bufferManager.Clear(); 
    } 

我的問題:這是否做到同樣的事情,呼籲ReturnBuffer對所有已採取經理緩衝區?

只是爲了一些背景:我使用的是BufferManager在下面的方法:

public byte[] ReadAllBufferedBytes(string filePath) 
    { 
     using (var fileStream = 
      new FileStream(filePath, FileMode.Open, FileAccess.Read)) 
     { 
      byte[] buffer = this.bufferManager.TakeBuffer((int)fileStream.Length); 

      fileStream.Read(buffer, 0, buffer.Length); 

      return buffer; 
     } 
    } 

的原因,我這樣做是因爲我一直得到OutOfMemory異常這將推倒的服務。

主機服務器有3 GB的內存。該服務處於InstanceContextMode.Single模式,因此一次處理一個圖像。圖像以字節數組的形式接收 - 最大可能爲100MB,但通常要小得多 - 被轉換,然後作爲字節數組返回。很多結果都出現在大對象堆上,圖像大小差別很大。

我想知道如果問題是堆碎片。

隨着文檔的每個頁面都被轉換,它會被附加到磁盤上的臨時文件。轉換後,我將整個轉換後的文件從磁盤讀取到一個字節數組中,並將其返回給客戶端。

標準File.ReadAllBytes方法從文件讀取時創建一個新的字節數組,由於我正在處理的圖像大小(我認爲這是發生了什麼),它不可避免地結束於LOH。我創建了ReadAllBufferedBytes方法來做同樣的事情,但是要緩衝字節數組並讓BufferManager在處理時返回緩衝區。

另一個問題是:我甚至需要做這一切?那裏有的小byte[]分配,接收或者在非常低的水平(例如,插座)發送數據時等很多 -

回答

0

的BufferManager在場景中必須防止GC壓力正常使用。這裏強調了很多,否則GC應該能夠處理內存分配。

爲了防止將整個轉換的文檔文件加載到內存中,如果可能,應該直接使用FileStream(而不是將其全部內容讀入內存 - 一個字節[])與streamed (response)TransferMode結合使用。

+0

如果我將操作合同更改爲流式傳輸模式,則必須更新客戶端以使用流。我的隊友們需要摔跤才能讓他們接受這個想法。我對當前實現的主要擔憂是LOH碎片化,因爲所有字節[]都大於85kb。當操作契約接收到一個字節[]時,WCF是否使用緩衝區管理器在內部管理它? – lintmouse

+0

當然,這就是創建BufferManager的原因。在緩衝傳輸模式下,方法調用的參數只有在收到完整的SOAP消息後纔會被反序列化。所以如果你不使用流傳輸,你將永遠不得不將整個文件加載到內存中。 – m0sa