序列化性能差的可能解决方案

red*_*alx 14 .net asp.net reflection performance serialization

我最近使用进程外会话状态对ASP.NET应用程序进行了一些性能测试和分析 - 这在Web场上使用会话状态时是必要的,这样可以在任何Web服务器上检索状态,例如,如果后续HTTP请求到达不同的服务器,因为会话不是"粘性"或原始服务器已关闭等.

让我感到惊讶的是,当我满负荷运行Web服务器并分析CPU使用率时,99%的CPU时间用于序列化和反序列化会话状态.随后我们实现了一个定制的"缓存"状态服务器; 这总是序列化状态,但也保持状态在内存中,这样如果你使用粘性会话,状态不必在大多数时间反序列化.这使服务器吞吐量提高了2倍; 但是,序列化仍然占CPU时间的98%或更多.

我们通过在序列化之前"修剪"会话状态中对象之间不必要的对象引用来获得速度的进一步改进 - 在反序列化时手动修复引用.这种速度提高了10-20%左右.这里的原因是一些性能损失是由于内置的​​序列化必须遍历对象指针的图形,这变成了一个更复杂的任务,有更多的指针.

继续调查,我们为一些类编写了自定义序列化例程,而不是依赖于.Net的内置序列化.我们发现,性能大大提高了约50倍.似乎CPU负载的大部分是由内置的.Net序列化引起的,而后者由于依赖于使用Reflection来遍历对象指针/图形并提取字段数据而变慢.

将我们的性能提高50倍是非常诱人的,因此将网络服务器硬件要求降低了很多(并且功率要求较低但仍然很重要).目前的选项是:

1)编写自定义序列化.由于任务的复杂性及其产生的维护开销,这是一个问题,也就是说,对类状态的任何更改都需要更改序列化/反序列化例程.

2)一些第三方解决方案.也许某些产品在构建时自动生成状态保存/加载代码,因此无需使用Reflection.

我很想知道是否有人知道第三方解决方案,或者遇到过这个问题,因为我没有从互联网搜索中找到任何提及它的内容.

更新:有些人建议在默认的内置序列化和纯自定义序列化例程之间采用一种中途解决方案.我们的想法是为最能影响性能的类实现自定义序列化,例如重写ISerializable.这是一种有趣且有前景的方法; 但是,我仍然认为可以完全替换内置序列化而无需编写和维护任何自定义代码 - 这在运行时无法完成,因为查询对象和访问私有数据需要Reflection.但理论上可以对已经构建的程序集进行后处理,并将新方法作为额外的构建步骤注入.一些分析器使用此方法在C#编译器构建之后将分析代码注入到程序集中.此外,我/我/我在某处读到.Net框架支持将方法注入到类中 - 因此可能需要处理IL的所有问题.

Rob*_*ert 2

不幸的是,我只知道选项一,而且说实话,这可能会开始变得非常痛苦。

但它只做你想做的事,所以速度尽可能快。

祝你好运。