2

我们在使用 XmlDocument 的 .NET Web 应用程序中看到了非常高的内存使用率。将一个小的 (~5MB) XML 文档加载到 XmlDocument 对象中并存储在 HttpContext.Cache 中,以便在每次加载页面时进行查询和 XSLT 转换。XML 在磁盘上定期修改,因此缓存依赖于文件。

这样的应用程序似乎使用了数百兆的 RAM。

我已经尝试在每次请求开始时请求垃圾收集,这使 RAM 使用率大大降低,但我无法想象这是一个好的做法。

有没有人对我们如何实现相同的目标但使用较低的 RAM 有任何建议?

4

2 回答 2

6

我的两分钱。. .

如果内存使用基于 XML 文档的大小呈指数增长,我会担心。例如,1mb XML 文件内存固定为 10mb,2mb 变平为 30mb,等等。

此外,请考虑 XML 文件的成本,而不是字节大小,而是每个节点的成本。如果你的 5mb XML 文档有两个数据节点,那么文档的内存表示不会比 5mb 大很多(实际上它可能要小得多,考虑到 XML 中的二进制数据将是它的两倍记忆)。

*如果您的 XML 文档是 utf-8,并且您有两个大文本节点,那么内存中的表示可能是 10mb(文本可以存储在 .net 字符串中,这些字符串是 Unicode,并且是标准宽度的两倍英语 UTF-8 文本)。

如果 XML 文档由许多离散的字符串值组成,那么每个节点都是一个对象,每个节点名称都是一个对象,每个节点值都是一个对象。因此,假设引用是 4 个字节,那么(至少)每个节点额外增加 12 个字节。

现在,假设您有很多节点,并且假设您的节点名称+值的平均长度是 20 个字符,那么 5mb 文件的引用开销是 3mb,加上 utf-8 到 Unicode 转换的可能额外 100%,它需要 5MB + 5mb + 3mb(至少)= 13mb(至少)的 ram 来存储 5mb XML 文件。. . 这还不包括因内存对齐而丢失的字节数,或者用于存储每个字符串对象大小的额外字节数**

还要考虑到因为您正在缓存 XML 文档,所有这些对象都会立即成为第 2 代可收集对象,这基本上意味着 GC 将非常懒惰地走动那相当大的堆以查看它可以收集什么。

See Rico Mariani's When to call GC.Collect() for the situations where it's not only OK to call GC Collect, but when it's necessary to call it.

Hope this helps, sorry if I'm preaching to the choir on the memory size thing.

* I've no idea if this is actually the case, but would be surprised if it isn't.
** I'm assuming .net strings store the size of the string before/after the actual characters of the string, this could significantly increase the in-memory representation by and extra 4-8 bytes per node, giving at 20 byte cost per 20 bytes of node name/value. Which effectively increases the overhead to match the size of the data stored.

于 2010-04-06T13:24:24.550 回答
1

由于积极的 GCing 清理了事情,你应该寻找你可能没有处理实现的对象的地方IDisposable。也许您需要使用 XSL 转换查看您的代码,以确保其中使用的对象得到正确处理。

于 2010-04-06T10:58:30.103 回答