I am moving several large arrays short[]between processes using WCF in streaming mode, and I ran into a problem when the transfer is very slow.
I did some tests, and it turned out that passing an array is short[]about 800 times slower than using an array byte[]that contains the same number of bytes.
I assume that I should be doing something wrong here, as this behavior cannot be expected.
Given the playback below, can anyone suggest how I can speed it up?
Please note that I use streaming mode because the arrays are VERY large, and using non-streaming mode seems to use three times the size of the array during transmission. (I am wrapping a 32-bit third-party managed DLL in a separate process so that it can be called from a 64-bit C # program through WCF.)
Here is the server and client code. It seems pretty long, but it's the shortest full review I can come up with ...
The code is very simple: the WCF interface has only two methods: one accepts a parameter short[], and the other accepts a parameter byte[]. I test it by passing short[]and byte[], each of which contains the same number of bytes, and use Stopwatchfor time how long it takes.
, ITest , - .
- , ENTER .
, .Net 4.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),
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)
shorts[i] = 1;
byte[] bytes = new byte[arraySizeInBytes];
for (int i = 0; i < bytes.Length; ++i)
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);
}
}
}
}
SERVER
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),
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);
}
}
}
, , :
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[], .