c# - XmlSerializer 可以池化字符串以避免大的重复字符串吗?

标签 c# .net xml-serialization memory-management

我有一些非常大的 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 制作一个更快的解析器,它不仅可以让我做我自己的字符串池,而且还可以在中期处理数据import 这样在我读完整个文件之前,不必将所有 200k 行都保存在 RAM 中。不过,我宁愿不花时间编写和调试自定义解析器。实际的 XML 比示例稍微复杂一些,因此这是一项非常重要的任务。如上所述 - XmlSerializer 的性能确实足以满足我的目的,我只是想知道是否有一种简单的方法可以稍微调整它。

  • 我可以编写自己的字符串池并在 Column.Name setter 中使用它,但我不想因为 (1) 这意味着摆弄自动生成的代码,并且 (2) 它会引发一系列与并发和内存泄漏相关的问题。

  • 不,我所说的“池化”并不是指“实习”,因为这会导致内存泄漏。

最佳答案

就个人而言,我会毫不犹豫地手动启动实体 - 要么通过承担生成代码的所有权,要么手动执行(并摆脱数组 ;-p)。

重新并发 - 你或许可以有一个线程静态池?据我所知,XmlSerializer只使用一个线程,所以这应该没问题。它还可以让你在完成后把游泳池扔掉。那么你可以有一些东西一个静态池,但每个线程。然后也许调整 setter :

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); }
    }
}

其中静态 MyPool.Get方法与用 HashSet<string> 装饰的静态字段(大概是 [ThreadStatic])对话.

关于c# - XmlSerializer 可以池化字符串以避免大的重复字符串吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/713178/

相关文章:

c# - 如何将伪json数组反序列化为c#

c# - linq中的关键字是什么?

c# - IObservable TakeLast(n) 和阻塞

c# - XmlSerializer 生成没有命名空间前缀的 XML

xml - XML 属性中哪些字符无效(除非已编码)?

C# 赢。表格 - 如何从 "System Summary"获取 "msinfo32"

c# - 如何在 Windows 服务中使用 Quartz.Net 安排任务?

c# - Keys.PageDown.ToString() 返回 Next

c# - 如何访问有关 WCF 服务部署位置的信息

c# - XML 序列化没有得到预期的 xml 文件 c#