【问题标题】:WCF serialization is slow at the first callWCF 序列化在第一次调用时很慢
【发布时间】:2012-01-27 21:21:06
【问题描述】:

我正在使用 .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 次并衡量性能。

测量对“RecieveBigDataType”的 10 次调用,我发现第一次调用比其他调用慢得多。似乎 WCF 第一次需要序列化类型“BigDataType”的速度非常慢。 有什么想法可以让第一次通话更快吗?

【问题讨论】:

  • 客户的测试怎么样? . .表示创建ServiceClient对象一次并调用它10次或每次创建新的serviceclient并调用方法。
  • 只创建一个ServiceClient对象,然后执行上面写的动作1-2。
  • 1.当您第一次创建对象时 2. 然后您第一次调用 Web 服务,它将在那时创建通信通道。因此,当下次调用 hapeend 时,它会继续使用该通道,因此后续调用会更快。尝试每次创建 ServiceClient 并衡量性能差异。
  • dotnetstep,这就是我首先调用“RecieveInteger”服务的原因。涉及“BigDataType”的调用是这里的问题。
  • 对不起,肖恩,不知道,但如果您找到答案,请在此处回复。

标签: c# performance wcf serialization datacontractserializer


【解决方案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 进行测试),不幸的是没有任何改进。
  • 也许你的启动时间是基于每个服务操作的。
  • 这肯定是一个序列化问题。如果我之后会调用另一个服务操作(使用相同的参数)它会很快。感谢您提供帮助。
【解决方案2】:

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) {}
        }
    }
}

【讨论】:

    猜你喜欢
    • 2018-02-02
    • 1970-01-01
    • 2013-01-31
    • 2017-05-23
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多