C# 流短[]比流字节[]慢约800倍-如何提高速度?

C# 流短[]比流字节[]慢约800倍-如何提高速度?,c#,wcf,C#,Wcf,我在流模式下使用WCF的进程之间传输一些大的short[]数组,我遇到了一个传输速度非常慢的问题 我做了一些测试,结果表明传输short[]数组比使用包含相同字节数的byte[]数组慢800倍左右 我想我一定是做错了什么,因为这种行为是不可预料的 鉴于下面的复制,有人能建议我如何加快复制速度吗? 请注意,我使用流模式是因为阵列非常大,而使用非流模式似乎在传输期间总共使用了阵列大小的三倍。(我将第三方32位托管DLL包装在一个单独的进程中,以便可以通过WCF从64位C#程序调用它。) 这是服务器和

我在流模式下使用WCF的进程之间传输一些大的
short[]
数组,我遇到了一个传输速度非常慢的问题

我做了一些测试,结果表明传输
short[]
数组比使用包含相同字节数的
byte[]
数组慢800倍左右

我想我一定是做错了什么,因为这种行为是不可预料的

鉴于下面的复制,有人能建议我如何加快复制速度吗?

请注意,我使用流模式是因为阵列非常大,而使用非流模式似乎在传输期间总共使用了阵列大小的三倍。(我将第三方32位托管DLL包装在一个单独的进程中,以便可以通过WCF从64位C#程序调用它。)

这是服务器和客户端代码。它看起来很长,但这是我能想出的最短的完整复制

代码非常简单:WCF接口只有两个方法,一个采用
short[]
参数,另一个采用
byte[]
参数。我通过传递一个
short[]
和一个
byte[]
来测试它,每个字节都包含相同的字节数,并使用一个
秒表来计时需要多长时间

为了简化工作,我将
ITest
接口的副本放在客户端和服务器源代码中,以避免第三个库—真正的代码可以正确地执行

这两个应用程序都只是控制台应用程序,您只需按任意顺序编译和运行它们,然后在客户端应用程序中按ENTER键即可运行测试

还要注意的是,我使用的是.NET4.6.2,但在其他版本中也有类似的结果

客户端

using System;
using System.Diagnostics;
using System.ServiceModel;
using Shared;

namespace Shared
{
    [ServiceContract]
    interface ITest
    {
        [OperationContract]
        void ShortTest(short[] array);

        [OperationContract]
        void ByteTest(byte[] array);
    }
}

namespace Client
{
    class Client
    {
        static void Main()
        {
            int arraySizeInBytes = 10 * 1024 * 1024;

            var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
            {
                MaxReceivedMessageSize = 4*arraySizeInBytes + 1024,
                SendTimeout            = TimeSpan.FromHours(1), // To allow debugging without timeouts.
                ReceiveTimeout         = TimeSpan.FromHours(1),
                ReaderQuotas           = {MaxArrayLength = 4*arraySizeInBytes + 1024},
                TransferMode           = TransferMode.Streamed
            };

            var channelFactory = new ChannelFactory<ITest>(binding, "net.pipe://localhost/wcftest");
            var proxy = channelFactory.CreateChannel();

            short[] shorts = new short[arraySizeInBytes/sizeof(short)];

            for (int i = 0; i < shorts.Length; ++i) // Touch entire array to ensure memory allocated.
                shorts[i] = 1;

            byte[] bytes = new byte[arraySizeInBytes];

            for (int i = 0; i < bytes.Length; ++i) // Touch entire array to ensure memory allocated.
                bytes[i] = 1;

            Stopwatch sw = new Stopwatch();

            while (true)
            {
                Console.WriteLine("Press <ENTER> to call ByteTest() and ShortTest()");
                Console.ReadLine();

                Console.WriteLine("Calling ByteTest()");
                sw.Restart();
                proxy.ByteTest(bytes);
                Console.WriteLine("ByteTest() took " + sw.Elapsed);

                Console.WriteLine("Calling ShortTest()");
                sw.Restart();
                proxy.ShortTest(shorts);
                Console.WriteLine("ShortTest() took " + sw.Elapsed);
            }
        }
    }
}
我在系统上得到的结果如下:

Press <ENTER> to call ByteTest() and ShortTest()

Calling ByteTest()
ByteTest() took 00:00:00.0519079
Calling ShortTest()
ShortTest() took 00:00:41.9868413
Press <ENTER> to call ByteTest() and ShortTest()

Calling ByteTest()
ByteTest() took 00:00:00.0344547
Calling ShortTest()
ShortTest() took 00:00:41.4307394
Press <ENTER> to call ByteTest() and ShortTest()
按下可调用ByteTest()和ShortTest()
调用ByteTest()
ByteTest()花了00:00:00.0519079
调用ShortTest()
ShortTest()花了00:00:41.9868413
按下可调用ByteTest()和ShortTest()
调用ByteTest()
ByteTest()花了00:00:00.0344547
调用ShortTest()
ShortTest()花了00:00:41.4307394
按下可调用ByteTest()和ShortTest()
有人知道如何加快
short[]
数据的传输吗


目前,我希望我只能自己将其转换为
字节[]
,但这是最不令人满意的。

您愿意使用不同的跨进程通信方式吗?;文档中说short[]根本不应该被允许用于流式传输:文档中一定是错误的,因为代码是运行的。@usr好的,如果它不起作用,我就打开自己的MMF,并通过它填充所有大的二进制数据(并且只将WCF用于控制流)。@usr Yes,在阅读了更多的内容后,似乎并没有像您所建议的那样,正确地支持这种流式传输(of
short[]
)。使用
MemoryMappedFile
通过该路径传递数据将相对容易(并且使用
UnmanagedMemoryAccessor.ReadArray()
UnmanagedMemoryAccessor.WriteArray()将数据复制到MMF中和从MMF中复制出来应该会非常快。
)所以我想我最终会采用这种方法。我相信ReadArray方法非常慢,如果我回忆正确的话,它是基于反射的。当心。使用memcpy在非托管缓冲区之间进行复制似乎是性能上最安全的选择。
Press <ENTER> to call ByteTest() and ShortTest()

Calling ByteTest()
ByteTest() took 00:00:00.0519079
Calling ShortTest()
ShortTest() took 00:00:41.9868413
Press <ENTER> to call ByteTest() and ShortTest()

Calling ByteTest()
ByteTest() took 00:00:00.0344547
Calling ShortTest()
ShortTest() took 00:00:41.4307394
Press <ENTER> to call ByteTest() and ShortTest()