2013-02-14 51 views
1

我使用C#與Domino COM進行交互。我正在使用Lotus Notes 8.5.2。 Visual Studio 2008,Windows 7 SP1。處理Notes對象與COM,內存泄漏

我試圖防止這種錯誤從Lotus:

LSXBE: ************************************ 
LSXBE: ****** Out of Backend Memory ******* 
LSXBE: ************************************ 

下面的代碼將每個NotesDocumentCollection中的NSF到另一個NSF。使用

NotesDocument ndoc = nd.GetDocumentByUNID(nve.UniversalID);   
ndoc.CopyToDatabase(nd2); 

鑑於,10 GB,內存量(專用字節,相信)的源具有NSF在時間SELECT @All的選擇查詢,代碼拷貝一個消息從一個爲NotesView得到UNIDs後由我的應用程序使用穩步增長到約450 MB。 ANTS Memory Profiler表明幾乎所有的內存都分配給非託管內存,這將是COM。

  1. 可以通過處理Notes對象來減少內存消耗嗎?我還沒有看到解除分配NotesSession,NotesDatabase,NotesDocument等方法。有沒有辦法解除分配內存?

我都想盡5000個文檔後一個版本()的代碼中調用所以GC.Collect和GC.WaitForPendingFinalizers()的,與16 GB RAM淘汰了機上的「走出後端內存不足」的錯誤。即使在複製完成時,我將包含以下代碼的對象設置爲null並調用垃圾回收,內存利用率仍保持在450 MB左右。

我也嘗試將複製代碼放在它自己的線程中,然後在線程完成後進行垃圾收集。這沒有幫助。

  1. 如果沒有Notes對象的處理方法,我該如何減少內存使用率?

代碼C#

//Establish session 
NotesSession ns = new Domino.NotesSessionClass(); 
ns.Initialize(""); 

//Open source NSF 
NotesDatabase nd = ns.GetDatabase("", "test.nsf", false); 
//Open destination NSF. 
//Assume that all design elements of nd2 are identical to those of nd 
NotesDatabase nd2 = ns.GetDatabase("", "test2.nsf", false); 

//Create view that returns all documents. 
NotesView nView2 = nd.GetView("$All"); 
nd.CreateView("All-DR", "SELECT @ALL", nView2, false); 
NotesView nView = NotesConnectionDatabase.GetView("All-DR"); 

//Loop through entries in the new view 
NotesViewEntry nvec = nView.AllEntries; 
nve = nvec.GetFirstEntry(); 

for (int j = 1; j <= intEntryCount; j++) 
{ 
    if (j == 1) 
    { 
      nve = nvec.GetFirstEntry(); 
    } 
    else 
    { 
      nve = nvec.GetNextEntry(nve); 
    } 

    //Copy document to second database. 
    NotesDocument ndoc = nd.GetDocumentByUNID(nve.UniversalID);   
    ndoc.CopyToDatabase(nd2); 
} 
//End loop. 
//All documents are copied. 

我有這些想法,其中沒有一個是吸引人:

  1. 呼叫垃圾收集每次調用CopyToDatabase後。我不認爲這會工作,因爲我相信我正在處理COM中的內存泄漏。我也希望它能夠降低我的應用程序的速度。

  2. 嘗試使用C++ API。我不知道這個問題是否存在。

  3. 這是一個非常笨拙的方式... 建立一個新的經理應用程序, a。獲取UNID列表並將它們寫入文本文件。 b。開始複製應用程序。 c。複製應用程序從文本文件複製記錄的一個子集。 d。複製應用程序終止,釋放其內存。 e。經理應用程序啓動新的複製應用程序進程。 f。根據需要重複c-e。

+1

把它作爲評論,因爲我沒有任何明確的說法。本人並不相信Domino COM類泄漏。如果他們這樣做了,Lotus會按照他們在Java類中的方式提供recycle()方法。但是在這些類的後面是整個Notes運行時,它會爲緩存分配大量內存,所以如果看到內存在增加,這並不奇怪。 – 2013-02-15 01:03:27

+1

我沒有看到這裏真正的問題的證據。如果你的程序拷貝了10個jigabytes並且沒有OOM而存活,那麼泄漏的機率很低。在GC.Collect()調用期間減少虛擬機大小是一個非常常見的錯誤,這與內存管理在Windows中的工作方式不同。它創建空的堆塊,他們留待下一次分配。這只是虛擬內存,它不需要任何成本。 – 2013-02-15 17:36:30

+0

在每個第5000個文檔之後添加GC.Collect()之前,在具有4 GB RAM的機器上,我確實收到類似 的錯誤LSXBE:****** Out of Backend Memory *******。 我剛剛在每個單獨的文檔之後嘗試過GC.Collect。這使內存利用率保持在75 MB左右,而不是450 MB。我希望這會讓我自由地對每個文檔執行額外的操作。我的申請速度減少了大約50%,這是可以接受的。 – 2013-02-15 22:50:01

回答

1

我不相信Domino COM類本身會泄漏。如果他們這樣做了,Lotus會按照他們在Java類中的方式提供recycle()方法。但是在這些類的後面是整個Notes運行時,它會爲緩存分配大量內存,所以如果看到內存在增加,這並不奇怪。

0

您是否試過使用顯式命令SetProcessWorkingSetSize()傳遞參數-1和-1?有時.NET COM對象不會釋放內存,直到明確地調用此調用。 This article更詳細地討論了這一點。

我遇到了類似的問題in this SO post並解決了這個問題。

+0

如果您發現一個您認爲重複的問題,請標記新的問題,而不是發佈答案。 – ChrisF 2013-05-20 20:51:01

+0

問題不是重複的,而是根本問題可能是相關的。 – 2013-05-20 22:54:30