Victor Garcia Aprea : Tuesday, May 11, 2004 - Posts

Subscriptions

<March 2010>
SuMoTuWeThFrSa
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910

Post Categories




Tuesday, May 11, 2004 - Posts

We need to get ScottGu to start blogging (again!)

The other day while I was reconstructing my OPML file I stumped across ScottGu weblog and noticed he hasn’t blogged this year yet. I already know that based on my poor average of 2,6 posts/month I’m in no position for asking anyone to blog more regularly.

 

But… Scott you are “ScottGu”!! I mean… you *need* to post more regularly, or better said, *we need* you to post more regularly.

 

From personal experience I know that writing, reviewing, giving talks, having a family *AND* having a day job makes it really difficult to find the free time to blog. But… Scott… I want to know what you’re into, no matter if it’s about Whidbey, Orcas or NextCoolCodeNameGoesHere technology.

 

How many people will notice if VGA has a 2,6 posts/month? Actually just a few, one of them being my friend Daniel who likes to remember me -about every day- of that poor average… But Scott… I bet there are *lots* of people waiting to read stuff from you. So let’s make all these people happy!, right?

 

And… I’m making a public compromise of making 3 (yes, that’s three) posts per every post made by Scott -- offer valid through May04 only, sorry!  :-)

 

posted Tuesday, May 11, 2004 7:43 PM by vga with 3 Comments

Don't let the BinaryFormatter get at it!

All the stuff written out there about viewstate will alert you that it was designed to handle only the following types: int, String, Boolean, Pair, Triple, Array, ArrayList, Hashtable and that trying to store anything else will incur in a performance loss. This is a well-known fact but what is not so well-known is the real why behind this.

 

One of the things I like to mention in my talks while addressing viewstate performance is something like “don’t let the BinaryFormatter get at your data”. I like all the “what??” this phrase causes at first :-) but after a bit of explanation everything comes back to normal again.

 

So, let’s see how the LosFormatter type –which happens to be the viewstate serializer- was designed for dealing with type serialization.

 

Its first approach is a very common one; it consists of checking if the type its dealing with it’s a simple one that it knows how to quickly serialize (the types listed at the very beginning of this post). In case it’s dealing with such a type it just needs to write out some form of header (usually a type code, which will be used to know what type follows) and then the customized (and fast) serialization happens. Note this is not really a novel ideal and it is exactly the same AltSerialization type already does.

 

Now, if the type LosFormatter is trying to serialize it’s not a supported one it will check if that type has an associated TypeConverter (yes, this implies some reflection code so you can start feeling the perf loss already, can you?). If a type converter is found then it will just say: “Hey you, type converter! Could you please serialize this type to a string representation for me please?”. It will then just use the output produced by the type converter.

 

But what happens if the type hasn’t an associated type converter. Well in this case the LosFormatter will say “Oh damn!, I don’t know how to serialize this type by myself and worse yet, it doesn’t have an associated type converter available to do the work for me; what am I gonna do now?” Its own answer is: “Let’s use the BinaryFormatter!”. Note that we’re talking here about instantiating a new BinaryFormatter and feeding it with the type in question. As you can imagine this is *lot* more work than any of the previous two steps, so you *really* want to avoid getting here in the first place.

 

 

Let’s put the above explanation into perspective; let’s say you’ve the following type:

 

[Serializable]

public class Customer {

     private String _lastname;

     private String _firstname;

     private String _address;

     private int _age;

     private int _code;

 

public Customer (String lastName, String firstName, String address, int age, int code) {

this._lastname = lastName;

           this._firstname = firstName;

           this._address = address;

           this._age = age;

           this._code = code;

 

     public String LastName {

           get {return _lastname;}

           set {_lastname = value;}

     }

     public String FirstName

     {

           get {return _firstname;}

           set {_firstname = value;}

     }

     public String Address

     {

           get {return _address;}

           set {_address = value;}

     }

     public int Age

     {

           get {return _age;}

           set {_age = value;}

     }

     public int Code

     {

           get {return _code;}

           set {_code = value;}

     }

}

 

Now let’s say you need to persist an instance of this Customer type to viewstate. If you just do so, the type won’t be one of the supported ones by LosFormatter and it won’t have a type converter associated so the BinaryFormatter will kick. Let’s try it:

 

 

Customer cust = new Customer("Garcia Aprea","Victor","1802 4th Clarius Ave.",29,31987);

LosFormatter los = new LosFormatter();

StringWriter sw = new StringWriter();

los.Serialize (sw, cust);

String resultSt = sw.GetStringBuilder ().ToString();

int size = sw.GetStringBuilder ().ToString().Length;

 

 

If you read size value you will notice that you just paid 436 bytes to serialize a Customer. For three short strings and two integers that seems just too much.

Let’s now code a type converter that knows how to persist a Customer to a String and get back a Customer from a String:

 

 

     public class CustomerConverter : System.ComponentModel.TypeConverter

     {

 

           public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)

           {

                if (sourceType == typeof(String))

                     return true;

                return base.CanConvertFrom (context, sourceType);

           }

 

           public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)

           {

                if (destinationType == typeof(String))

                     return true;

                return base.CanConvertTo (context, destinationType);

           }

 

           public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)

           {

                String state = value as String;

                if (state == null)

                     return base.ConvertFrom (context, culture, value);

                String []parts = state.Split ('#');

                return new Customer (parts[0], parts[1], parts[2], System.Convert.ToInt32 (parts[3]), System.Convert.ToInt32 (parts[4]));

           }

 

           public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)

           {

                if (destinationType == null)

                     throw new ArgumentException ("destinationType");

                Customer cust = value as Customer;

                if (cust != null)

                     return cust.LastName + "#" + cust.FirstName + "#" + cust.Address + "#" + cust.Age.ToString() + "#" + cust.Code.ToString();

                else

                     return base.ConvertTo (context, culture, value, destinationType);

           }

     }

 

And let’s attach it to the Customer type:

 

[TypeConverter (typeof(CustomerConverter))]

public class Customer

 

Run again the previous code used to feed a Customer instance to the LosFormatter and this time the footprint will be of 196 bytes! That’s quite a reduction, isn’t it?

 

Lastly, let’s play by LosFormatter rules and offer it a type that it knows how to handle:

 

Triplet t = new Triplet (cust.LastName, cust.FirstName, cust.Address);

Pair p = new Pair (cust.Age, cust.Code);

Pair custPair = new Pair (t,p);

 

Now feed the LosFormatter with custPair and not just an instance of Customer; this time the footprint will be of… 60 bytes! Another great improvement over the original 436 bytes.

 

I’m hoping that you can now see there are *real* benefits of knowing this stuff and that you could start taking advantage of it right away! :-)

posted Tuesday, May 11, 2004 6:24 PM by vga with 23 Comments