【发布时间】:2009-04-03 09:22:19
【问题描述】:
我有一些非常大的 XML 文件,我使用 System.Xml.Serialization.XmlSerializer 读取这些文件。它非常快(嗯,足够快),但我希望它汇集字符串,因为一些长字符串出现很多次。
XML 看起来有点像这样:
<Report>
<Row>
<Column name="A long column name!">hey</Column>
<Column name="Another long column name!!">7</Column>
<Column name="A third freaking long column name!!!">hax</Column>
<Column name="Holy cow, can column names really be this long!?">true</Column>
</Row>
<Row>
<Column name="A long column name!">yo</Column>
<Column name="Another long column name!!">53</Column>
<Column name="A third freaking long column name!!!">omg</Column>
<Column name="Holy cow, can column names really be this long!?">true</Column>
</Row>
<!-- ... ~200k more rows go here... -->
</Report>
XML 被反序列化成的类看起来有点像这样:
class Report
{
public Row[] Rows { get; set; }
}
class Row
{
public Column[] Columns { get; set; }
}
class Column
{
public string Name { get; set; }
public string Value { get; set; }
}
导入数据时,会为每个列名分配一个新字符串。我知道为什么会这样,但根据我的计算,这意味着一些重复的字符串占导入数据使用的内存的大约 50%。我认为花费一些额外的 CPU 周期将内存消耗减少一半是一个很好的权衡。有什么方法可以让XmlSerializer 池字符串,以便丢弃重复项并在下次发生 gen0 GC 时回收?
还有一些最后的说明:
我无法更改 XML 架构。它是从第三方供应商导出的文件。
我知道(理论上)可以使用
XmlReader来创建一个更快的解析器,它不仅可以让我进行自己的字符串池,还可以在导入过程中处理数据,这样不是所有的在我读完整个文件之前,必须将 200k 行保存在 RAM 中。不过,我宁愿不花时间编写和调试自定义解析器。真正的 XML 比示例要复杂一些,因此这是一项非常重要的任务。如上所述 -XmlSerializer的性能确实足以满足我的目的,我只是想知道是否有一种简单的方法可以稍微调整一下。我可以编写自己的字符串池并在
Column.Name设置器中使用它,但我不希望 (1) 这意味着摆弄自动生成的代码,并且 (2) 它会打开解决与并发和内存泄漏相关的一系列问题。不,我所说的“池化”并不是指“实习”,因为这会导致内存泄漏。
【问题讨论】:
-
实习有什么问题?这只是一个系统管理的字符串池(编译器也使用)。
-
我希望池在反序列化完成后被丢弃,所以我不会占用比我需要的更多的内存。一个实习字符串“从不”释放(“在公共语言运行时 (CLR) 终止之前,为实习字符串对象分配的内存不可能被释放”,API 说)。
-
谢谢...建议用那些有点晦涩的信息替换“愚蠢”。
标签: c# .net xml-serialization memory-management