WCF序列化在第一次调用时较慢

3
我将使用.Net 3.5 SP1,并与默认的WCF序列化程序DataContractSerializer一起工作。 我有这个简单的接口:
[ServiceContract]
public interface IService
{
    [OperationContract]
    void RecieveInteger(int value);

    [OperationContract]
    void RecieveBigDataType(BigDataType value);
}

我的客户端需要执行以下操作:

  1. 调用 'RecieveInteger' 以预热服务。
  2. 调用 'RecieveBigDataType' 10 次并测量性能。

在测量 10 次对 'RecieveBigDataType' 的调用时,我发现第一次调用比其他调用慢得多。似乎第一次 WCF 需要序列化类型 'BigDataType' 的时间非常慢。 有什么想法可以使第一次调用更快吗?


你的客户端测试怎么样了?是创建一个ServiceClient对象然后调用10次,还是每次都创建新的ServiceClient并调用方法? - dotnetstep
创建一个ServiceClient对象,然后执行上述的1-2个操作。 - Sean
  1. 当您第一次创建对象时,
  2. 然后您第一次调用 Web 服务时,它将在那时创建通信通道。因此,当下一次调用发生时,它会持续使用该通道,因此后续调用更快。尝试每次创建 ServiceClient 并测量性能差异。
- dotnetstep
dotnetstep,这就是我首先调用“RecieveInteger”服务的原因。 涉及“BigDataType”的调用是问题所在。 - Sean
抱歉,Sean,我不知道,但如果你找到了答案,请在这里回复。 - tom redfern
2个回答

1
根据MSDN文档,对于XmlSerializer, 在启动时通过调用FromTypes初始化XmlSerializer 第一次XmlSerializer遇到一个类型时,它会生成代码来执行序列化,然后将该代码缓存以供以后使用。但是,如果您调用XmlSerializer的FromTypes静态方法,则会强制XmlSerializer立即生成并缓存所需类型的代码以进行序列化。这可以减少第一次序列化特定类型所用的时间。以下示例显示了这种方法。
static void OnApplicationStart()
{
  Type[] myTypes = new Type[] { Type.GetType("customer"), Type.GetType("order") };
  XmlSerializer.FromTypes( myTypes );
}

我知道你正在使用使用DataContractSerializer的WCF,但可能有一些方法可以做同样的事情。

从这里开始:http://msdn.microsoft.com/en-us/library/ff650685.aspx


我已尝试过它(还将我的序列化器更改为xmlSerializer以进行测试),不幸的是没有任何改善。 - Sean
也许你的启动时间是基于每个服务操作的。 - tom redfern
这肯定是一个序列化问题。如果之后我调用另一个服务操作(使用相同的参数),它会很快。感谢你的帮助。 - Sean

0

我遇到了与DataContractJsonSerializer几乎相同的问题。在我的情况下,第一个调用DataContractJsonSerializer.WriteObject(..)比同一对象的其他调用慢了1.3秒。
说实话,序列化对象具有某些接口,因此必须定义KnownTypes

我唯一找到的解决方法是在应用程序启动时运行一个Task,并对已知类型的虚拟对象进行序列化。
有趣的是,在线程池上,虚拟对象的序列化时间比在GUI上少0.5秒。

Task.Run(() =>
{
    var knownTypes = new[] { typeof(ServiceImpl_1), typeof(ServiceImpl_2), typeof(ServiceImpl_3)};
    var ser = new System.Runtime.Serialization.Json.DataContractJsonSerializer
                (
                    typeof(IService),
                    new DataContractJsonSerializerSettings { KnownTypes = knownTypes }
                );

    using(var ms = new MemoryStream())
    {
        foreach(var tp in knownTypes)
        {
            object inst = null;
            try
            {
                foreach(var ctorInf in tp.GetConstructors())
                {
                    try
                    {
                        var prInfos = ctorInf.GetParameters();
                        if(prInfos.Length == 0)
                        {
                            inst = Activator.CreateInstance(tp);
                        }
                        else
                        {
                            var parList = new object[prInfos.Length];
                            for(int i = 0; i < prInfos.Length; i++)
                            {
                                parList[i] = prInfos[i].ParameterType.IsValueType ? Activator.CreateInstance(prInfos[i].ParameterType) : null;
                            }
                            inst = Activator.CreateInstance(tp, parList);
                        }
                    }
                    catch(Exception)
                    {
                        continue;
                    }
                    ser.WriteObject(ms, inst);
                }
            }
            catch(Exception exc) {}
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接