【问题标题】:Most efficient way to build a serializer in C#在 C# 中构建序列化程序的最有效方法
【发布时间】:2021-12-03 22:47:08
【问题描述】:

我目前正在构建自己的序列化程序,并且我不想再滥用 System.Xml.Linq 类,所以我正在构建自己的序列化程序。

假设我有这些课程:

  • XmlElement
  • XmlAttribute
  • XmlText

让我们假设它们只有一个返回stringName 属性和一个返回IReadonlyList<IXmlNode>Value 属性。

我的问题是,让类自己负责写出自己的序列化值会更有效,还是让一个使用模式匹配的类更有效?

例如选项A

public class XmlElement: IXmlNode {

    public void Write(StringBuilder stringBuilder) {

        stringBuilder.WriteLine($"<{Name}>")

        foreach(var child in Children) {
            child.Write(stringBuilder);
        }

        stringBuilder.WriteLine($"</{Name}>")

    }

}

选项B

public class XmlWriter {

    public string Write(IXmlNode node, StringBuilder passedStringBuilder) {

        var stringBuilder = passedStringBuilder ?? new StringBuilder();

        if (IXmlNode is XmlElement xmlElement) WriteElement(xmlElement, stringBuilder);
        if (IXmlNode is XmlAttribute xmlAttribute) WriteAttribute(xmlAttribute, stringBuilder);
        if (IXmlNode is XmlText xmlText) WriteText(xmlText, stringBuilder);

        return stringBuilder.ToString();
    }

    public void WriteElement(XmlElement element, stringBuilder) {

        stringBuilder.WriteLine($"<{element.Name}>")

        foreach(var child in element.Children) {
            Write(child, stringBuilder);
        }

        stringBuilder.WriteLine($"</{element.Name}>")

    }

}

显然,编写 XML 序列化程序还有更多内容,这不是很好的代码,我在这里和那里遗漏了一些部分。
我最关心的是哪个概念最有效。

其他信息

由于有人要求定义我所说的效率,这里有一些因素我想对实施进行评分:

  • Speed
  • Garbage collection
  • Memory allocation

当然,代码可读性也是一个因素,但是,此时我已经编写了两个实现,关于可读性选项 A 有我的偏好。 选项 B 在一个文件中产生了相当多的代码行,可以说它对一个类来说做得太多了。

简而言之:
除非 选项 B 大大优于 选项 A,否则我的偏好将倾向于 选项 A

【问题讨论】:

  • 请定义效率
  • 您无法自己进行测试是否有原因?
  • 但是您已经编写了两个基本实现。如果您问题中的代码足以让其他人回答问题,那么您也应该足以回答问题。
  • @devlin 只有当每个人都拥有相同的知识时才会如此,这将使 StackOverflow 完全无用。
  • @ShrimpPerator :除了这个问题不是仅依赖于知识的问题。 “效率”是整个领域的因素,其中大部分是我们不知道的。

标签: c# .net-core serialization xml-serialization


【解决方案1】:

在这种情况下,我想答案是选项A

我做了什么来测试这个:

  • 我为 JSON 和 XML 创建了基本数据类型,当调用 ToString 时它们会写出自己的序列化值
  • 我编写了一些测试来比较预期字符串表示的输出,以确保输出符合我的预期
  • 我为 JSON 和 XML 数据类型创建了序列化程序的基本实现
  • 我在现有测试中添加了测试用例,以确保两种解决方案的输出相同
  • 我为这两种选项和两种数据类型编写了一个基本的BenchmarkDotNet 测试,并使用Bogus 推动的大约 200 个复杂项目的数据输入作为初始样本运行该测试

这是基准测试的结果:

// * Summary *

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19043.1288 (21H1/May2021Update)
Intel Core i7-8750H CPU 2.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK=5.0.402
  [Host]                                                                              : .NET Core 3.1.20 (CoreCLR 4.700.21.47003, CoreFX 4.700.21.47101), X64 RyuJIT
  BenchmarkDotNet, Version=0.13.1.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4 : .NET Core 3.1.20 (CoreCLR 4.700.21.47003, CoreFX 4.700.21.47101), X64 RyuJIT

Job=BenchmarkDotNet, Version=0.13.1.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4  MaxRelativeError=0.01  IterationCount=1
LaunchCount=5  RunStrategy=ColdStart  UnrollFactor=1
WarmupCount=1

|           Method |       Mean |     Error |   StdDev |       Gen 0 | Completed Work Items | Lock Contentions |      Gen 1 | Allocated |
|----------------- |-----------:|----------:|---------:|------------:|---------------------:|-----------------:|-----------:|----------:|
| JsonDataToSTring |   420.3 ms |  42.31 ms | 10.99 ms |  19000.0000 |               4.0000 |                - |  6000.0000 |    232 MB |
| SerialJsonWriter |   420.7 ms |  58.03 ms | 15.07 ms |  19000.0000 |               4.0000 |                - |  6000.0000 |    232 MB |
|  XmlDataToSTring | 1,012.1 ms | 342.95 ms | 89.06 ms | 145000.0000 |               4.0000 |                - | 35000.0000 |  1,036 MB |
|  SerialXmlWriter | 1,128.5 ms |  70.71 ms | 18.36 ms | 203000.0000 |               4.0000 |                - | 40000.0000 |  1,384 MB |

基准测试无论如何都不是广泛的,我没有进行非常深入的评估,因为这些结果对我来说非常清楚。

对于 JSON 和 XML,选项 A 在非常小的数据集上在 timegarbage collectionmemory allocation 上得分最高。

回想起来,我本可以预见到这一点,因为 C# 不支持尾递归。
事实上,当我增加数据大小时,我设法通过分析溢出堆栈的代码使我的计算机崩溃。

PS:我认为过多详细说明数据的生成方式没有什么价值,因为这么小的数据集已经产生了如此大的影响。

【讨论】:

    猜你喜欢
    • 2022-10-23
    • 2014-05-14
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 2022-11-14
    • 2012-02-22
    相关资源
    最近更新 更多