我在流媒体模式下使用WCF在进程之间传输一些大型short[]
数组,而且我遇到了传输速度非常慢的问题。
我已经完成了一些测试,事实证明,传输short[]
数组比使用包含相同字节数的byte[]
数组慢大约800倍。
我认为我必须在这里做错事,因为这种行为是不可能的。
鉴于以下复制,有人可以建议我如何加快速度吗?
请注意,我使用的是流模式,因为数组非常大,使用非流模式似乎在传输过程中总共使用了数组大小的三倍。 (我在一个单独的进程中包装第三方32位托管DLL,以便可以通过WCF从64位C#程序调用它。)
这是服务器和客户端代码。这似乎很长,但它是我能想出的最短完整的复制品......
代码非常简单:WCF接口只有两个方法,一个采用short[]
参数,另一个采用byte[]
参数。我通过传递short[]
和byte[]
来测试它,每个Stopwatch
和ITest
包含相同数量的字节,并使用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);
}
}
}
}
来计算所需的时间。
为简化起见,我已将using System;
using System.ServiceModel;
using System.Threading;
using Shared;
namespace Shared
{
[ServiceContract]
interface ITest
{
[OperationContract]
void ShortTest(short[] array);
[OperationContract]
void ByteTest(byte[] array);
}
}
namespace Server
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
class Server : ITest
{
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 serviceHost = new ServiceHost(new Server());
serviceHost.AddServiceEndpoint(typeof(ITest), binding, "net.pipe://localhost/wcftest");
serviceHost.Open();
Console.WriteLine("Server started. Close console to stop.");
Thread.Sleep(TimeSpan.FromHours(10));
}
public void ShortTest(short[] array)
{
Console.WriteLine("ShortTest() received array of size " + array.Length);
}
public void ByteTest(byte[] array)
{
Console.WriteLine("ByteTest() received array of size " + array.Length);
}
}
}
接口的副本放入客户端和服务器源代码中,以避免使用第三个库 - 真正的代码正确执行。
这些只是控制台应用程序 - 您只需要以任何顺序编译和运行它们,然后在客户端应用程序中按Enter键运行测试。
另请注意,我使用.Net 4.6.2,但我与其他版本的结果相似。
的客户端
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()
服务器
short[]
我在系统上得到的结果如下:
byte[]
有没有人有任何想法如何加快request
数据的传输?
目前,我希望自己只需将其转换为bytes
,但这是最令人不满意的。