gus*_*afc 5 .net c# memory-management xml-serialization
我有一些非常大的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>
Run Code Online (Sandbox Code Playgroud)
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; }
}
Run Code Online (Sandbox Code Playgroud)
导入数据时,会为每个列名分配一个新字符串.我可以看出为什么会这样,但根据我的计算,这意味着一些重复的字符串占导入数据使用的内存的约50%.我认为花一些额外的CPU周期来减少一半的内存消耗是一个非常好的权衡.有没有办法让XmlSerializer池字符串,以便重复被丢弃,并可以在下次gen0 GC发生时回收?
还有一些最后的说明:
我无法更改XML架构.它是来自第三方供应商的导出文件.
我知道可以(理论上)使用一个更快的解析器XmlReader,它不仅允许我自己进行字符串池化,而且还可以在导入中期处理数据,这样所有200k行都不能保存在RAM中直到我已经阅读了整个文件.不过,我宁愿不花时间编写和调试自定义解析器.真正的XML比示例复杂一点,所以这是一项非常重要的任务.如上所述 - XmlSerializer我的目的确实表现得非常好,我只是想知道是否有一种简单的方法来调整它.
我可以编写一个自己的字符串池并在Column.Namesetter中使用它,但我不愿意(1)这意味着摆弄自动生成的代码,(2)它开启了一系列与并发相关的问题和内存泄漏.
不,通过"汇集",我不是指"实习",因为这会导致内存泄漏.
就我个人而言,我会毫不犹豫地手动启动实体 - 要么通过假设生成的代码的所有权,要么手动执行(并摆脱数组;-p)。
再并发——你也许可以有一个线程静态池?AFAIK,XmlSerializer只使用一个线程,所以这应该没问题。当你用完后,它还可以让你把游泳池扔掉。那么你就可以有一个类似静态池的东西,但是每个线程。然后也许调整设置器:
class Column
{
private string name, value;
public string Name {
get { return this.name; }
set { this.name= MyPool.Get(value); }
}
public string Value{
get { return this.value; }
set { this.value = MyPool.Get(value); }
}
}
Run Code Online (Sandbox Code Playgroud)
其中静态方法与用 装饰的MyPool.Get静态字段(大概是)进行对话。HashSet<string>[ThreadStatic]