9

我正在开发一个紧凑的框架应用程序,需要提高性能。该应用程序当前通过将对象序列化为 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;
}
4

6 回答 6

6

我要纠正自己,Marc Gravall 指出第一次迭代有构建模型的开销,所以我做了一些测试,对 XML 和二进制进行平均 1000 次序列化和反序列化迭代。我首先使用 Compact Framework DLL 的 v2 进行了测试,然后使用了 v3.5 DLL。这是我得到的,时间以毫秒为单位:

.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
于 2009-07-08T12:56:18.667 回答
3

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

按照这个建议,我看到我的应用程序的性能有了很大的提升,这让我可以继续使用 XML 序列化。

希望这可以帮助。

于 2011-11-19T17:58:32.423 回答
1

有趣的......想法:

  • 这是什么版本的CF;2.0?3.5?特别是,CF 3.5Delegate.CreateDelegate允许 protobuf-net 访问属性的速度比 CF 2.0 中的 can 快得多
  • 您在注释字段属性吗?同样,在 CF 中,反射优化是有限的。您可以在 CF 3.5 中通过properties获得更好的性能,因为我唯一可用的选项是FieldInfo.SetValue

CF中还有很多其他的东西根本不存在,所以它不得不在一些地方做出妥协。对于过于复杂的模型,CF 的泛型限制也存在一个已知问题。修复正在进行中,但这是一个很大的变化,并且需要“一段时间”。

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

于 2009-07-07T12:34:33.473 回答
0

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

W3C已经表明 gzip 方法不是最优的,他们和其他各种小组一直在致力于更好的二进制序列化,适用于快速处理和压缩,以进行传输。

于 2009-07-10T18:56:21.470 回答
0

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

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

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

于 2009-07-08T06:36:16.093 回答
0

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

如果您有 Visual Studio,则该选项在项目属性的“生成”选项卡下可用。

于 2009-07-07T12:41:54.990 回答