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

发布于 2024-12-22 15:53:35 字数 510 浏览 2 评论 0原文

我正在使用 .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”类型的速度非常慢。 有什么办法可以让第一次通话更快吗?

I'm using .Net 3.5 SP1, working with the default WCF serializer - DataContractSerializer.
I have this simple interface:

[ServiceContract]
public interface IService
{
    [OperationContract]
    void RecieveInteger(int value);

    [OperationContract]
    void RecieveBigDataType(BigDataType value);
}

My client does the following:

  1. Invokes 'RecieveInteger' just to warm-up the service.
  2. Invokes 'RecieveBigDataType' 10 times and measure performance.

Measuring the 10 calls to 'RecieveBigDataType', I found the first call is much slower than the others. It seems like the first time WCF needs to serialize the type 'BigDataType' is happening very slow.
Any ideas to make the first call faster?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浪漫人生路 2024-12-29 15:53:35

根据 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

According to MSDN, for the XmlSerializer,

Initializing XmlSerializer by Calling FromTypes on Startup

The first time XmlSerializer encounters a type, it generates code to perform serialization and then it caches that code for later use. However, if you call the FromTypes static method on the XmlSerializer, it forces XmlSerializer to immediately generate and cache the required code for the types you plan to serialize. This reduces the time taken to serialize a specific type for the first time. The following example shows this approach.

static void OnApplicationStart()
{
  Type[] myTypes = new Type[] { Type.GetType("customer"), Type.GetType("order") };
  XmlSerializer.FromTypes( myTypes );
}

I know you are using WCF which uses DataContractSerializer, but there maybe some way to do the same thing.

From here: http://msdn.microsoft.com/en-us/library/ff650685.aspx

绝對不後悔。 2024-12-29 15:53:35

我在使用 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) {}
        }
    }
}

I had nearly the same issue with DataContractJsonSerializer. In my case first call of DataContractJsonSerializer.WriteObject(..) took 1.3 sec more then other calls for the same object.
To be honestly the serialized object had some interfaces, so KnownTypes had to be defined.

The only work around I had found was to run a Task on application start and serialize dummy objects of known types.
Interesting is that on the thread pool serialization of dummy objects took 0.5 sec less time than on GUI.

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) {}
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文