Zulfiqar's weblog

Architecture, security & random .Net

Calculating WCF Message Size

Posted by zamd on August 15, 2008


Here I have talked about various encoding options and their impact on the message size (byte stream produced by WCF). The question is how you can measure the size of the byte stream produced by WCF?

Size of the byte stream depends on the encoder being used and different encoder produced byte stream of different sizes.

I have written a MessageInspector, which does message/stream rewriting to calculate the size of the final byte stream. Once you have configured this inspector in your client it will print the difference in the size of message created by text encoder vs your configured encoder (MTOM, Binary or GZip).  Send method of Inspector looks like following:

public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)

{

    var mb = request.CreateBufferedCopy(int.MaxValue);

    request = mb.CreateMessage();

    var ms = new MemoryStream();

 

    // Dump message size based on text encoder.

    using (var memWriter = XmlDictionaryWriter.CreateTextWriter(ms))

    {

        mb.CreateMessage().WriteMessage(memWriter);

        memWriter.Flush();

        Console.WriteLine("Message size using text encoder {0}", ms.Position);

    }

    ms = new MemoryStream();

    if (gzipEncoding != null)

    {// GZip Special case

        var encoder = gzipEncoding.CreateMessageEncoderFactory().CreateSessionEncoder();

        encoder.WriteMessage(mb.CreateMessage(), ms);

        Console.WriteLine("GZip encoded size {0}", ms.Position);

        return null;

    }

    // just wrap the message – and wrapper will do the trick.

    request = new WrappingMessage(request);

    return null;

}

 

public class WrappingMessage : Message

{

    Message innerMsg;

    MessageBuffer msgBuffer;

    public WrappingMessage(Message inner)

    {

        this.innerMsg = inner;

        msgBuffer = innerMsg.CreateBufferedCopy(int.MaxValue);

        innerMsg = msgBuffer.CreateMessage();

    }

    public override MessageHeaders Headers

    {

        get { return innerMsg.Headers; }

    }

 

    protected override void OnWriteBodyContents(XmlDictionaryWriter writer)

    {

        innerMsg.WriteBodyContents(writer);

    }

 

    public override MessageProperties Properties

    {

        get { return innerMsg.Properties; }

    }

 

    public override MessageVersion Version

    {

        get { return innerMsg.Version; }

    }

 

    protected override void OnWriteMessage(XmlDictionaryWriter writer)

    {

        // write message to the actual stream using encoder..

        base.OnWriteMessage(writer);

        writer.Flush();

        // write message to MemoryStream (using encoder) to get it’s size.

        var copy = msgBuffer.CreateMessage();

        DumpEncoderSize(writer, copy);

    }

    private static void DumpEncoderSize(System.Xml.XmlDictionaryWriter writer, Message copy)

    {

        var ms = new MemoryStream();

        string configuredEncoder = string.Empty;

        if (writer is IXmlTextWriterInitializer)

        {

            var w = (IXmlTextWriterInitializer)writer;

            w.SetOutput(ms, Encoding.UTF8, true);

            configuredEncoder = "Text";

        }

        else if (writer is IXmlMtomWriterInitializer)

        {

            var w = (IXmlMtomWriterInitializer)writer;

            w.SetOutput(ms, Encoding.UTF8, int.MaxValue, "", null, null, true, false);

            configuredEncoder = "MTOM";

        }

        else if (writer is IXmlBinaryWriterInitializer)

        {

            var w = (IXmlBinaryWriterInitializer)writer;

            w.SetOutput(ms, null, null, false);

            configuredEncoder = "Binary";

        }

        copy.WriteMessage(writer);

        writer.Flush();

        var size = ms.Position;

        Console.WriteLine("Message size using configured ({1}) encoder {0}",  size,configuredEncoder);

    }

 

}

I have attached complete solution with this post.

Download: MessageSize.zip

Advertisements

4 Responses to “Calculating WCF Message Size”

  1. Kevin Burton said

    The MessageSize.zip does not seem to have the code mentioned in this article.

  2. namigop said

    Hi zamd,

    Love your post! I tried out the code and it worked perfectly. I was able to measure the message size of the response on the service side by moving the code to the BeforeSendReply method of IDispatchMessageInspector. Would you know of a way to get the size of the inbound request from the service side code? I do not have control on the clients.

    Erik

  3. sabbadin enrico said

    what about logging the size of the response mesage ?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: