1

我使用 C# 与 Domino COM 交互。我正在使用 Lotus Notes 8.5.2。视觉工作室 2008,Windows 7 SP1。

我正在尝试防止 Lotus 出现此错误:

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

以下代码将 NSF 中的每个 NotesDocument 复制到另一个 NSF。从具有 SELECT @All 选择查询的 NotesView 获取 UNID 后,代码使用一次复制一条消息

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

给定一个 10 GB 的源 NSF,我的应用程序使用的内存量(我相信是私有字节)稳步增长到大约 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. 这是一种非常笨拙的方式......构建一个新的经理应用程序。获取列表 UNID 并将它们写入文本文件。湾。启动复制应用程序。C。复制应用程序从文本文件中复制一部分记录。d。复制应用程序终止,释放其内存。e. 管理器应用程序启动一个新的复制应用程序进程。F。根据需要重复 c - e。

4

2 回答 2

1

我不相信 Domino COM 类本身会泄漏。如果他们这样做了,Lotus 将提供一个 recycle() 方法,就像他们在 Java 类中所做的那样。但在这些类的背后是整个 Notes 运行时,它确实为缓存分配了大量内存,所以如果您看到内存增加也就不足为奇了。

于 2013-02-16T00:14:45.687 回答
0

您是否尝试过使用SetProcessWorkingSetSize()传递参数 -1 和 -1 的显式命令?有时 .NET COM 对象在显式调用之前不会释放内存。本文更详细地讨论了这一点。

我在这篇 SO 帖子中遇到了类似的问题,这解决了这个问题。

于 2013-05-20T20:13:26.057 回答