【发布时间】:2013-10-18 11:09:41
【问题描述】:
我有一个 VB.NET 应用程序,它使用 CreateObject 来使用 Excel 并将大量数据转储到其中。我们正在出现内存不足的异常,此时我们的应用程序通常会达到 1GB 的内存。但是我不能把所有的数字加起来。
这是将数据传递到 Excel 的方式:
worksheet_object.Range("A1").Resize(rows, cols).Value = an_array
应用程序大约 400mb,屏幕上的数据 (datagrid),当它崩溃时,它已经使用了额外的 600mb,尽管带有 CSV 的 Excel 只有 200mb,而 CSV 只有 68mb。我意识到内存中的数组可能会更大一些,但是除非 Excel 以某种方式使用我的应用程序内存,否则 600mb 的数据如何被吞并到 Excel?
我试图通过 CreateObject 找出 Excel 是在它自己的内存空间中运行还是使用我的应用程序的内存空间,完全空白。 ProcessExplorer 将它们显示为单独的进程,所以我不知道该怎么想。
我们发现以 64 位而不是 32 位运行应用程序可以解决问题,但并非我们所有的客户都将拥有 64 位办公室。
所以我的问题是:那一行如何使用 600mb,有没有更好的方法将数据传递到 Excel。
【问题讨论】:
-
Excel 只在自己的进程中分配内存。您需要注意进程中的 GC,并查看它是否经常收集。当您只进行互操作调用时,很容易永远不会触发集合。这可以让 RCW 建立起来。使用 Perfmon.exe 查看 .NET GC 性能计数器,最好使用内存分析器。对策是定期强制 GC,比如每 N 行。
-
你不说行和列怎么可能? (每个 Excel 单元格可以使用大量内存)。但也许您正在分割可用的 2GB 地址空间:您是否尝试过以较小的块工作?
-
大约 200,000 行,可能 50 列。被传递的数组有大约 970 万个单元。我找不到获取其内存大小的方法。我想我可以使用二进制序列化程序并将其写入文件。
-
大概这个操作意味着对数组进行大量的复制。这种大小的工作表占用超过 200MB(假设它的唯一数字):等效的对象数组可能大致相同,然后通过 com-interop 可能意味着内存中至少有一个或 2 个副本。内存碎片可能意味着无法满足对大块连续内存的请求。如果你使用 10 个更小的块,它可能会在 32 位模式下工作