XML与序列化/反序列化的二进制性能

时间:2009-07-07 12:28:07

标签: c# .net serialization compact-framework protobuf-net

我正在开发一个紧凑的框架应用程序,需要提高性能。该应用程序当前通过将对象序列化为XML并将其存储在数据库中而脱机工作。使用分析工具,我可以看到这是一个相当大的开销,减慢了应用程序。我想如果我切换到二进制序列化,性能会增加,但因为在紧凑的框架中不支持,我看了protobuf-net。序列化似乎更快,但反序列化要慢得多,并且应用程序比序列化更多地反序列化。

二进制序列化应该更快,如果是这样,我可以做些什么来加快性能?以下是我如何使用XML和二进制文件的片段:

XML序列化:

public string Serialize(T obj)
{
  UTF8Encoding encoding = new UTF8Encoding();
  XmlSerializer serializer = new XmlSerializer(typeof(T));
  MemoryStream stream = new MemoryStream();
  XmlTextWriter writer = new XmlTextWriter(stream, Encoding.UTF8);
  serializer.Serialize(stream, obj);
  stream = (MemoryStream)writer.BaseStream;
  return encoding.GetString(stream.ToArray(), 0, Convert.ToInt32(stream.Length));
}
public T Deserialize(string xml)
{
  UTF8Encoding encoding = new UTF8Encoding();
  XmlSerializer serializer = new XmlSerializer(typeof(T));
  MemoryStream stream = new MemoryStream(encoding.GetBytes(xml));            
  return (T)serializer.Deserialize(stream);
}

Protobuf-net二进制序列化:

public byte[] Serialize(T obj)
{
  byte[] raw;
  using (MemoryStream memoryStream = new MemoryStream())
  {
    Serializer.Serialize(memoryStream, obj);
    raw = memoryStream.ToArray();
  }

  return raw;            
}

public T Deserialize(byte[] serializedType)
{
  T obj;
  using (MemoryStream memoryStream = new MemoryStream(serializedType))
  {
    obj = Serializer.Deserialize<T>(memoryStream);
  }
  return obj;
}

6 个答案:

答案 0 :(得分:5)

我要对此进行纠正,Marc Gravall指出第一次迭代有一个建模模型的开销,所以我做了一些测试,平均需要1000次迭代的序列化和反序列化来处理XML和二进制文件。我首先使用Compact Framework DLL的v2尝试我的测试,然后使用v3.5 DLL。这是我得到的,时间是在ms:

.NET 2.0
================================ XML ====== Binary ===
Serialization 1st Iteration      3236       5508
Deserialization 1st Iteration    1501       318
Serialization Average            9.826      5.525
Deserialization Average          5.525      0.771

.NET 3.5
================================ XML ====== Binary ===
Serialization 1st Iteration      3307       5598
Deserialization 1st Iteration    1386       200
Serialization Average            10.923     5.605
Deserialization Average          5.605      0.279

答案 1 :(得分:3)

您方法的主要开支是实际生成XmlSerializer类。创建序列化器是一个耗时的过程,您应该只为每个对象类型执行一次。尝试缓存序列化程序,看看是否能提高性能。

根据这个建议,我看到我的应用程序中的性能大幅提升,这使我能够继续使用XML序列化。

希望这有帮助。

答案 2 :(得分:1)

有趣......想法:

  • 这是什么版本的CF; 2.0? 3.5?特别是,CF 3.5具有Delegate.CreateDelegate,允许protobuf-net比CF 2.0中的can更快地访问属性
  • 您是在注释字段还是属性?同样,在CF中,反射优化是有限的;您可以使用属性获得CF 3.5中的beter性能,就像字段一样,我唯一可用的选项是FieldInfo.SetValue

CF中还有许多其他东西根本不存在,所以它必须在一些地方做出妥协。对于过于复杂的模型,还有一个known issue with the generics limitations of CF。正在进行修复,但这是一个更改,并且需要“一段时间”。

有关信息,常规(完整).NET上的一些指标比较各种格式(包括XmlSerializer和protobuf-net)are here

答案 3 :(得分:0)

您是否尝试过为类创建自定义序列化类?而不是使用XmlSerializer,它是一个通用的序列化程序(它在运行时创建一堆类)。这是一个工具(sgen)。您在构建过程中运行它,它会生成一个可以在XmlSerializer中使用的自定义程序集。

如果您有Visual Studio,则可以在项目属性的“构建”选项卡下找到该选项。

答案 4 :(得分:0)

在序列化对象或将它们写入数据库时​​,性能是否受到影响?由于编写它们可能会遇到某种缓慢存储,我认为它比序列化步骤要大得多。

请记住,Marc Gravell发布的性能指标测试的性能超过1,000,000次迭代。

您将它们存储在哪种数据库中?对象是在内存中序列化还是直接存储?他们是如何被发送到数据库的?物体有多大?如果更新了一个,您是将所有对象发送到数据库,还是只发送了更改的对象?您是否在内存中缓存任何内容,或者每次都从存储中重新读取?

答案 5 :(得分:0)

XML的处理速度通常很慢,占用了大量空间。已经有很多不同的尝试来解决这个问题,而今天最流行的尝试似乎只是放弃了gzip文件,就像使用Open Packaging Convention一样。

W3C表明gzip方法不是最优的,他们和各种other groups一直致力于更好的二进制序列化,适合快速处理和压缩,用于传输。