Introduction
Recently, I was developing a function which included transferring an image in a message package. So, following a habit, I made up a property in the message class like this: public List<byte> Image { get; set; }
. This Image
is sent to the client through a duplex channel. Can you imagine how I was surprised when I saw the percentage of processor consumption for this service process? It was ~15-20% loaded with an image size of ~400 KB. I then started to think about a better solution.
Background
Here is the structure of duplex channels in WCF:
[ServiceContract(CallbackContract = typeof(IServiceCallback),
SessionMode = SessionMode.Required)]
public interface IService
{
[OperationContract(IsOneWay = true)]
void SendData(List<byte> array);
}
public interface IServiceCallback
{
[OperationContract(IsOneWay = true)]
void RecieveData(List<byte> array);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,
ConcurrencyMode = ConcurrencyMode.Multiple,
MaxItemsInObjectGraph = Int32.MaxValue)]
public class Service : IService
{
public void SendData(List<byte> array)
{
IServiceCallback callback =
OperationContext.Current.GetCallbackChannel<IServiceCallback>();
callback.RecieveData(array);
}
}
Using the Code
A search for a solution to the problem took a considerable quantity of my time, and then, having replaced the type List<byte>
with an array of bytes, I received considerably better results: practically ~1-2% loading. Why is there such a big difference between what would seem like identical types of data? The difference is in how the SOAP message is generated. For List<byte>
:
...
<s:Body u:Id="_0"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-utility-1.0.xsd">
<SendData xmlns="http://tempuri.org/">
<array
xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:unsignedByte>0</a:unsignedByte>
<a:unsignedByte>0</a:unsignedByte>
<a:unsignedByte>0</a:unsignedByte>
<a:unsignedByte>0</a:unsignedByte>
<a:unsignedByte>0</a:unsignedByte>
<a:unsignedByte>0</a:unsignedByte>
<a:unsignedByte>0</a:unsignedByte>
<a:unsignedByte>0</a:unsignedByte>
<a:unsignedByte>0</a:unsignedByte>
<a:unsignedByte>0</a:unsignedByte>
<a:unsignedByte>0</a:unsignedByte>
<a:unsignedByte>0</a:unsignedByte>
...
</array>
</SendData>
</s:Body>
...
And for the array of bytes:
...
<s:Body u:Id="_0"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<SendData xmlns="http://tempuri.org/">
<array>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</array>
</SendData>
</s:Body>
...
Points of Interest
In general, the difference in size of these two SOAP messages differed approximately 10 times, and the loading of the processor fell from ~15-20 % to ~1-3 % at the same size of package. I was very surprised, because nowhere have I found official information on these differences.