2

更新

这个问题被确定不是 XmlSerializer 和反序列化的问题,而实际上是从远程源读取响应流的问题。感谢Chris SinclairJesse C. Slicer在确定我所看到的差异方面提供的帮助和指导。


我一直在分析将XmlSerializer静态 XML 数据块反序列化到我的自定义MyXmlObject类中所花费的时间,尽管数据完全相同,但从请求到请求的时间似乎波动很大。

我在将 XML 传递给serializer.Deserialize()方法的那一刻开始计时反序列化,并在完成后立即停止计时:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
//initialization stuff and writing to request stream.

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
    //If I run a stopwatch up to this point, I get the round trip time,
    //so I know that the stream has already been received at this point.

    using (Stream stream = response.GetResponseStream()) //In production this stream is received from a remote server.
    {
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();

        MyXmlObject obj = (MyXmlObject)serializer.Deserialize(stream);

        stopwatch.Stop();
    }
}

我的XmlSerializer对象定义如下:

private static readonly XmlSerializer serializer = new XmlSerializer(typeof(MyXmlObject));

我的 WCF Web 服务是一个多线程的单例。

[ServiceBehavior(
    ConcurrencyMode = ConcurrencyMode.Multiple,
    InstanceContextMode = InstanceContextMode.Single)]

以下是我对 15 个并发请求反序列化一个只有 177,792 字节的静态 XML 数据块的结果:

177,792 字节的静态 XML 文件

Request   Execution (ms)
1         300
2         302
3         303
4         303
5         368 *High
6         303
7         302
8         242 *Low
9         243
10        244
11        245
12        242
13        243
14        883 *Outlier
15        260

如您所见,它有些一致,但仍会波动约 +/-100 毫秒

在这个相对较小的 XML 文件中,波动很小,但如果我向它提供一个更大的文件(我将在我的 WCF Web 服务中更频繁地接收它,它的波动会更加剧烈:

3,851,199 字节的静态 XML 文件

Request   Execution (ms)
1         1384
2         2402
3         1715
4         4000 *Outlier
5         1310
6         2132
7         1388
8         1654
9         1183
10        1464
11        2368
12        2752 *High
13        1094 *Low
14        1838
15        1940

因此,您可以看到反序列化 XML 文件所花费的时间比在较小文件上的波动要大得多。

我希望它是相对相同的(只有 +/- 100 毫秒),但是相反,我看到了 +/- 1200 毫秒或更大的差异。

此外,2.5 秒的时间比我希望放弃将 XML 反序列化为 C# POD 对象的时间要多。有趣的是,当我将数据返回到服务器时,WCF 将 C# POD 对象序列化为 JSON 相对较快。

问题

  • 为什么会出现这些波动?
  • 如果有的话,我能做些什么来最小化这些波动?
  • 是否有另一种类型的 Xml 反序列化可以更快地将这种大小的传入 Xml 转换为 C# POD 对象的层次结构?
    • 也许DataContractSerializer
    • DataContractSerializer使用XmlSerializer引擎盖下?

如果我遗漏了任何对诊断此问题有用的信息,请告诉我。谢谢。

4

2 回答 2

3

根据评论,这里有一段代码纯粹用于测量反序列化时间,而不是通过网络接收响应流。请注意,它确实依赖于 .NET 4 的CopyTo()方法Stream来工作。

var request = (HttpWebRequest)WebRequest.Create(uri);
// initialization stuff and writing to request stream.

using (var response = (HttpWebResponse)request.GetResponse())
using (var stream = response.GetResponseStream())
using (var memoryStream = new MemoryStream())
{
    // In production this stream is fully received from a remote server.
    stream.CopyTo(memoryStream);
    memoryStream.Seek(0, SeekOrigin.Begin);

    // If I run a stopwatch up to this point, I get the round trip time,
    // so I know that the stream has already been received at this point.
    var stopwatch = Stopwatch.StartNew();

    var obj = (MyXmlObject)serializer.Deserialize(memoryStream);

    stopwatch.Stop();
}
于 2013-08-23T15:21:49.223 回答
2

鉴于您的评论和您进行基准测试的方式,我不认为速度缓慢或波动的根源是由于 XML 反序列化。

根据我的经验,使用XmlSerializer反序列化的速度非常快,而且对于大约 3.5 兆字节的文件,肯定不会在 2-4 秒的范围内。我敢打赌,如果您要进行另一个测试,只需在没有任何网络的情况下反序列化静态 XML 字符串,您会发现它非常、非常快(我敢打赌少于 50 毫秒;当然远不及 2000 毫秒)。

但是,对于您发布的代码,我相信存在一些网络问题或其他影响时间的因素。如果您更改基准测试以将流读取与 XML 反序列化分开,您会发现反序列化本身对总时间的贡献可能微不足道。

我怀疑其他网络问题与 WCF 服务有关。我建议发布一个新问题,完全消除 XML 反序列化,并简单地测量读取原始数据流的速度。也许用户将能够为您提供关于如何优化/配置/改进该方面的更好的想法,因为序列化不是这里的问题。

于 2013-08-23T15:47:34.503 回答