Since I’m lik­ing git more and more by the day, with tools such as Smart­Git and Git­Flow mak­ing the task of man­ag­ing even a com­plex branch­ing model a rel­a­tively easy task, I’ve decided to move my Sim­ple Speed Tester project over to github!

Sim­ple Speed Tester is a very sim­ple frame­work I wrote to help me run bench­marks and is used to power my JSON and binary seri­al­iz­ers bench­marks. It takes cares of some of the orches­tra­tion that you tend to do when run­ning bench­marks, e.g.:

  • repeat­ing a test mul­ti­ple times
  • time the indi­vid­ual runs
  • ignore the min and max runs and use the rest to cal­cu­late a mean­ing­ful average

It’s intended to be really easy to use (see exam­ples here) and for one and only one use case – help you speed test a spe­cific piece of code!

If you’re like me and like to run your own bench­marks then check it out, you can also install it via Nuget.

Share

Note: don’t for­get to check out the Bench­marks page to see the lat­est round up of binary and JSON serializers.

 

Since my last round of bench­marks on binary seri­al­iz­ers, there’s a new player in town – Mes­sage­Shark, which at the time of this writ­ing does not sup­port seri­al­iza­tion of fields, but offers com­pa­ra­ble speed and pay­load to protobuf-net.

Using the same test objects, here’s how Mes­sage­Shark com­pares to the other binary serializers:

Untitled_1

Untitled_2

Untitled

It’s early days for Mes­sage­Shark but the signs are good, com­pa­ra­ble seri­al­iza­tion speed with protobuf-net and a notice­ably faster dese­ri­al­iza­tion speed, def­i­nitely one to keep an eye out for!

Share

Note: don’t for­get to check out the Bench­marks page to see the lat­est round up of binary and JSON serializers.

A lit­tle while ago I put together a quick per­for­mance test com­par­ing the BCL’s Bina­ry­For­mat­ter with that of Marc Grav­ell’s protobuf-net library (.Net imple­men­ta­tion of Google’s pro­to­col buffer for­mat). You can read more about my results here.

There’s another fast binary seri­al­iza­tion library which I had heard about before, Mes­sagePack, which claims to be 4 times faster than pro­to­col buffers which I find a lit­tle hard to believe, so nat­u­rally, I have to see for myself!

Tests

The con­di­tions of the test is very sim­i­lar to those out­lined in my first post, except Mes­sagePack is now included in the test.

I defined two types to be serialized/deserialized, both con­tain the same amount of data, one exposes them as pub­lic prop­er­ties whilst the other exposes them as pub­lic fields:

image image

The rea­son for this arrange­ment is to try and get the best per­for­mance out of Mes­sagePack (see Note 2 below).

100,000 iden­ti­cal instances of the above types are seri­al­ized and dese­ri­al­ized over 5 runs with the best and worst results excluded, results of the remain­ing 3 runs are then aver­aged to give the final results.

Results

image

image

image

A cou­ple of obser­va­tions from these results:

1. Bina­ry­For­mat­ter per­forms bet­ter with fields – faster seri­al­iza­tion and smaller payload!

2. Protobuf-net per­forms equally well with fields and prop­er­ties – because it’s dri­ven by the [DataMem­ber] attributes.

3. Mes­sagePack per­forms sig­nif­i­cantly bet­ter with fields – over 10% faster seri­al­iza­tion and deserialization!

4. Mes­sagePack is NOT 4x faster than Pro­to­col Buffer! – at least not with the two imple­men­ta­tions (Msg­Pack and Profotbuf-net) I have tested here, speed-wise there’s not much sep­a­rat­ing the two and depend­ing on the data being seri­al­ized you might find a slightly dif­fer­ent result.

5. Mes­sagePack gen­er­ates big­ger pay­load than Pro­to­col Buffer – again, depend­ing on the data being seri­al­ized you might arrive at a slightly dif­fer­ent result.

Source code

If you’re inter­ested in run­ning the tests your­self, you can find the source code here. It uses my Sim­ple­SpeedTester frame­work to orches­trate test runs but you should be able to get the gist of it fairly easily.

Clos­ing thoughts…

Although Mes­sagePack couldn’t back up its claim to be 4x faster than Pro­to­col Buffer in my test here, it’s still great to see that it offers com­pa­ra­ble speed and pay­load, which makes it a viable alter­na­tive to Pro­to­col Buffer and in my opin­ion hav­ing a num­ber of dif­fer­ent options is always a plus!

In addi­tion to seri­al­iza­tion Mes­sagePack also offers a RPC frame­work, and is also widely avail­able with client imple­men­ta­tions avail­able in quite a num­ber of dif­fer­ent lan­guage and plat­forms, e.g. C#, JavaScript, Node.Js, Erlang, Python and Ruby, so it’s def­i­nitely worth con­sid­er­ing when you start a new project.

On a dif­fer­ent note, although you’re able to get a good 10% improve­ment in per­for­mance when you use fields instead of prop­er­ties to expose pub­li­cally avail­able data in your type, it’s impor­tant to remem­ber that the idiomatic way in .Net is to use pub­lic properties.

As much as I think per­for­mance is of para­mount impor­tance, main­tain­abil­ity of your code is a close sec­ond, espe­cially in an envi­ron­ment where many devel­op­ers will be work­ing on the same piece of code. By fol­low­ing the ‘rec­og­nized’ way of doing things you can more eas­ily com­mu­ni­cate your inten­tions to other devel­op­ers work­ing on the same code.

Imag­ine you’ve inten­tion­ally used pub­lic fields in your class because you know it will be seri­al­ized by the Mes­sagePack seri­al­izer but then a new devel­oper joins the team and, not know­ing all the intri­cate details of your code, decides to con­vert them all to pub­lic prop­er­ties instead..

So if you’re will­ing to step out of the idiomatic .Net way to get that per­for­mance boost, be sure to com­ment your code well in all the places where you’re diverg­ing from the norm!

NOTE 1:

The Sim­pleOb­ject class in this post is slightly dif­fer­ent from the one I used in my pre­vi­ous post, the ‘Scores’ prop­erty is now an int array instead of List<int>, doing so dras­ti­cally improved per­for­mance for ALL the seri­al­iz­ers involved.

This is because the imple­men­ta­tion of List<T> uses an array inter­nally and the array is resized when capac­ity is reached. So even though you only have x num­ber of items in a List<T> the inter­nal array will always have more than x num­ber of spaces. Which is why Sim­pleOb­ject in my first post (where ‘Scores’ is of type List<int>) is seri­al­ized into 708 bytes by the Bina­ry­For­mat­ter but the Sim­pleOb­ject class defined in this post can be seri­al­ized into 376 bytes.

Sim­i­larly, ini­tial­iz­ing an instance of Dictionary<TKey, TValue> with the intended capac­ity allows you to add items to it much more effi­ciently, for more details, see here.

Note 2:

One caveat I came across in the Mes­sagePack test was that, if you instan­ti­ate Com­piled­Packer with­out any para­me­ter, the default behav­iour is to seri­al­ize pub­lic fields only and that meant none of the pub­lic prop­er­ties I’ve defined on the Sim­pleOb­ject type will get seri­al­ized. As a result, to serialize/deserialize instances of Sim­pleOb­ject I needed to use an instance of Com­piled­Packer that seri­al­izes pri­vate fields too, which accord­ing to the MessagePack’s Get­tingStarted guide, is slower.

So in order to get the best per­for­mance (speed) out of Mes­sagePack, I defined a sec­ond type (see Sim­pleOb­jectWith­Fields type above) to see how well it does with a type that defines pub­lic fields instead of prop­er­ties. In the inter­est of fair­ness, I repeated the same test for Bina­ry­For­mat­ter and protobuf-net too, just to see if you get bet­ter per­for­mance out of them too.

Share

Note: don’t for­get to check out the Bench­marks page to see the lat­est round up of binary and JSON serializers.

When work­ing with the Bina­ry­For­mat­ter class fre­quently, one of the things you notice is that it is really damn inef­fi­cient… both in terms of speed as well as the pay­load (the size of the seri­al­ized byte array).

Google’s Pro­to­col Buffers for­mat is designed to be super fast and min­i­mizes the pay­load by requir­ing a seri­al­iz­able object to define ahead of time the order in which its properties/fields should be serialized/deserialized in, doing so removes the need for all sorts of meta­data that tra­di­tion­ally need to be encoded along with the actual data.

Marc Grav­ell (of Stack­Over­flow fame!) has a .Net imple­men­ta­tion called ‘protobuf-net’, and is said to totally kick ass! As with most per­for­mance related top­ics, it’s hugely intrigu­ing to me so I decided to put it to test myself :-)

Assumptions/Conditions of tests

  1. code is com­piled in release mode, with opti­miza­tion option turned on
  2. 5 runs of the same test is per­formed, with the top and bot­tom results excluded, the remain­ing three results is then averaged
  3. 100,000 iden­ti­cal instances of type SimpleObject(see below) is seri­al­ized and deserialized
  4. serialization/deserializatoin of the objects hap­pen sequen­tially in a loop (no concurrency)

image

Results

Unsur­pris­ingly, the protobuf-net seri­al­izer wins hands-down in all three cat­e­gories, as you can see from the table below it is a stag­ger­ing 12x faster than Bina­ry­For­mat­ter when it comes to seri­al­iza­tion, with a pay­load size less than 15th of its counterpart’s.

One curi­ous obser­va­tion about the pay­load size is that, when I used a Bina­ry­Writer to sim­ply write every prop­erty into the out­put stream with­out any meta­data, what I got back should be the min­i­mum pay­load size with­out com­pres­sion, and yet the protobuf-net seri­al­izer still man­ages to beat that!

image

image

image

Bina­ry­For­mat­ter with ISerializable

I also tested the Bina­ry­For­mat­ter with a class that imple­ments the ISe­ri­al­iz­able inter­face (see below) because oth­ers had sug­gested in the past that you are likely to get a notice­able per­for­mance boost if you imple­ment the ISe­ri­al­iz­able inter­face your­self. The belief is that it will per­form much bet­ter as it removes the reliance on reflec­tion which can be detri­men­tal to the per­for­mance of your code when used excessively.

How­ever, based on the tests I have done, this does not seem to be the case, the slightly bet­ter seri­al­iza­tion speed is far from con­clu­sive and is off­set by a slightly slower dese­ri­al­iza­tion speed..

image

Source code

If you’re inter­ested in run­ning the tests your­self, you can find the source code here, it uses my Sim­ple­SpeedTester frame­work to orches­trate the test runs but you should be able to get the gist of it fairly easily.

UPDATE 2011/08/24:

As I men­tioned in the post, protobuf-net man­aged to pro­duce a smaller pay­load than what is required to hold all the prop­erty val­ues of the test object with­out any meta.

I posted this ques­tion on SO, and as Marc said in his answer the smaller pay­load is achieved through the use of varint and zigzag encod­ing, read more about them here.

Share

Since I do a fair bit of per­for­mance tests on ran­dom things that pique my inter­est, it’s only nat­ural that I should make the task of car­ry­ing out these tests eas­ier for myself, so over the week­end I put together a sim­ple, no frills frame­work to do just that!

The Sim­ple­SpeedTester project is intended to make it eas­ier to:

  • time the exe­cu­tion of some code
  • orches­trate mul­ti­ple runs of the same test
  • col­late the exe­cu­tion time of the test runs
  • pro­vide an easy way to obtain sum­mary for the tests

What it’s not

It’s not a pro­filer! It doesn’t tell you which line of your code is tak­ing what per­cent­age of your CPU time or how much mem­ory is used where. It’s intended for one thing and one thing only – help you speed test a spe­cific piece of code/method over mul­ti­ple runs, col­late the results and work out the aver­age for you so you don’t have to.

Get­ting Started

To get started, down­load the bina­ries here, ref­er­ence the SimpleSpeedTester.dll in your project, and all you need is one line of code to sched­ule a test to be run mul­ti­ple times and get a sum­mary of the test runs:

   1: // initialize a new test group

   2: var testGroup = new TestGroup("Example2");

   3:  

   4: // PlanAndExecute executes the Action delegate 5 times and returns the result summary

   5: var testResultSummary = testGroup.PlanAndExecute("Test1", () => { }, 5);

   6:  

   7: Console.WriteLine(testResultSummary);

   8: /* prints out something along the line of

   9:  *

  10:  * Test Group [Example2], Test [Test1] results summary:

  11:  * Successes   [5]

  12:  * Failures    [0] 

  13:  * Average Exec Time [...] milliseconds

  14:  *

  15:  */

And you’re done! Easy, right? ;-)

I’ve included a cou­ple more exam­ples here cov­er­ing the most com­mon use cases, more will be added as I add more functionalities.

So what are you wait­ing for? Go on, down­load it and play around with it, let me know what you think, any con­struc­tive sug­ges­tions are very welcomed!

Share