A common question that I get from folks at my talks as well as clients is how binary performance of WCF stacks up against .NET Remoting. To quickly level-set, the lingua franca for all messages that WCF exchanges is SOAP/XML. However, out of the box, WCF provides 3 means for representing the message payload on the wire:
Of the encodings above, only Text and MTOM are interoperable (and I'll cover these in upcoming posts), but sometimes, in a .NET to .NET messaging scenario, encoding the message in a binary representation will yield smaller payloads and thus more efficient message transfer (especially when pairing a binary message with TCP). It is important to note that regardless of the encoding used to serialize the message, the message itself is SOAP and thus can be de-serialized according to the SOAP standard in use on the client and server stack.
It is widely documented that the System.Runtime.Serialization assembly introduces an optimized byte representation for packaging XML/SOAP via the XmlDictonaryWriter which can be found in the System.Xml namespace within the System.Runtime.Serialization.dll.
In short, WCF leverages the XmlDictionaryWriter which provides a factory method for getting a binary writer which is capable of taking an XML document and serializing it to a proprietary binary format:
XmlDocument doc = new XmlDocument();
doc.Load(from);
FileStream stream = new FileStream(to, FileMode.OpenOrCreate);
XmlDictionaryWriter binaryWriter = XmlDictionaryWriter.CreateBinaryWriter(stream);
doc.WriteContentTo(binaryWriter);
binaryWriter.Flush();
The code above takes a file containing the following XML and loads it into an instance of the XmlDocument:
Then, using the binary encoder, the stream is written to a file called "CustomerWCF.bin" on disk, which when opened looks like this:
Similarly, if I want to use the "legacy" BinaryFormatter, which ships in the System.Runtime.Serialization.Formatters namespace of mscorlib, I can write the following code which loads and serializes the same Customer.xml file:
XmlDocument doc = new XmlDocument();
doc.Load(from);
FileStream stream = new FileStream(to, FileMode.OpenOrCreate);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, doc.InnerXml);
This time, the contents is written to a file called CustomerNET.bin which resembles the following:
Of course, both of these files are encoded in binary, so when you open them in notepad or some other tool (in this case I am using Visual Studio) you will see some semblance of the original message with corresponding octal representation for each byte of data. It is evident, in just looking at the octal representation that the CustomerNET.bin is larger.
In fact, it turns out that the CustomerWCF.bin file has a size of 98 bytes, compared to the CustomerNET.bin file that has a size of 205 bytes.
Customer.WCF.bin:
CustomerNET.bin:
Given this very simple example, you could say that the WCF binary encoder produces a payload that is roughly half the size of the BinaryFormatter!
It is important to note that the these are different binary representations, that are each proprietary and therefore not interoperable outside of the .NET Framework. In fact, the WCF version of the Customer.xml contents is only supported within .NET 3.0 and later, and is naturally the encoder that is used when exchanging binary messages with WCF. The cool thing is that you can leverage this encoding outside of WCF, provided you have .NET 3.0+ on both sides of the wire.
Forthcoming: Exploring Text and MTOM message representations.