<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;Ak8CRnk9fCp7ImA9WhRUFko.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763</id><updated>2012-01-27T07:41:07.764-08:00</updated><category term="tpl" /><category term="reflection" /><category term="linq" /><category term="me" /><category term="dynamic" /><category term="disposable" /><category term="redis" /><category term="autism" /><category term="community" /><category term="metaprogramming" /><category term="serialization" /><category term="c# linq" /><category term="expression" /><category term="immutability" /><category term="cf" /><category term="4.0" /><category term="c# .net 5.0 async redis" /><category term="c#" /><category term="mvc" /><category term="stackoverflow" /><category term="generics" /><category term="phone-7" /><category term="linq expression c#" /><category term="5.0" /><category term="asp.net" /><category term=".net" /><category term="protobuf-net" /><category term="c# profiling" /><category term="surface" /><category term="async" /><category term="ide" /><category term="stackexchange" /><title>Code, code and more code.</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://marcgravell.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>112</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/CodeCodeAndMoreCode" /><feedburner:info uri="codecodeandmorecode" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>51.8167</geo:lat><geo:long>-2.4833</geo:long><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by/2.0/" /><entry gd:etag="W/&quot;CEAFSXc_cSp7ImA9WhRVFEk.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-7502015263835482265</id><published>2012-01-12T15:20:00.001-08:00</published><updated>2012-01-13T00:18:38.949-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-13T00:18:38.949-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dynamic" /><category scheme="http://www.blogger.com/atom/ns#" term="reflection" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><category scheme="http://www.blogger.com/atom/ns#" term="metaprogramming" /><title>Playing with your member</title><content type="html">&lt;p style="font-weight: normal; "&gt;(and: introducing &lt;a href="http://nuget.org/packages/FastMember"&gt;FastMember&lt;/a&gt;)&lt;/p&gt;  &lt;p style="font-weight: normal; "&gt;Toying with members. We all do it. Some do it slow, some do it fast.&lt;/p&gt;  &lt;p style="font-weight: normal; "&gt;I am of course talking about the type of flexible member access that you need regularly in data-binding, materialization, and serialization code – and various other utility code.&lt;/p&gt;  &lt;h3 style="font-weight: normal; "&gt;Background&lt;/h3&gt;  &lt;p style="font-weight: normal; "&gt;Here’s standard member access:&lt;/p&gt; &lt;code style="font-weight: normal; "&gt;Foo obj = GetStaticTypedFoo(); &lt;br /&gt;obj.Bar = "abc";&lt;/code&gt;   &lt;p style="font-weight: normal; "&gt;Not very exciting, is it? Traditional static-typed C# is very efficient here when everything is known at compile-time. With C# 4.0, we also get nice support for when the target is not known at compile time:&lt;/p&gt; &lt;code style="font-weight: normal; "&gt;dynamic obj = GetDynamicFoo(); &lt;br /&gt;obj.Bar = "abc";&lt;/code&gt;   &lt;p style="font-weight: normal; "&gt;Looks much the same, eh? But what about when the &lt;em&gt;member&lt;/em&gt; is not known? What we can’t do is:&lt;/p&gt; &lt;code style="font-weight: normal; "&gt;dynamic obj = GetStaticTypedFoo(); &lt;br /&gt;string propName = "Bar";  &lt;br /&gt;obj.propName = "abc"; // does not do what we intended!&lt;/code&gt;   &lt;p style="font-weight: normal; "&gt;So, we find ourselves in the realm of reflection. And as everyone knows, reflection is &lt;em&gt;slooooooooow&lt;/em&gt;. Or at least, it is normally; if you don’t object to talking with &lt;a href="http://en.wikipedia.org/wiki/Cthulhu"&gt;Cthulhu&lt;/a&gt; you can get into the exciting realms of meta-programming with tools like &lt;code&gt;Expression&lt;/code&gt; or &lt;code&gt;ILGenerator&lt;/code&gt; – but most people like keeping hold of their sanity, so… what to do?&lt;/p&gt;  &lt;h3 style="font-weight: normal; "&gt;Middle-ground&lt;/h3&gt;  &lt;p style="font-weight: normal; "&gt;A few years ago, I threw together &lt;a href="http://www.codeproject.com/KB/cs/HyperPropertyDescriptor.aspx"&gt;&lt;code&gt;HyperDescriptor&lt;/code&gt;&lt;/a&gt;; this is a custom implementation of the &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.aspx"&gt;&lt;code&gt;System.ComponentModel&lt;/code&gt;&lt;/a&gt; representation of properties, but using some IL instead of reflection – significantly faster. It is a good tool – a &lt;em&gt;worthy&lt;/em&gt; tool; but… I just can’t get excited about it now, for various reasons, but perhaps most importantly:&lt;/p&gt;  &lt;ul style="font-weight: normal; "&gt;   &lt;li&gt;the weirdness that is &lt;code&gt;System.ComponentModel&lt;/code&gt; is slowly fading away into obscurity &lt;/li&gt;    &lt;li&gt;it does not really address the DLR &lt;/li&gt; &lt;/ul&gt;  &lt;p style="font-weight: normal; "&gt;Additionally, I’ve seen a few bug reports since 4.0, and frankly I’m not sure it is quite the right tool now. Fixing it is sometimes a bad thing.&lt;/p&gt;  &lt;p style="font-weight: normal; "&gt;Having written tools like &lt;a href="http://code.google.com/p/dapper-dot-net/"&gt;dapper-dot-net&lt;/a&gt; and &lt;a href="http://code.google.com/p/protobuf-net/"&gt;protobuf-net&lt;/a&gt;, my joy of meta-programming has grown. Time to start afresh!&lt;/p&gt;  &lt;h3 style="font-weight: normal; "&gt;FastMember&lt;/h3&gt;  &lt;p style="font-weight: normal; "&gt;So with gleaming eyes and a bottle of Chilean to keep the evil out, I whacked together a fresh library; &lt;code&gt;FastMember&lt;/code&gt; – available on &lt;a href="http://code.google.com/p/fast-member/"&gt;google-code&lt;/a&gt; and &lt;a href="http://nuget.org/packages/FastMember"&gt;nuget&lt;/a&gt;. It isn’t very big, or very complex – it simply aims to solve two scenarios:&lt;/p&gt;  &lt;ul style="font-weight: normal; "&gt;   &lt;li&gt;reading and writing properties and fields (known by name at runtime) on a set of homogeneous (i.e. groups of the same type) objects &lt;/li&gt;    &lt;li&gt;reading and writing properties and fields (known by name at runtime) on an individual object, which might by a DLR object &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Here’s some typical usage &lt;b&gt;&lt;span&gt;(EDITED - API changes)&lt;/span&gt;&lt;/b&gt;:&lt;/p&gt; &lt;code style="font-weight: normal; "&gt;var accessor = TypeAccessor.Create(type); &lt;br /&gt;string propName = // something known only at runtime  &lt;br /&gt;while( /* some loop of data */ ) {  &lt;br /&gt;accessor[obj, propName] = rowValue;  &lt;br /&gt;}&lt;/code&gt;   &lt;p style="font-weight: normal; "&gt;or:&lt;/p&gt;  &lt;p style="font-weight: normal; "&gt;&lt;code&gt;// could be static or DLR   &lt;br /&gt;&lt;/code&gt;&lt;code&gt;var wrapped = ObjectAccessor.Create(obj);   &lt;br /&gt;string propName = // something known only at runtime    &lt;br /&gt;Console.WriteLine(wrapped[propName]);&lt;/code&gt; &lt;/p&gt;  &lt;p style="font-weight: normal; "&gt;Nothing hugely exciting, but it comes up often enough (especially with the DLR aspect) to be worth putting somewhere reusable. It might also serve as a small but complete example for either meta-programming (&lt;code&gt;ILGenerator&lt;/code&gt; etc), or manual DLR programming (&lt;code&gt;CallSite&lt;/code&gt; etc).&lt;/p&gt;  &lt;h3 style="font-weight: normal; "&gt;Mary Mary quite contrary, how does your member perform?&lt;/h3&gt;  &lt;p style="font-weight: normal; "&gt;So let’s roll some numbers; I’m bundling read and write together here for brevity, but - based on 1M reads and 1M writes of a class with an auto-implemented string property:&lt;/p&gt;  &lt;pre style="font-weight: normal; "&gt;Static C#: 14ms&lt;br /&gt;Dynamic C#: 268ms&lt;br /&gt;PropertyInfo: 8879ms&lt;br /&gt;PropertyDescriptor: 12847ms&lt;br /&gt;TypeAccessor.Create: 73ms&lt;br /&gt;ObjectAccessor.Create: 92ms&lt;/pre&gt;&lt;p style="font-weight: normal; "&gt;As you can see, it somewhat stomps on both reflection (&lt;code&gt;PropertyInfo&lt;/code&gt;) and &lt;code&gt;System.ComponentModel&lt;/code&gt; (&lt;code&gt;PropertyDescriptor&lt;/code&gt;), and isn't very far from static-typed C#. Furthermore, both APIs work (as mentioned) with DLR types, which is cute - becaues frankly they are a pain to talk to manually. It also supports fields (vs. properties) and structs (vs. classes, although only for read operations).&lt;/p&gt;&lt;p style="font-weight: normal; "&gt;That's all; I had some fun writing it; I hope some folks get some use out of it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-7502015263835482265?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/urZDzR7hVkc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/7502015263835482265/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=7502015263835482265" title="26 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/7502015263835482265?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/7502015263835482265?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/urZDzR7hVkc/playing-with-your-member.html" title="Playing with your member" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>26</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2012/01/playing-with-your-member.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UGRXc9fCp7ImA9WhRUFEU.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-8140957947264738454</id><published>2011-11-26T03:18:00.001-08:00</published><updated>2012-01-25T01:53:44.964-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-25T01:53:44.964-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="autism" /><title>The autistic elephant in the server-room</title><content type="html">&lt;div&gt;A bit of a serious blog-entry this time. Normally I blog about language lemmas, IL intricacies, serialization subtleties, and materialisation mechanisms; but occasionally bigger topics present.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This blog entry is probably more for my purposes than yours. But you might like it anyway. If not, just come back next time.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2&gt;Woah, lots of words; why should I read this?&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Because knowledge never hurts. You might start to understand a colleague better; maybe it might help you recognise autistic traits in a family-member; or maybe you'll just think for a second before "tutting" when you see a child apparently misbehaving in the supermarket - perhaps you don't know what is happening quite as much as you think.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2&gt;Why am I putting this on my geek blog?&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Because, while the reasons &lt;a href="http://www.nature.com/news/2011/111102/full/479025a.html"&gt;still aren't exactly clear&lt;/a&gt; [edit: &lt;a href="http://www.wired.com/wired/archive/9.12/aspergers_pr.html"&gt;alternative&lt;/a&gt;], it tends to present more commonly in the children (mainly sons) of people in geeky professions. Indeed, our profession has a pretty high rate of successful autistic or &lt;a href="http://en.wikipedia.org/wiki/Asperger_syndrome"&gt;Asperger's&lt;/a&gt; members; some very notable, some doing the day job like everyone else.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;More specifically, I care because my eldest son is autistic. Now, autism (or more correctly, &lt;a href="http://en.wikipedia.org/wiki/Autism_spectrum"&gt;ASD&lt;/a&gt;) is a pretty large spectrum. In the UK, there is a trend not to bother trying to diagnose more specific groupings (like Asperger's) because it doesn't actually help with treatment: everyone with ASD needs to be assessed as an individual to understand their needs.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Evan is at the (perhaps unfairly named) "high functioning" end of the spectrum, which means he is of pretty normal intelligence and largely independent, but experiences the world in a slightly different way.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you want to very quickly get a feel for stereotypical ASD at the "high" end, then &lt;a href="http://en.wikipedia.org/wiki/Sheldon_Cooper"&gt;Sheldon Cooper&lt;/a&gt;  is perhaps the easiest place to look, with two caveats:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;- there is no automatic "brilliance"; normal intelligence (albeit it, focused) is more likely&lt;/div&gt;&lt;div&gt;- everybody truly is individual; it helps to remember that generally speaking, generalisations don't help&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also, AFAIK The Big Bang Theory has never explicitly labelled Sheldon with ASD or Asperger's&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;(boo, someone deleted my Sheldon image... &lt;a href="http://images.google.com/search?q=sheldon+cooper+images"&gt;take your pick from here&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;Typical observations would include (not exhaustive):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;- attention / interest can be intensely focused on a narrow topic, to the exclusion of others&lt;/div&gt;&lt;div&gt;- sensory perception (sound, touch, taste, smell, sight, etc) can be extreme (both hyper- and hypo-); for example, simply the washing/size-label on a t-shirt can cause agitation&lt;/div&gt;&lt;div&gt;- cognitive processing can get focused on a particular detail rather than processing the wider context; in programming terms think &lt;a href="http://xkcd.com/761/"&gt;"depth first" rather than "bredth first"&lt;/a&gt;&lt;/div&gt;&lt;div&gt;- language and interpretation can be very literal (for example, "laughing your head off" could be concerning) and repetitive&lt;/div&gt;&lt;div&gt;- routine and predictability are important (in particular, this reduced the stress of processing unfamiliar scenarios), to the point where an individual can seem inflexible and stubborn&lt;/div&gt;&lt;div&gt;- social interaction tends to be limited (people aren't predictable, and often aren't very interesting - even less so if they aren't talking about your preferred topic) and a little awkward (not least, brutal honesty doesn't always go down well - "that lady smells bad" etc)&lt;/div&gt;&lt;div&gt;- there can be a definite need for "quiet time", or just time to unwind in whatever way works. That might be "&lt;a href="http://autism.about.com/od/autismterms/f/stimming.htm"&gt;stimming&lt;/a&gt;", or it might be sitting under a table for half an hour&lt;/div&gt;&lt;div&gt;- recollection (in particular visual memory) can be more acute&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Of course, at the other end of ASD are far more debilitating issues, which may mean dedicated life-long care, maybe institutionalisation. It is not always gentle. I can't speak of this from experience, so I won't try.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2&gt;So... What is the point of this blog entry?&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It is a serious issue that affects our industry, perhaps more than most. Also, our industry &lt;b&gt;is well suited&lt;/b&gt; to ASD. Computers are predictable; IT has a use for massively-focused detail-oriented people (experts perhaps in a very narrow and specialised field), and people who can quickly spot some really minor and subtle differences.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Perhaps more importantly though: it shouldn't be something we don't talk about. ASD tends to be an invisible and private thing (you can see a wheel-chair or hearing-aid; you can't necessarily see that the person you are talking to is actually massively stressed to breaking point because a road was closed and they took a different route to work, and then the 2nd lift on the right - THE LIFT THEY USE - was out of order).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ultimately, no matter where on the spectrum someone is, we should not feel anything like embarrassment. I'm not embarrassed by my son - he's awesome! It took us as a family a little time to properly understand him and his needs, but I think we have something that works well now. And his current school is really great (mainstream, but really understand ASD; his last two schools..... not so much).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2&gt;If you have a child with ASD&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Moving from denial through to acceptance can take time. There's only so many birthday parties you can take them to where opening and closing a door for an hour is more interesting that the hired entertainer - eventually you need to accept that they are simply different. Not better or worse; just different.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Yes, I know, it can be hard sometimes.  You may feel like a chess grand-master constantly thinking 12 steps ahead to avoid some meltdown later in the day. Remembering to give advance notice of change, and implementing damage limitation when something truly unexpected happens. Talking openly about it can be hard (yet is also very liberating). There are often local groups of other parents with similar experiences that you may find helpful (assuming you can arrange cover - regular babysitters may not work out so well).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Laughing helps. Try reading &lt;a href="http://search.twitter.com/search?q=#youmightbeanautismparentif"&gt;#youmightbeanautismparentif&lt;/a&gt;. Or watching &lt;a href="http://www.amazon.com/Mary-Max-Toni-Collette/dp/B00366E1E6"&gt;Mary and Max&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also, don't buy into any of the snake-oil.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2&gt;If you have ASD&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then you know ASD better than me. I've seen some folks with ASD get annoyed before because it is always "parents of..." doing the talking. Well, the world is your podium: I'd love to hear your thoughts. The "parents of" also have an awful lot to bring to the table, though.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2&gt;And for Evan&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;He's doing great. He likes maths and his handwriting is almost as bad as mine. He can probably name a handful of the children in his class, but I'm sure he could tell me how many lights there are in each room in the school (and how many have broken/missing bulbs). We have good days, and we've had some really horrible days - but as we get better, together, at knowing what each of us needs, we get more of the former and less of the latter.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2&gt;Final words&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.youtube.com/watch?v=RjluRCKL8R4"&gt;"I'm not crazy; my mother had me tested"&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.youtube.com/watch?v=mr6XHJ7qcSE"&gt;"I'm not insane; my mother had me tested"&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Dr. Sheldon Cooper&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-8140957947264738454?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/Rl5rycCaFp4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/8140957947264738454/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=8140957947264738454" title="18 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/8140957947264738454?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/8140957947264738454?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/Rl5rycCaFp4/autistic-elephant-in-server-room.html" title="The autistic elephant in the server-room" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>18</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/11/autistic-elephant-in-server-room.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIERXsyfCp7ImA9WhdaFEU.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-4613554179174482804</id><published>2011-10-24T05:12:00.000-07:00</published><updated>2011-10-24T13:35:04.594-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-24T13:35:04.594-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="stackoverflow" /><category scheme="http://www.blogger.com/atom/ns#" term="stackexchange" /><title>Assault by GC</title><content type="html">&lt;h3&gt;TL;DR;&lt;/h3&gt;  &lt;p&gt;We had performance spikes, which we eased with some insane use of &lt;code&gt;struct&lt;/code&gt;s.&lt;/p&gt;  &lt;h3&gt;History&lt;/h3&gt;  &lt;p&gt;For a while now, we had been seeing a problem in the Stack Exchange engine where we would see regular and predictable stalls in performance. So much so that our sysadmins blogged about it &lt;a href="http://blog.serverfault.com/post/a-non-foolish-consistency/"&gt;back here&lt;/a&gt;. Annoyingly, we could only see this problem &lt;em&gt;from the outside&lt;/em&gt; (i.e. haproxy logging, etc) – and to cut a very long story short, these stalls were due to garbage collection (GC).&lt;/p&gt;  &lt;p&gt;We had a problem, you see, with some particularly large and long-lived sets of data (that we use for some crazy-complex performance-related code), that would hobble the server periodically.&lt;/p&gt;  &lt;h3&gt;Short aside on Server GC&lt;/h3&gt;  &lt;p&gt;The regular .NET framework has a generational GC – meaning: new objects are allocated “generation 0” (GEN-0). When it chooses, the system scans GEN-0 and finds (by walking references from the so-called “roots”) which (if any) of the objects are still in use to your application. Most objects have very short lives, and it can very quickly and efficiently reclaim the space from GEN-0; any objects that survived move to GEN-1. GEN-1 works the same (more-or-less), but is swept less often – moving any survivors into GEN-2. GEN-2 is the final lurking place for all your long-lived data – it is swept least often, and is the most expensive to check (especially if it gets big).&lt;/p&gt;  &lt;p&gt;Until .NET 4.5 rolls into town &lt;a href="http://blogs.microsoft.co.il/blogs/sasha/archive/2011/09/17/improvements-in-the-clr-core-in-net-framework-4-5.aspx"&gt;with a background server GC&lt;/a&gt;, checking GEN-2 is a “stop the world” event – it (usually briefly) pauses your code, and does what it needs to. Now imagine you have a huge set of objects which &lt;em&gt;will never&lt;/em&gt; be available to collect (because you will always be using them) all sat in GEN-2. What does that look like? Well, using &lt;a href="http://data.stackexchange.com/about"&gt;StackExchange Data Explorer&lt;/a&gt; to analyse our &lt;a href="http://haproxy.1wt.eu/"&gt;haproxy&lt;/a&gt; logs, it looks a bit like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-Rimz3g9QqbA/TqVW1mViy7I/AAAAAAAAAZo/w4f29VaeBnA/s1600-h/image%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-_tvTO-my8vs/TqVW2Ul3biI/AAAAAAAAAZw/XQCjF0nmukw/image_thumb%25255B1%25255D.png?imgmax=800" width="450" height="236" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I’ve omitted the numbers, as they don’t matter; but interpretation: normally the server is ticking along with nice fast response times, then WHAM! A big spike (which we have correlated with GC) that just hammers the response-times.&lt;/p&gt;  &lt;p&gt;So what to do?&lt;/p&gt;  &lt;p&gt;We &lt;a href="http://www.codinghorror.com/blog/2011/06/performance-is-a-feature.html"&gt;take performance very seriously&lt;/a&gt; at Stack Exchange, so as you imagine this got a bit of attention. The obvious answer of “don’t keep that data”, while a valid suggestion, would have hurt a lot of the overall performance, so we needed to find a way to remove or reduce this while keeping the data.&lt;/p&gt;  &lt;p&gt;Our initial efforts focused on removing things like unnecessary copy/extend operations on the data, which &lt;em&gt;helped some&lt;/em&gt;, but didn’t really make a step-change. Eventually, we concluded…&lt;/p&gt;  &lt;h3&gt;Break all the rules&lt;/h3&gt;  &lt;p&gt;Important: the following is merely a discussion of what has helped us. This is not a magic bullet, and should only be applied to some very limited scenarios after you have profiled and you know what you are doing and why. And it helps if you are just a little bit crazy.&lt;/p&gt;  &lt;p&gt;First, a brief overview – imagine you are holding &lt;code&gt;Customer&lt;/code&gt; objects in memory for an extended period; you have a lot of them in a &lt;code&gt;List&amp;lt;Customer&amp;gt;&lt;/code&gt;, and occasionally add more (with suitable threading protection, etc). Further, you have some pre-calculated subsets of the data (perhaps by region) – so a number of smaller &lt;code&gt;List&amp;lt;Customer&amp;gt;&lt;/code&gt;. That is entirely inaccurate, but sets the scene ;p&lt;/p&gt;  &lt;p&gt;After exhausting alternatives, what we did was:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;change &lt;code&gt;Customer&lt;/code&gt; from a &lt;code&gt;class&lt;/code&gt; to a &lt;code&gt;struct&lt;/code&gt; (only within this crazy code) &lt;/li&gt;    &lt;li&gt;change the main store from a &lt;code&gt;List&amp;lt;Customer&amp;gt;&lt;/code&gt; to a &lt;code&gt;Customer[]&lt;/code&gt; &lt;/li&gt;    &lt;li&gt;change the subsets from &lt;code&gt;List&amp;lt;Customer&amp;gt;&lt;/code&gt; to &lt;code&gt;List&amp;lt;int&amp;gt;&lt;/code&gt;, specifically the offset into the main &lt;code&gt;Customer[]&lt;/code&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;eek; so what does that do for us?&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;the main data is now a single object (the array) on the "large object heap", rather than lots of small objects &lt;/li&gt;    &lt;li&gt;by using direct access into an array (rather than a list indexer) you can access the data in-situ, so we are not constantly copying &lt;code&gt;Customer&lt;/code&gt; values on the stack &lt;/li&gt;    &lt;li&gt;the &lt;code&gt;int&lt;/code&gt; offsets for subsets are essential to make sure we don't have multiple separate values of each record, but on x64 using &lt;code&gt;int&lt;/code&gt; offsets rather than references also means our subsets suddenly take half the memory &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Note that for some of the more complex code (applying predicates etc), we also had to switch to by-ref passing, i.e.&lt;/p&gt;  &lt;pre&gt;void SomethingComplex(ref Customer customer) {...}&lt;br /&gt;...&lt;br /&gt;int custIndex = ...&lt;br /&gt;SomethingComplex(ref customers[custIndex]);&lt;/pre&gt;&lt;p&gt;This again is accessing the &lt;code&gt;Customer&lt;/code&gt; value in-situ inside the array, rather than copying it.&lt;/p&gt;&lt;p&gt;To finish off the bad-practice sheet, we also had some crazy changes to replace some reference data inside the record to &lt;a href="http://msdn.microsoft.com/en-us/library/zycewsya.aspx"&gt;fixed sized buffers&lt;/a&gt; &lt;em&gt;inside&lt;/em&gt; the value (avoiding an array on the heap per item), and some corresponding &lt;code&gt;unsafe&lt;/code&gt; code to query it (including the rarely-used &lt;code&gt;stackalloc&lt;/code&gt;), but that code is probably a bit complex to cover properly - essentially: we removed &lt;em&gt;all&lt;/em&gt; the objects/references from this data. And after removing the objects, &lt;strong&gt;there is nothing for GC to look at&lt;/strong&gt;.&lt;/p&gt;&lt;h3&gt;Impact&lt;/h3&gt;&lt;p&gt;It helped! Here’s the “after”, at the same scales:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/-8z10sHr01uE/TqVW3PtVh2I/AAAAAAAAAZ4/bsRWfH0-Ecg/s1600-h/image%25255B10%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-8WFRumCEQfA/TqVW4INIq0I/AAAAAAAAAaA/R4FJs1whQag/image_thumb%25255B4%25255D.png?imgmax=800" width="431" height="226" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;As you can see, there are still a few vertical spikes (which still tie into GC), but they are much less dense, and less tall. Basically, the server is no longer tied up in knots. The code is a bit less OOP than we might usually do, but it is a: constrained to this very specific scenario (this is absolutely &lt;strong&gt;not&lt;/strong&gt; a carte-blanche “make everything a struct”), and b: for understood reasons.&lt;/p&gt;&lt;p&gt;Plus, it was pretty interesting (oh dear; I really, really need to get out more). Enjoy.&lt;/p&gt;&lt;h3&gt;Disclaimers&lt;/h3&gt;&lt;ul&gt; &lt;li&gt;You need to be really careful messing with this – especially with updates etc, since your records are certainly over-size for atomic read/write, and you don’t want callers seeing torn data.&lt;/li&gt;&lt;li&gt;This is not about “struct is faster” – please don’t let that be what you take away; this is a very specific scenario.&lt;/li&gt;  &lt;li&gt;You need to be really careful to avoid copying fat values on the stack.&lt;/li&gt;  &lt;li&gt;This code really is well outside of the normal bell-curve. Indeed, it is pretty resonant of XNA-style C# (for games, where GC hurts the frame-rate).&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Credit&lt;/h3&gt;&lt;p&gt;A lot of input, data-analysis, scheming, etc here is also due to Sam Saffron and Kyle Brandt; any stupid/wrong bits are mine alone.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-4613554179174482804?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/jTVNY39FPf8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/4613554179174482804/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=4613554179174482804" title="33 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/4613554179174482804?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/4613554179174482804?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/jTVNY39FPf8/assault-by-gc.html" title="Assault by GC" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/-_tvTO-my8vs/TqVW2Ul3biI/AAAAAAAAAZw/XQCjF0nmukw/s72-c/image_thumb%25255B1%25255D.png?imgmax=800" height="72" width="72" /><thr:total>33</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/10/assault-by-gc.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUER3g8eSp7ImA9WhdbEE8.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-2508712789559932817</id><published>2011-10-07T15:22:00.000-07:00</published><updated>2011-10-07T15:23:26.671-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-07T15:23:26.671-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="serialization" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><title>The trouble with tuples</title><content type="html">&lt;p&gt;A little while ago, I &lt;a href="http://marcgravell.blogspot.com/2011/08/automatic-serialization-whats-in-tuple.html"&gt;mentioned how new tuple handling&lt;/a&gt; in protobuf-net meant that likely-looking tuples could now be handled automatically, and &lt;em&gt;even better&lt;/em&gt; this meant I could remove my hacky &lt;code&gt;KeyValuePair&amp;lt;,&amp;gt;&lt;/code&gt; handling. All was well in the world – after all, &lt;em&gt;what could go wrong?&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Answer: Mono.&lt;/p&gt;  &lt;p&gt;Actually, I’m not criticizing the Mono implementation &lt;em&gt;really&lt;/em&gt;, but simply: Mono has a subtly different implementation of &lt;code&gt;KeyValuePair&amp;lt;,&amp;gt;&lt;/code&gt; to Microsoft – nothing huge; simply &lt;em&gt;there exist&lt;/em&gt; some &lt;code&gt;set&lt;/code&gt; accessors (private ones, &lt;a href="http://www.java2s.com/Open-Source/CSharp/2.6.4-mono-.net-core/System.Collections/System/Collections/Generic/KeyValuePair.cs.htm"&gt;visible here&lt;/a&gt;). And the library was pretty fussy – if there was a &lt;code&gt;set&lt;/code&gt; it wouldn’t be treated as a sure-thing tuple.&lt;/p&gt;  &lt;p&gt;This is now fixed in &lt;a href="http://code.google.com/p/protobuf-net/downloads/list"&gt;r447&lt;/a&gt;, but: if you are using Mono and your dictionaries stopped serializing – then honestly and humbly: sorry about that.&lt;/p&gt;  &lt;p&gt;And if you are a library author – watch out: sometimes the simplest most subtle differences between implementations can kill you.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-2508712789559932817?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/_mNGlNuDjzY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/2508712789559932817/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=2508712789559932817" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/2508712789559932817?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/2508712789559932817?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/_mNGlNuDjzY/trouble-with-tuples.html" title="The trouble with tuples" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>3</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/10/trouble-with-tuples.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0YERn84fip7ImA9WhdQFE0.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-8239269998123814512</id><published>2011-08-15T04:48:00.001-07:00</published><updated>2011-08-15T04:51:47.136-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-15T04:51:47.136-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="serialization" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><title>Automatic serialization; what’s in a tuple?</title><content type="html">&lt;p&gt;I recently had a lot of reason (read: a serialization snafu) to think about tuples in the context of serialization. Historically, protobuf-net has focused on mutable types, which are convenient to manipulate while processing a protobuf stream (setting fields/properties on a per-field basis). However, if you think about it, tuples have an implicit obvious positional “contract”, so it makes a lot of sense to serialize them automatically. If I write:&lt;/p&gt;  &lt;pre&gt;var tuple = Tuple.Create(123, &amp;quot;abc&amp;quot;);&lt;/pre&gt;&lt;p&gt;then it doesn’t take a lot of initiative to think of &lt;code&gt;tuple&lt;/code&gt; as an implicit contract with two fields:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;field 1 is an integer with value 123 &lt;/li&gt;&lt;li&gt;field 2 is a string with value “abc” &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Since it is deeply immutable, at the moment we would need to either abuse reflection to mutate private fields, or write a mutable &lt;em&gt;surrogate&lt;/em&gt; type for serialization, with conversion operators, and tell protobuf-net about the surrogate. Wouldn’t it be nice if protobuf-net could make this leap for us? &lt;/p&gt;&lt;p&gt;Well, after a Sunday-night hack it now (in the source code) &lt;em&gt;does&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;The rules are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;it must not already be marked as an explicit contract &lt;/li&gt;&lt;li&gt;only public fields / properties are considered&lt;/li&gt;&lt;li&gt;any public fields (spit) must be &lt;code&gt;readonly&lt;/code&gt; &lt;/li&gt;&lt;li&gt;any public properties must have a &lt;code&gt;get&lt;/code&gt; but not a &lt;code&gt;set&lt;/code&gt; (on the public API, at least) &lt;/li&gt;&lt;li&gt;there must be exactly one interesting constructor, with parameters that are a case-insensitive match for each field/property in some order (i.e. there must be an obvious 1:1 mapping between members and constructor parameter names) &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If &lt;em&gt;all&lt;/em&gt; of the above conditions are met then it is now capable of behaving as you might hope and expect, deducing the contract and using the chosen constructor to rehydrate the objects. Which is nice! As a few side-benefits:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;this completely removes the need for the existing &lt;code&gt;KeyValuePairSurrogate&amp;lt;,&amp;gt;&lt;/code&gt;, which conveniently meets all of the above requirements &lt;/li&gt;&lt;li&gt;it also works for C# anonymous types if we want, since they too have an implicit positional contract (I am not convinced this is significant, but it may have uses)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This should make it into the next deploy, once I’m sure there are no obvious failures in my assumptions.&lt;/p&gt;&lt;h3&gt;Just one more thing, sir…&lt;/h3&gt;&lt;p&gt;While I’m on the subject of serialization (which, to be fair, I often am) – I have now also completed some changes to use &lt;a href="http://msdn.microsoft.com/en-us/library/11tbk3h9.aspx"&gt;&lt;code&gt;RuntimeHelpers.GetHashCode()&lt;/code&gt;&lt;/a&gt;for reference-tracking (serialization). This lets met construct a reference-preserving hash-based lookup to minimise the cost of checking whether an object has already been seen (and if so, fetch the existing token). Wins all round.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-8239269998123814512?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/XvMKWM2klUM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/8239269998123814512/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=8239269998123814512" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/8239269998123814512?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/8239269998123814512?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/XvMKWM2klUM/automatic-serialization-whats-in-tuple.html" title="Automatic serialization; what’s in a tuple?" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>3</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/08/automatic-serialization-whats-in-tuple.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ACQHs-cSp7ImA9WhdQEUU.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-5743070234722762775</id><published>2011-08-12T13:21:00.000-07:00</published><updated>2011-08-12T13:42:41.559-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-12T13:42:41.559-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dynamic" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><category scheme="http://www.blogger.com/atom/ns#" term="4.0" /><title>Shifting expectations: non-integer shift operators in C#</title><content type="html">&lt;p&gt;In C#, it is quite nice that the shift operators (&lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; and &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;) &lt;a href="http://msdn.microsoft.com/en-us/library/xt18et0d(v=VS.100).aspx"&gt;have had their second argument constrained&lt;/a&gt; to &lt;code&gt;int&lt;/code&gt; arguments, avoiding the oft-confusing piped C++ usage:&lt;/p&gt;  &lt;pre&gt;cout &amp;lt;&amp;lt; &amp;quot;abc&amp;quot; &amp;lt;&amp;lt; &amp;quot;def&amp;quot;;&lt;/pre&gt;&lt;p&gt;But wait a minute! The above line is actually C#, in an all-C# project. OK, I cheated a &lt;em&gt;little&lt;/em&gt; (I always do…) but genuinely! This little nugget comes from a &lt;a href="http://stackoverflow.com/questions/7043639/operator-op-cannot-be-applied-to-operands-of-type-dynamic-and-lambda-expres/7043775#7043775"&gt;stackoverflow post&lt;/a&gt; that really piqued my curiosity. All credit here goes to &lt;a href="http://stackoverflow.com/users/492405/vcsjones"&gt;vcsjones&lt;/a&gt;, but indeed the line in the documentation about restricting to &lt;code&gt;int&lt;/code&gt; (and the return type, etc) is about &lt;em&gt;declaring&lt;/em&gt; the operator – not &lt;em&gt;consuming&lt;/em&gt; it – so it is seemingly valid for the C# &lt;code&gt;dynamic&lt;/code&gt; implementation to use it quite happily.&lt;/p&gt;&lt;p&gt;In fact, the main &lt;em&gt;cheat&lt;/em&gt; I used here was simply hiding the assignment of the result, since that is still required. Here’s the full evil:&lt;/p&gt;&lt;pre&gt;  using System;
&lt;br /&gt;  using System.Dynamic;
&lt;br /&gt;  using System.Linq.Expressions;
&lt;br /&gt;
&lt;br /&gt;  class Evil : DynamicObject {
&lt;br /&gt;      static void Main() {
&lt;br /&gt;          dynamic cout = new Evil();
&lt;br /&gt;          var hacketyHackHack =
&lt;br /&gt;          cout &amp;lt;&amp;lt; &amp;quot;abc&amp;quot; &amp;lt;&amp;lt; &amp;quot;def&amp;quot;;
&lt;br /&gt;      }
&lt;br /&gt;      public override bool TryBinaryOperation(
&lt;br /&gt;              BinaryOperationBinder binder,
&lt;br /&gt;              object arg, out object result) {
&lt;br /&gt;          switch(binder.Operation) {
&lt;br /&gt;              case ExpressionType.LeftShift:
&lt;br /&gt;              case ExpressionType.LeftShiftAssign:
&lt;br /&gt;                  // or whatever you want to do
&lt;br /&gt;                  Console.WriteLine(arg);
&lt;br /&gt;                  result = this;
&lt;br /&gt;                  return true;
&lt;br /&gt;          }
&lt;br /&gt;          return base.TryBinaryOperation(
&lt;br /&gt;               binder, arg, out result);
&lt;br /&gt;      }
&lt;br /&gt;   }&lt;/pre&gt;&lt;p&gt;I've seen &lt;i&gt;more evil&lt;/i&gt; things (subverting &lt;code&gt;new()&lt;/code&gt; via &lt;code&gt;ContextBoundObject&lt;/code&gt; is still my favorite evil), but quite dastardly, IMO!&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Additional: grrr! I don't know why blogger hates me so much; &lt;a href="http://pastie.org/2362978"&gt;here it is on pastie.org&lt;a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-5743070234722762775?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/Ccx2UD87C_8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/5743070234722762775/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=5743070234722762775" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/5743070234722762775?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/5743070234722762775?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/Ccx2UD87C_8/shifting-expectations-non-integer-shift.html" title="Shifting expectations: non-integer shift operators in C#" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>1</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/08/shifting-expectations-non-integer-shift.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MDR3k4eip7ImA9WhZaF0o.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-6477204071933826096</id><published>2011-07-04T03:54:00.001-07:00</published><updated>2011-07-04T04:37:56.732-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-04T04:37:56.732-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="redis" /><title>BookSleeve, transactions, hashes, and flukes</title><content type="html">&lt;p&gt;Sometimes, you just get lucky.&lt;/p&gt;  &lt;p&gt;tl;dr; version : &lt;a href="http://code.google.com/p/booksleeve/"&gt;BookSleeve&lt;/a&gt; now has transactions and Hashes; new version on &lt;a href="http://nuget.org/List/Packages/BookSleeve"&gt;nuget&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Transactions&lt;/h3&gt;  &lt;p&gt;For some time now I’ve been meaning to add multi/exec support to &lt;a href="http://code.google.com/p/booksleeve/"&gt;BookSleeve&lt;/a&gt; (which is how &lt;a href="http://redis.io/commands#transactions"&gt;redis manages transactions&lt;/a&gt;). The main reason it wasn’t there already is simply: we don’t use them within &lt;a href="http://stackexchange.com/"&gt;StackExchange&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;To recap, because BookSleeve is designed to be entirely asynchronous, the API almost-always returns some kind of Task or (more often) Task-of-T; from there you can hook a “continue-with” handler, you can elect to wait for a result (or error), or you can just drop it on the floor (fire-and-forget).&lt;/p&gt;  &lt;p&gt;Over the weekend, I finally got around to looking at multi/exec. The interesting thing here is that once you’ve issued a MULTI, redis changes the output – return “QUEUED” for pretty much every command. If I was using a synchronous API, I’d be pretty much scuppered at this point; I’d need to duplicate the entire (&lt;a href="http://redis.io/commands"&gt;quite large&lt;/a&gt;) API to provide a way of using it. I’d love to say it was by-design (I’d be lying), but the existing asynchronous API made this a breeze (relatively speaking) – all I had to do was wrap the messages in a decorator that &lt;em&gt;expects &lt;/em&gt;to see “QUEUED”, and then (after the EXEC) run the already-existing logic against the wrapped message. Or more visually:&lt;/p&gt;  &lt;pre&gt;conn.Remove(db, &amp;quot;foo&amp;quot;); // just to reset&lt;br /&gt;using(var tran = conn.CreateTransaction())&lt;br /&gt;{   // deliberately ignoring INCRBY here&lt;br /&gt;    tran.Increment(db, &amp;quot;foo&amp;quot;);&lt;br /&gt;    tran.Increment(db, &amp;quot;foo&amp;quot;);&lt;br /&gt;    var val = tran.GetString(db, &amp;quot;foo&amp;quot;);&lt;br /&gt;&lt;br /&gt;    tran.Execute(); // this *still* returns a Task&lt;br /&gt;&lt;br /&gt;    Assert.AreEqual(&amp;quot;2&amp;quot;, conn.Wait(val));&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Here all the operations happen as an atomic (but pipelined) unit, allowing for more complex integrity conditions. Note that Execute() is still asynchronous (returning a Task), so you can still carry on doing useful work while the network and redis server does some thinking (although redis &lt;em&gt;is&lt;/em&gt; shockingly quick).&lt;/p&gt;&lt;h3&gt;So what is CreateTransaction?&lt;/h3&gt;&lt;p&gt;Because a BookSleeve connection is a thread-safe multiplexer, it is not a good idea to start sending messages down the wire until we have everything we need. If we did that, we’d have to block all the other clients, which is not a good thing. Instead, CreateTransaction() creates a staging area to build commands (using&lt;strong&gt;&lt;em&gt; exactly the same API&lt;/em&gt;&lt;/strong&gt;) and capture future results. Then, when Execute() is called the buffered commands are assembled into a MULTI/EXEC unit and sent down in a contiguous block (the multiplexer will send all of these together, obviously).&lt;/p&gt;&lt;p&gt;As an added bonus, we can also use the Task cancellation metaphor to cleanly handle discarding the transaction without execution.&lt;/p&gt;&lt;p&gt;The only &lt;em&gt;disadvantage&lt;/em&gt; of the multiplexer approach here is that it makes it pretty hard to use &lt;a href="http://redis.io/commands/watch"&gt;WATCH&lt;/a&gt;/&lt;a href="http://redis.io/commands/unwatch"&gt;UNWATCH&lt;/a&gt;, since we wouldn’t be sure what we are watching. Such is life; I’ll think some more on this.&lt;/p&gt;&lt;h3&gt;Hashes&lt;/h3&gt;&lt;p&gt;Another tool we don’t use much at StackExchange is &lt;a href="http://redis.io/commands#hash"&gt;hashes&lt;/a&gt;; however, for your convenience this is now fully implemented in BookSleeve. And since we now have transactions, we can solve the awkward varadic/non-varadic issue of &lt;a href="http://redis.io/commands/hdel"&gt;HDEL&lt;/a&gt; between 2.2+ and previous versions; if BookSleeve detects a 2.2+ server it will automatically use the varadic version, otherwise it will automatically use a transaction (or enlist in the existing transaction). Sweet!&lt;/p&gt;&lt;h3&gt;Go play&lt;/h3&gt;&lt;p&gt;A new build is on &lt;a href="http://nuget.org/List/Packages/BookSleeve"&gt;nuget&lt;/a&gt;; I hope you find it useful.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-6477204071933826096?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/Pr5zGHGBf_w" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/6477204071933826096/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=6477204071933826096" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6477204071933826096?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6477204071933826096?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/Pr5zGHGBf_w/booksleeve-transactions-hashes-and.html" title="BookSleeve, transactions, hashes, and flukes" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>1</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/07/booksleeve-transactions-hashes-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUHQnw4fCp7ImA9WhZUFk0.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-295539600141419203</id><published>2011-06-08T15:54:00.001-07:00</published><updated>2011-06-08T23:17:13.234-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-08T23:17:13.234-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="community" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="mvc" /><title>Profiling with knobs on</title><content type="html">&lt;p&gt;A little while ago, &lt;a href="http://marcgravell.blogspot.com/2011/04/practical-profiling.html"&gt;I mentioned&lt;/a&gt; the core part of the profiling tool we use at &lt;a href="http://stackexchange.com/"&gt;stackexchange&lt;/a&gt; – our &lt;a href="http://code.google.com/p/mvc-mini-profiler/"&gt;mini-profiler&lt;/a&gt;. Well, I’m delighted to say that with the input from Jarrod and Sam this tool has been evolving at an alarming rate, and has now gained:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;full integration with our bespoke SQL profiler, which is now &lt;em&gt;also included&lt;/em&gt;       &lt;ul&gt;       &lt;li&gt;basically, this is a custom ADO.NET &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.common.dbconnection.aspx"&gt;DbConnection&lt;/a&gt; that you wrap around your existing connection, and it adds logging &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;an awesome UI (rather than html comments), including a much clearer timeline &lt;/li&gt;    &lt;li&gt;full support for AJAX activity &lt;/li&gt;    &lt;li&gt;some &lt;em&gt;very&lt;/em&gt; basic highlighting of duplicated queries, etc&lt;/li&gt;&lt;li&gt;webform support&lt;/li&gt;    &lt;li&gt;and a ton of other features and enhancements &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;To illustrate with Jarrod’s image from the project page:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-2S7Qa_TWGvs/Te_9n1BF-MI/AAAAAAAAAXU/txSQoWpX6dI/s1600-h/miniprofiler%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="miniprofiler" border="0" alt="miniprofiler" src="http://lh5.ggpht.com/-oDcRSAwokTY/Te_9onX33ZI/AAAAAAAAAXY/WvYcs33o5Rw/miniprofiler_thumb%25255B1%25255D.png?imgmax=800" width="416" height="255" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The custom connection has been exercised extensively with &lt;a href="http://code.google.com/p/dapper-dot-net/"&gt;dapper-dot-net&lt;/a&gt;, LINQ-to-SQL and direct ADO.NET, but should also work with Entity Framework (via &lt;code&gt;ObjectContextUtils&lt;/code&gt;, provided) and hopefully any other DB frameworks built on top of ADO.NET.&lt;/p&gt;  &lt;p&gt;We use it constantly. It is perhaps our primary tool in both understanding problems and just keeping a constant eye on the system &lt;em&gt;while we use it&lt;/em&gt; – since this is running (for our developers) constantly, 24×7.&lt;/p&gt;  &lt;p&gt;All too often such fine-grain profiling is just “there’s a problem, ask a DBA to attach a profiler to the production server for 2 minutes while I validate something”.&lt;/p&gt;  &lt;p&gt;Enjoy.&lt;/p&gt;&lt;p&gt;&lt;a href="http://code.google.com/p/mvc-mini-profiler/"&gt;http://code.google.com/p/mvc-mini-profiler/&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-295539600141419203?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/MLKO2wYTsfU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/295539600141419203/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=295539600141419203" title="9 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/295539600141419203?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/295539600141419203?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/MLKO2wYTsfU/profiling-with-knobs-on.html" title="Profiling with knobs on" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-oDcRSAwokTY/Te_9onX33ZI/AAAAAAAAAXY/WvYcs33o5Rw/s72-c/miniprofiler_thumb%25255B1%25255D.png?imgmax=800" height="72" width="72" /><thr:total>9</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/06/profiling-with-knobs-on.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYMQHo-cCp7ImA9WhZVE0s.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-6529908490015602328</id><published>2011-05-25T16:45:00.001-07:00</published><updated>2011-05-25T16:46:21.458-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-25T16:46:21.458-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="serialization" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>So soon, beta 2</title><content type="html">&lt;p&gt;I’m delighted by the level of response to my protobuf-net v2 beta; I have been kept really busy with a range of questions, feature requests and bug fixes (almost exclusively limited to the new features).&lt;/p&gt;  &lt;p&gt;So, before I annoy people with too many “fixed in source” comments, I thought I’d better re-deploy. Beta 2 gives &lt;a href="http://marcgravell.blogspot.com/2011/05/protobuf-net-v2-beta.html"&gt;the same as beta 1&lt;/a&gt;, but with:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;reference-tracked objects      &lt;ul&gt;       &lt;li&gt;root object now included &lt;strong&gt;&lt;font color="#ff0000"&gt;(BREAKING CHANGE)&lt;/font&gt;&lt;/strong&gt; &lt;/li&gt;        &lt;li&gt;fixed false-positive recursion issue &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;full type metadata      &lt;ul&gt;       &lt;li&gt;support custom formatting/parsing &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;interface serialization      &lt;ul&gt;       &lt;li&gt;support serialization from interfaces &lt;/li&gt;        &lt;li&gt;support known-implementations of interfaces &lt;/li&gt;        &lt;li&gt;support default concrete type &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;WCF      &lt;ul&gt;       &lt;li&gt;expose WCF types on public API to allow custom models &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;misc      &lt;ul&gt;       &lt;li&gt;support shadow set-methods &lt;/li&gt;        &lt;li&gt;fix IL glitch&lt;/li&gt;        &lt;li&gt;fix cold-start thread-race condition &lt;/li&gt;        &lt;li&gt;fix missing method-forwarding from legacy non-generic API &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In addition to a very encouraging level of interest, I’m also pleased that things like the interface-based support mentioned above were pretty effortless to push through the v2 type-model. These are things that had been proposed previously, but there was just no way to push them into the codebase without hideous (and cumulative) hackery. With v2, it was pretty much a breeze.&lt;/p&gt;  &lt;p&gt;But for v2 fun &lt;a href="http://code.google.com/p/protobuf-net/downloads/list"&gt;see the project download page&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;And please, keep pestering me ;p&lt;/p&gt;  &lt;p&gt;&lt;font size="1"&gt;Note that the BREAKING CHANGE marked above only applies to data serialized with the new full-graph &lt;code&gt;AsReference&lt;/code&gt; option. No v1 data is impacted, but if you have stored data from earlier v2 alpha/beta code, please drop me a line and I can advise.&lt;/font&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-6529908490015602328?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/r5YYYDSVfmM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/6529908490015602328/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=6529908490015602328" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6529908490015602328?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6529908490015602328?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/r5YYYDSVfmM/so-soon-beta-2.html" title="So soon, beta 2" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>8</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/05/so-soon-beta-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIMR309fCp7ImA9WhZWGE4.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-8386441148740399235</id><published>2011-05-19T13:23:00.001-07:00</published><updated>2011-05-19T13:23:06.364-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-19T13:23:06.364-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="serialization" /><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><title>protobuf-net v2, beta</title><content type="html">&lt;p&gt;It has been a long time in the coming, I know. I make no excuses, but various other things have meant that it didn’t get much input for a while…&lt;/p&gt;  &lt;p&gt;But! I’m happy to say that I’ve just pushed a &lt;a href="http://code.google.com/p/protobuf-net/downloads/list"&gt;beta download&lt;/a&gt; up onto &lt;a href="http://code.google.com/p/protobuf-net/"&gt;the project site&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;So… this v2… what is it?&lt;/h3&gt;  &lt;p&gt;Basically, it is still the core protobuf stream, but &lt;a href="http://www.joelonsoftware.com/articles/fog0000000069.html"&gt;against all the safe advice of my employer&lt;/a&gt; I rewrote the entire core. For many reasons:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;the original design grew organically, and ideas that seemed good turned to make for some problematic code later&lt;/li&gt;    &lt;li&gt;the vast overuse of generics (and in particular, generics at runtime via reflection) was really hurting some platforms&lt;/li&gt;    &lt;li&gt;there were many things the design &lt;em&gt;could not readily support&lt;/em&gt; – structs, runtime models, pre-built serialization dlls, &lt;strong&gt;usage on mobile devices&lt;/strong&gt;, etc&lt;/li&gt;    &lt;li&gt;the code path at runtime was just not as minimal as I would like&lt;/li&gt;    &lt;li&gt;and a myriad of other things&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So… I rewrote it. Fortunately I had a barrage of integration tests, which grew yet further during this exercise. The way I figured, I had 2 choices here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;go with a richer code-generator to use as a build task (not runtime)&lt;/li&gt;    &lt;li&gt;go crazy with meta-programming&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;After some thought, I opted for the latter. In particular, this would (in my reasoning) give me lots of flexibility for keeping things runtime based (where you are able to, at least), and would be a good opportunity to &lt;strong&gt;have some fun&lt;/strong&gt; and learn IL emit to dangerous levels (which, incidentally, turns out to be very valuable – hence mine and Sam’s work on &lt;a href="http://samsaffron.com/archive/2011/03/30/How+I+learned+to+stop+worrying+and+write+my+own+ORM"&gt;dapper-dot-net&lt;/a&gt;).&lt;/p&gt;  &lt;h3&gt;So what is new?&lt;/h3&gt;  &lt;p&gt;I don’t claim this list is exhaustive:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;the ability to define models at runtime (also useful for working with types you don’t control) (&lt;a href="http://stackoverflow.com/questions/6058645/is-it-possible-to-use-protobuf-net-serializer-and-at-the-same-time-the-respective/6059693#6059693"&gt;example&lt;/a&gt;)&lt;/li&gt;    &lt;li&gt;the ability to have separate models for the same types&lt;/li&gt;    &lt;li&gt;pre-generation to dll&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;runtime performance improvements&lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;support for structs&lt;/li&gt;    &lt;li&gt;support for immutable objects via surrogates (&lt;a href="http://stackoverflow.com/questions/6063273/is-it-possible-to-deserialize-a-private-property-using-protobuf-net-in-silverli/6063812#6063812"&gt;example&lt;/a&gt;)&lt;/li&gt;    &lt;li&gt;the ability to run on mobile platforms (&lt;a href="http://www.frictionpointstudios.com/blog/2011/3/31/using-protobuf-net-serialization-in-unity-iphone.html"&gt;unity&lt;/a&gt;, &lt;a href="http://marcgravell.blogspot.com/2010/04/walkthrough-protobuf-net-on-phone-7.html"&gt;wp7&lt;/a&gt; – and perhaps moot for a while: &lt;a href="http://marcgravell.blogspot.com/2010/09/protobuf-net-on-monodroid.html"&gt;MonoDroid&lt;/a&gt;, &lt;a href="http://marcgravell.blogspot.com/2010/02/protobuf-net-v2-on-iphone.html"&gt;MonoTouch&lt;/a&gt; – but presumably &lt;a href="http://tirania.org/blog/archive/2011/May-16.html"&gt;Xamarin&lt;/a&gt;)&lt;/li&gt;    &lt;li&gt;the ability to serialize &lt;a href="http://marcgravell.blogspot.com/2011/03/objects-graphs-and-all-that-jazz.html"&gt;object graphs preserving references&lt;/a&gt; (&lt;a href="http://stackoverflow.com/questions/6063729/does-protocol-buffers-support-serialization-of-object-graphs-with-shared-referenc/6063837#6063837"&gt;example&lt;/a&gt;)&lt;/li&gt;    &lt;li&gt;the ability to work with types not known in advance (&lt;a href="http://marcgravell.blogspot.com/2011/03/objects-graphs-and-all-that-jazz.html"&gt;same&lt;/a&gt;)&lt;/li&gt;    &lt;li&gt;probably about 40 other things that slip my mind&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I’ll try to go into each of these in detail when I can&lt;/p&gt;  &lt;h3&gt;And what isn’t there yet?&lt;/h3&gt;  &lt;p&gt;This is beta; at some point I had to make a milestone cut – but some things aren’t quite complete yet; these are &lt;strong&gt;not&lt;/strong&gt; usually needed (hint: I’m happy to use protobuf-net v2 on my employer’s code-base, so I have confidence in it, and confidence that the core paths have been smoke-tested)&lt;/p&gt;  &lt;p&gt;But things that definitely aren’t there in the beta&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;WCF hooks&lt;/li&gt;    &lt;li&gt;VS tooling (it is just the core runtime dlls)&lt;/li&gt;    &lt;li&gt;round-trip safe / “extension” fields&lt;/li&gt;    &lt;li&gt;extraction of .proto (schema) files from a model&lt;/li&gt;    &lt;li&gt;my build / deploy script needs an overhaul&lt;/li&gt;    &lt;li&gt;tons of documentation / examples&lt;/li&gt;    &lt;li&gt;tooling to make the “mobile” story easier (but; it should &lt;em&gt;work&lt;/em&gt; – it is being used in a few, for example)&lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;But; have at it&lt;/h3&gt;  &lt;p&gt;If you want to play with it, go ahead. I only ask that if something behaves unexpectedly, drop me a line before declaring loudly “it sux, dude!”. It might just need some guidance, or maybe even a code fix (I’m far from perfect).&lt;/p&gt;  &lt;p&gt;Likewise, any feature suggestions, etc; let me know.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-8386441148740399235?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/N5ZOYHjwIck" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/8386441148740399235/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=8386441148740399235" title="45 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/8386441148740399235?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/8386441148740399235?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/N5ZOYHjwIck/protobuf-net-v2-beta.html" title="protobuf-net v2, beta" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>45</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/05/protobuf-net-v2-beta.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcCQ3w9eCp7ImA9WhZQGU0.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-1109110563541530926</id><published>2011-04-27T03:57:00.001-07:00</published><updated>2011-04-27T04:17:42.260-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-27T04:17:42.260-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="async" /><category scheme="http://www.blogger.com/atom/ns#" term="5.0" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><category scheme="http://www.blogger.com/atom/ns#" term="redis" /><title>Completion tasks - the easy way</title><content type="html">&lt;p&gt;One of the good things about doing things in public – people point out when you’ve missed a trick.&lt;/p&gt;  &lt;p&gt;Just the other day, I was moaning about how Task seemed too tightly coupled to schedulers, and &lt;em&gt;wouldn’t it be great&lt;/em&gt; if you could have a Task that just allowed you to indicate success/failure – I even went so far as to write some experimental code to do &lt;em&gt;just that&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;So you can predict what comes next; &lt;strong&gt;it already existed&lt;/strong&gt; – I just didn’t know about it. I give you &lt;a href="http://msdn.microsoft.com/en-us/library/dd449174.aspx"&gt;TaskCompletionSource&amp;lt;T&amp;gt;&lt;/a&gt;, which has SetResult(…), SetException(…) and a Task property. Everything I need (except maybe support for result-free tasks, but I can work around that).&lt;/p&gt;  &lt;p&gt;And wouldn’t you believe it, the TPL folks shine again, easily doubling my lousy performance, and &lt;em&gt;trebling&lt;/em&gt; (or more) the performance compared to “faking it” via RunSynchronously:&lt;/p&gt;  &lt;pre&gt;Future (uncontested): 1976ms // my offering&lt;br /&gt;Task (uncontested): 4149ms // TPL Task via RunSynchronously&lt;br /&gt;Source (uncontested): 765ms // via TaskCompletionSource&lt;T&gt;&lt;br /&gt;Future (contested): 5608ms&lt;br /&gt;Task (contested): 6982ms&lt;br /&gt;Source (contested): 2389ms&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I am hugely indebted to &lt;a href="http://www.blogger.com/profile/01345100698738870730"&gt;Sam Jack&lt;/a&gt;, who corrected me via a comment on the blog entry. Cheers!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-1109110563541530926?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/upBBihaiz_I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/1109110563541530926/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=1109110563541530926" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/1109110563541530926?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/1109110563541530926?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/upBBihaiz_I/completion-tasks-easy-way.html" title="Completion tasks - the easy way" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>2</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/04/completion-tasks-easy-way.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcBQH06fyp7ImA9WhZQGU0.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-2765970361586071075</id><published>2011-04-25T13:45:00.001-07:00</published><updated>2011-04-27T04:00:51.317-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-27T04:00:51.317-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="async" /><category scheme="http://www.blogger.com/atom/ns#" term="5.0" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><category scheme="http://www.blogger.com/atom/ns#" term="tpl" /><title>Musings on async</title><content type="html">&lt;p&gt;OUT OF DATE: SEE &lt;a href="http://marcgravell.blogspot.com/2011/04/completion-tasks-easy-way.html"&gt;UPDATE&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;For &lt;a href="http://code.google.com/p/booksleeve/"&gt;BookSleeve&lt;/a&gt;, I wanted an API that would work with current C#/.NET, but which would also mesh directly into C# 5 with the async/await pattern. The obvious option there was the &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx"&gt;Task&lt;/a&gt; API, which is familiar to anyone who has used the &lt;a href="http://msdn.microsoft.com/en-us/library/dd460717.aspx"&gt;TPL&lt;/a&gt; in .NET 4.0, but which gains extension methods with the &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=4738205D-5682-47BF-B62E-641F6441735B&amp;amp;displaylang=en"&gt;Async CTP&lt;/a&gt; to enable async/await.&lt;/p&gt;  &lt;p&gt;This &lt;em&gt;works&lt;/em&gt;, but in the process I found a few niggles that made me have a few doubts:&lt;/p&gt;  &lt;h3&gt;Completion without local scheduling&lt;/h3&gt;  &lt;p&gt;In my process, I never really want to &lt;em&gt;schedule&lt;/em&gt; a task; the task is performed on a separate server, and what I really want to do is signal that something &lt;strong&gt;is now complete&lt;/strong&gt;. There isn’t really an API for that on Task (since it is geared more for operations you are running locally, typically in parallel). The closest you can do is to ask the &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.default.aspx"&gt;default scheduler&lt;/a&gt; to run your task &lt;a href="http://msdn.microsoft.com/en-us/library/dd449178.aspx"&gt;immediately&lt;/a&gt;, but this feels a bit ungainly, not least because task-schedulers are not &lt;strong&gt;required&lt;/strong&gt; to offer synchronous support.&lt;/p&gt;  &lt;p&gt;In my use-case, I’m not even &lt;em&gt;remotely&lt;/em&gt; interested in scheduling; personally I’d quite like it if Task supported this mode of use in isolation, perhaps via a protected method and a subclass of Task.&lt;/p&gt;  &lt;p&gt;(yes, there is &lt;a href="http://msdn.microsoft.com/en-us/library/dd321435.aspx"&gt;RunSynchronously&lt;/a&gt;, but that just uses the current scheduler, which in library code you can’t assume is capable of actually &lt;em&gt;running&lt;/em&gt; synchronously).&lt;/p&gt;  &lt;h3&gt;Death by exception&lt;/h3&gt;  &lt;p&gt;The task API is also pretty fussy about errors – which isn’t unreasonable. If a task fails &lt;u&gt;and you don’t explicitly observe the exception&lt;/u&gt; (by asking it for the result, etc), then it intentionally re-surfaces that exception in a finalizer. Having a finalizer is note-worthy in itself, and you get &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.unobservedtaskexception.aspx"&gt;one last chance&lt;/a&gt; to convince the API that you’re sane – but if you forget to hook that exception it is a process-killer.&lt;/p&gt;  &lt;h3&gt;So what would it take to do it ourselves?&lt;/h3&gt;  &lt;p&gt;So: what is involved in writing our own sync+async friendly API? It turns out it isn’t that hard; in common with things like LINQ (and foreach if you really want), the async API is pattern-based rather than interface-based; this is convenient for retro-fitting the async tools onto existing APIs without changing existing interfaces.&lt;/p&gt;  &lt;p&gt;What you need (in the Async CTP Refresh for VS2010 SP1) is:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Some GetAwaiter() method (possibly but not necessarily an extension method) that returns something with all of: &lt;/li&gt;    &lt;li&gt;A boolean IsCompleted property (get) &lt;/li&gt;    &lt;li&gt;A void OnCompleted(Action callback) &lt;/li&gt;    &lt;li&gt;A GetResult() method which returns void, or the desired outcome of the awaited operation &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So this isn’t a hugely challenging API to implement if you want to write a custom awaitable object. I have a &lt;a href="http://code.google.com/p/booksleeve/source/browse/Async/CustomAwaiter.cs"&gt;working implementation&lt;/a&gt; that I put together with BookSleeve in mind. Highlights:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Acts as a set-once value with wait (sync) and continuation (async) support &lt;/li&gt;    &lt;li&gt;Thread-safe &lt;/li&gt;    &lt;li&gt;Isolated from the TPL, and scheduling in particular &lt;/li&gt;    &lt;li&gt;Based on Monitor, but allowing efficient re-use of the object used as the sync-lock (my understanding is that once used/contested in a Monitor, the object instance obtains additional cost; may as well minimise that) &lt;/li&gt;    &lt;li&gt;Supporting typed (Future&amp;lt;T&amp;gt;) or untyped (Future) usage – compares to Task&amp;lt;T&amp;gt; and Task respectively&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;My local tests aren’t exhaustive, but (over 500,000 batches of 10 operations each), I get:&lt;/p&gt;  &lt;pre&gt;Future (uncontested): 1993ms&lt;br /&gt;Task (uncontested): 4126ms&lt;br /&gt;Future (contested): 5487ms&lt;br /&gt;Task (contested): 6787ms&lt;/pre&gt;&lt;p&gt;So our custom awaitable object is faster… but I’m just not convinced that it is &lt;strong&gt;&lt;em&gt;enough&lt;/em&gt;&lt;/strong&gt; of an improvement to justify changing away from the Task API. This call density is somewhat artificial, and we’re talking less than a µs per-operation difference.&lt;/p&gt;&lt;h3&gt;Conclusions&lt;/h3&gt;&lt;p&gt;In some ways I’m pleasantly surprised with the results; if Task is keeping up (more or less), even &lt;strong&gt;outside&lt;/strong&gt; of it’s primary design case, then I think we should forget about it; use Task, and move on to the actual meat of the problem we are trying to solve.&lt;/p&gt;&lt;p&gt;However, I’ll leave my experimental Future/Future&amp;lt;T&amp;gt; code &lt;em&gt;&lt;u&gt;as reference only&lt;/u&gt;&lt;/em&gt; off on the side of BookSleeve – in case anybody else feels the need for a non-TPL implementation. I’m not saying mine is ideal, but it works reasonably.&lt;/p&gt;&lt;p&gt;But: I will not be changing away from Task / Task&amp;lt;T&amp;gt; at this time. I’m passionate about performance, but I’m not (quite) crazy; I’ll take the more typical and more highly-tested Task API that has been put together by people who &lt;strong&gt;&lt;em&gt;really, really&lt;/em&gt;&lt;/strong&gt; understand threading optimisation, to quite ludicrous levels.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-2765970361586071075?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/kAZ9J1naU40" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/2765970361586071075/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=2765970361586071075" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/2765970361586071075?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/2765970361586071075?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/kAZ9J1naU40/musings-on-async.html" title="Musings on async" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>2</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/04/musings-on-async.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8BR3s8eSp7ImA9WhZQEkw.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-6955562987963143450</id><published>2011-04-19T04:38:00.001-07:00</published><updated>2011-04-19T05:57:36.571-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-19T05:57:36.571-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="c# profiling" /><title>Practical Profiling</title><content type="html">&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Profiling the hard way" border="0" alt="Profiling the hard way" align="right" src="http://lh4.ggpht.com/_feJtUp7IGuI/Ta10LtfQ-jI/AAAAAAAAAXQ/gUKd4Gt9tuc/stopwatch_in_hand_thumb%5B1%5D.png?imgmax=800" width="202" height="244" /&gt;If you don’t know what is causing delays, you are doomed to performance woes. Performance is something I care about deeply, and there are no end of performance / profiling tools available for .NET. Some invasive and detailed, some at a higher level. And quite often, tools that you wouldn’t leave plugged into your production code 24/7.&lt;/p&gt;  &lt;p&gt;Yet… I &lt;em&gt;care&lt;/em&gt; about my production environment 24/7; and trying to reproduce a simulated load for the sites I work on can be&amp;#160; somewhat challenging. So how can we get realistic and detailed data without adversely impacting the system?&lt;/p&gt;  &lt;h3&gt;Keep It Simple, Stupid&lt;/h3&gt;  &lt;p&gt;A common strapline in agile programming states:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Do the simplest thing that could possibly work&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now, I don’t profess to be strictly “agile”, or indeed strictly &lt;em&gt;anything&lt;/em&gt; (except maybe “pragmatic”) in my development process, but there is much wisdom in the above. And it makes perfect sense when wanting to add constant (live) profiling capabilities.&lt;/p&gt;  &lt;p&gt;So what is the simplest thing that could possibly work with profiling? Automated instrumentation? Process polling on the debugging API? &lt;em&gt;Way&lt;/em&gt; too invasive. IoC/DI chaining with profiling decorators? Overkill. AOP with something like PostSharp? Unnecessary complexity. How about we just &lt;em&gt;tell the system openly what we are doing?&lt;/em&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Heresy! That isn’t part of the system! It has no place in the codebase!&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Well, firstly – remember I said I was “pragmatic”, and secondly (more importantly) &lt;strong&gt;&lt;em&gt;performance is both a requirement and a feature&lt;/em&gt;&lt;/strong&gt;, so I have no qualms &lt;em&gt;whatsoever&lt;/em&gt; changing my code to improve our measurements.&lt;/p&gt;  &lt;h3&gt;So what are you talking about?&lt;/h3&gt;  &lt;p&gt;Frustrated by the inconvenience of many of the automated profiling tools, I cobbled together the simplest, hackiest, &lt;em&gt;yet fully working&lt;/em&gt; mini-profiler – and I thought I’d share. What I want is &lt;em&gt;as a developer&lt;/em&gt;, to be able to review the performance of pages I’m viewing in the production environment – sure, this doesn’t cover every scenario, but it certainly does the job on sites that are read-intensive. So say I browse to “http://mysite/grobbits/MK2-super-grobit” – I want immediate access to how that page was constructed (and where the pain was). And in particular, I want it live so I can hit “refresh” a few times and watch how it behaves as different caches expire. Nothing rocket-science, just a basic tool that will let me hone in on the unexpected performance bumps. Finally, it can’t impact performance the 99.99% of regular users who will never see that data.&lt;/p&gt;  &lt;p&gt;I’m currently having great success using this mini tool; the concept is simple – you have a MiniProfiler object (which would be null for most users), and you just surround the interesting code:&lt;/p&gt;  &lt;pre&gt;using (profiler.Step(&amp;quot;Set page title&amp;quot;))&lt;br /&gt;{&lt;br /&gt;    ViewBag.Message = &amp;quot;Welcome to ASP.NET MVC!&amp;quot;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;using (profiler.Step(&amp;quot;Doing complex stuff&amp;quot;))&lt;br /&gt;{&lt;br /&gt;    using (profiler.Step(&amp;quot;Step A&amp;quot;))&lt;br /&gt;    { // something more interesting here&lt;br /&gt;        Thread.Sleep(100);&lt;br /&gt;    }&lt;br /&gt;    using (profiler.Step(&amp;quot;Step B&amp;quot;))&lt;br /&gt;    { // and here&lt;br /&gt;        Thread.Sleep(250);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;(the Step(…) method is implemented as an extension method, so it is perfectly happy operating on a null reference; which is a crude but simple way of short-circuiting the timings for regular users)&lt;/p&gt;&lt;p&gt;Obviously this isn’t very sophisticated, and &lt;strong&gt;it isn’t meant to be&lt;/strong&gt; – but it is very fast, and easy to make as granular as you like as you focus in on some specific knot of code that is hurting. But for the simplicity, it is &lt;strong&gt;remarkably&lt;/strong&gt; useful in finding trouble spots on your key pages, and reviewing ongoing performance.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;So what do I see?&lt;/h3&gt;&lt;p&gt;The output is very &lt;strike&gt;basic&lt;/strike&gt; &lt;em&gt;functional&lt;/em&gt; – you simply get a call tree of the code you’ve marked as interesting (above), to whatever granularity you marked it to; no more, no less. So with the sample project (see below), the home-page displays (in the html markup):&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;!--&lt;br /&gt;MYPC at 19/04/2011 11:28:12&lt;br /&gt;Path: http://localhost:3324/&lt;br /&gt; http://localhost:3324/ = 376.9ms&lt;br /&gt;&amp;gt; Set page title = 0ms&lt;br /&gt;&amp;gt; Doing complex stuff = 349.3ms&lt;br /&gt;&amp;gt;&amp;gt; Step A = 99.3ms&lt;br /&gt;&amp;gt;&amp;gt; Step B = 250ms&lt;br /&gt;&amp;gt; OnResultExecuting = 27.5ms&lt;br /&gt;&amp;gt;&amp;gt; Some complex thinking = 24.8ms&lt;br /&gt;--&amp;gt;&lt;/pre&gt;&lt;p&gt;(for your developers only; there is no change for users without the profiler enabled)&lt;/p&gt;&lt;h3&gt;Stop waffling, Man!&lt;/h3&gt;&lt;p&gt;Anyway, if you have similar (high-level, but &lt;em&gt;live&lt;/em&gt;) profiling needs, I’ve thrown the mini-profiler onto &lt;a href="http://code.google.com/p/mvc-mini-profiler/"&gt;google-code&lt;/a&gt; and &lt;a href="http://nuget.org/List/Packages/MiniProfiler"&gt;NuGet&lt;/a&gt;, along with a tweaked version of the MVC3 (razor) sample project to show typical usage. Actually, you only need a &lt;a href="http://mvc-mini-profiler.googlecode.com/hg/MiniProfiler/MiniProfiler.cs"&gt;single C# file&lt;/a&gt; (it really is basic code, honest).&lt;/p&gt;&lt;ul&gt;&lt;li&gt;If you find it useful, let me know!&lt;/li&gt;&lt;li&gt;If it sucks, let me know!&lt;/li&gt;&lt;li&gt;If I’ve gone mad, let me know!&lt;/li&gt;&lt;li&gt;I’ve &lt;em&gt;you’ve&lt;/em&gt; gone mad, keep that to yourself.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-6955562987963143450?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/4s8LnqNgnkg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/6955562987963143450/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=6955562987963143450" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6955562987963143450?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6955562987963143450?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/4s8LnqNgnkg/practical-profiling.html" title="Practical Profiling" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_feJtUp7IGuI/Ta10LtfQ-jI/AAAAAAAAAXQ/gUKd4Gt9tuc/s72-c/stopwatch_in_hand_thumb%5B1%5D.png?imgmax=800" height="72" width="72" /><thr:total>8</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/04/practical-profiling.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUNQX88eyp7ImA9WhZQEU0.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-2516179010033384607</id><published>2011-04-11T04:48:00.001-07:00</published><updated>2011-04-17T22:24:50.173-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-17T22:24:50.173-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="c# .net 5.0 async redis" /><title>async Redis await BookSleeve</title><content type="html">&lt;p&gt;At &lt;a href="http://stackexchange.com/"&gt;Stack Exchange&lt;/a&gt;, performance is a feature we work hard at. Crazy hard. Whether that means &lt;a href="http://blog.stackoverflow.com/2010/08/stack-overflow-sponsors-haproxy/"&gt;sponsoring load-balancer features&lt;/a&gt; to reduce system impact, or &lt;a href="http://samsaffron.com/archive/2011/03/30/How+I+learned+to+stop+worrying+and+write+my+own+ORM"&gt;trying to out-do the ORM folks on their own turf&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;One of the many tools in our performance toolkit is &lt;a href="http://redis.io/"&gt;Redis&lt;/a&gt;; a highly performant key-value store that we use in various ways:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;as our second-level cache&lt;/li&gt;    &lt;li&gt;for various tracking etc counters, that we really don’t want to bother SQL Server about&lt;/li&gt;    &lt;li&gt;for our &lt;a href="http://en.wikipedia.org/wiki/Publish/subscribe"&gt;pub/sub&lt;/a&gt; channels&lt;/li&gt;    &lt;li&gt;for various other things that don’t need to go direct to SQL Server&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;It is &lt;em&gt;really&lt;/em&gt; fast; we were using the &lt;a href="https://github.com/migueldeicaza/redis-sharp"&gt;redis-sharp&lt;/a&gt; bindings and they served us well. I have much thanks for redis-sharp, and my intent here is not to critique it &lt;em&gt;at all&lt;/em&gt; – but rather to highlight that &lt;em&gt;in some environments&lt;/em&gt; you might need that extra turn of the wheel. First some context:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Redis itself is single threaded supporting multiple connections&lt;/li&gt;    &lt;li&gt;the Stack Exchange sites work in a &lt;a href="http://en.wikipedia.org/wiki/Multitenancy"&gt;multi-tenancy&lt;/a&gt; configuration, and in the case of Redis we partition (mainly) into Redis databases&lt;/li&gt;    &lt;li&gt;to reduce overheads (both handshakes etc and OS resources like sockets) we re-use our Redis connection(s)&lt;/li&gt;    &lt;li&gt;but since redis-sharp is not thread-safe we need to synchronize access to the connection&lt;/li&gt;    &lt;li&gt;and since redis-sharp is synchronous we need to block while we get each response&lt;/li&gt;    &lt;li&gt;and since we are split over Redis databases we might also first have to block while we &lt;a href="http://redis.io/commands/select"&gt;select&lt;/a&gt; database&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Now, LAN latency is low; most estimates put it at around 0.3ms per call – but &lt;strong&gt;this adds up&lt;/strong&gt;, especially if you might be blocking other callers behind you. And even more so given that you might not even care what the response is (yes, I know we could offload that somewhere so that it doesn’t impact the current request, but we would still end up adding blocking for requests that do care).&lt;/p&gt;  &lt;h3&gt;Enter BookSleeve&lt;/h3&gt;  &lt;blockquote&gt;   &lt;p&gt;Seriously, what now? What on earth is BookSleeve?&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;As a result of the above, we decided to write a bespoke Redis client with specific goals around solving these problems. Essentially it is a wrapper around Redis dictionary storage; and what do you call a wrapper around a dictionary? A book-sleeve. Yeah, I didn’t get it at first, but &lt;a href="http://blog.stackoverflow.com/2009/03/it-stack-overflow-update-naming-is-hard/"&gt;naming stuff is hard&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;And we’re giving it away (under the &lt;a href="http://www.apache.org/licenses/LICENSE-2.0"&gt;Apache License 2.0&lt;/a&gt;)! Stack Exchange is happy to release our efforts here as open source, which is groovy.&lt;/p&gt;  &lt;p&gt;So; what are the goals?&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;to operate as a fully-functional Redis client (obviously)&lt;/li&gt;    &lt;li&gt;to be thread-safe and non-blocking&lt;/li&gt;    &lt;li&gt;to support implicit database switching to help with multi-tenancy scenarios&lt;/li&gt;    &lt;li&gt;to be on-par with redis-sharp on like scenarios (i.e. a complete request/response cycle)&lt;/li&gt;    &lt;li&gt;to allow &lt;strong&gt;absolute minimum&lt;/strong&gt; cost fire-and-forget usage (for when you don’t care what the reply is, and errors will be handled separately)&lt;/li&gt;    &lt;li&gt;to allow use as a “future” – i.e request some data from Redis &lt;em&gt;and&lt;/em&gt; start some other work while it is on the wire, and merge in the Redis reply when available&lt;/li&gt;    &lt;li&gt;to allow use with callbacks for when you need the reply, but not necessarily as part of the current request&lt;/li&gt;    &lt;li&gt;to allow C# 5 continuation usage (aka &lt;a href="http://blogs.msdn.com/b/ericlippert/archive/2010/10/28/asynchrony-in-c-5-part-one.aspx"&gt;async/await&lt;/a&gt;)&lt;/li&gt;    &lt;li&gt;to allow fully pipelined usage – i.e. issue 200 requests before we’ve even got the first response&lt;/li&gt;    &lt;li&gt;to allow fully multiplexed usage – i.e. it must handle meshing the responses from different callers on different threads and on different databases &lt;strong&gt;but on the same connection&lt;/strong&gt; back to the originator&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;(actually, Stack Exchange didn’t strictly need the C# 5 scenario; I added that while moving it to open-source, but it is an excellent fit)&lt;/p&gt;  &lt;p&gt;   &lt;/p&gt;&lt;h3&gt;     &lt;p&gt;Where are we? And where can I try it?&lt;/p&gt;   &lt;/h3&gt; &lt;p&gt;&lt;/p&gt;  &lt;p&gt;It exists; it works; it even passes some of the tests! And it is fast. It still needs some tidying, some documentation, and more tests, but I offer you BookSleeve:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://code.google.com/p/booksleeve/"&gt;http://code.google.com/p/booksleeve/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The API is very basic and should be instantly familiar to anyone who has used Redis; and documentation will be added.&lt;/p&gt;  &lt;p&gt;In truth, the version I’m open-sourcing is more like the &lt;em&gt;offspring&lt;/em&gt; of the version we’re currently using in production – you tend to learn a lot the first time through. But as soon as we can validate it, Stack Exchange will be using BookSleeve too.&lt;/p&gt;  &lt;h3&gt;So how about some numbers&lt;/h3&gt;  &lt;p&gt;These are based on my dev machine, running redis &lt;strong&gt;on the same machine&lt;/strong&gt;, so I also include &lt;em&gt;estimates&lt;/em&gt; using the 0.3ms latency per request as mentioned above. &lt;/p&gt;  &lt;p&gt;In each test we are doing 5000 &lt;a href="http://redis.io/commands/INCR"&gt;INCR&lt;/a&gt; commands (purely as an arbitrary test); spread over 5 databases, in a round-robin in batches of 10 per db – i.e. 10 on db #0, 10 on db #1, … 10 on db #4 – so that is an additional 500 &lt;a href="http://redis.io/commands/SELECT"&gt;SELECT&lt;/a&gt; commands too.&lt;/p&gt;  &lt;p&gt;redis-sharp:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;to completion 430ms&lt;/li&gt;    &lt;li&gt;(not meaningful to measure fire-and-forget)&lt;/li&gt;    &lt;li&gt;to completion assuming 0.3ms LAN latency: 2080ms&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;BookSleeve&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;to completion 391ms&lt;/li&gt;    &lt;li&gt;2ms fire-and-forget&lt;/li&gt;    &lt;li&gt;to completion assuming 0.3ms LAN latency: 391ms&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The last 2 are the key, in particular noting that the time we aren’t waiting on LAN latency is otherwise-blocking time we have &lt;em&gt;subtracted for other callers&lt;/em&gt; (web servers tend to have more than one thing happening…); the fire-and-forget performance allows us to do a lot of operations without blocking the &lt;strong&gt;current&lt;/strong&gt; caller.&lt;/p&gt;  &lt;p&gt;As a bonus we have added to ability to do genuinely parallel work on a single caller – by starting a Redis request first, doing the &lt;em&gt;other&lt;/em&gt; work (TSQL typically), and then asking for the Redis result. And let’s face it, while TSQL is versatile, Redis is so fast that it would be quite unusual for the Redis reply to not to already be there by the time you get to look.&lt;/p&gt;  &lt;h3&gt;Wait – did you say C# 5?&lt;/h3&gt;  &lt;p&gt;Yep; because the API is task based, it can be used in any of 3 ways without needing separate APIs:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;synchronous (blocking on the response) via &lt;a href="http://msdn.microsoft.com/en-us/library/dd235604.aspx"&gt;Wait&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;asynchronous (callback-based) via &lt;a href="http://msdn.microsoft.com/en-us/library/dd235663.aspx"&gt;ContinueWith&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;async/await by using the &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=18712f38-fcd2-4e9f-9028-8373dc5732b2"&gt;Async CTP&lt;/a&gt; (edit &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=4738205d-5682-47bf-b62e-641f6441735b"&gt;or for VS2010 SP1&lt;/a&gt;) and C# 5 language features&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;As an example of the last:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_feJtUp7IGuI/TaLqkXi49vI/AAAAAAAAAXI/SzIiVkYReiY/s1600-h/async%20redis%5B4%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="async redis" border="0" alt="async redis" src="http://lh6.ggpht.com/_feJtUp7IGuI/TaLqlLyfSPI/AAAAAAAAAXM/7q9IXu8CLHI/async%20redis_thumb%5B2%5D.png?imgmax=800" width="328" height="421" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;IMPORTANT: in the above “await” does not mean “block until this is done” – it means “yield back to the caller here, and run the rest as a callback when the answer is available” – or for a better definition see &lt;a href="http://blogs.msdn.com/b/ericlippert/archive/tags/async/"&gt;Eric Lippert’s blog series&lt;/a&gt;.&lt;/p&gt;  &lt;h3&gt;And did I mention…&lt;/h3&gt;  &lt;p&gt;…that a high perfomance binary-based dictionary store works well when coupled with a high performance binary serializer? ;p&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-2516179010033384607?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/0Rsm_bHiXMQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/2516179010033384607/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=2516179010033384607" title="28 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/2516179010033384607?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/2516179010033384607?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/0Rsm_bHiXMQ/async-redis-await-booksleeve.html" title="async Redis await BookSleeve" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_feJtUp7IGuI/TaLqlLyfSPI/AAAAAAAAAXM/7q9IXu8CLHI/s72-c/async%20redis_thumb%5B2%5D.png?imgmax=800" height="72" width="72" /><thr:total>28</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/04/async-redis-await-booksleeve.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUBRXkzeip7ImA9Wx9aFU8.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-856677583324482271</id><published>2011-03-07T11:52:00.001-08:00</published><updated>2011-03-07T12:04:14.782-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-07T12:04:14.782-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><title>Objects, Graphs and all that Jazz</title><content type="html">&lt;p align="left"&gt;protobuf-net v2 ticks along slowly; I’m embarrassed to say that due to a combination of factors progress has been slower than I would have liked – and for purely human reasons (availability etc).&lt;/p&gt;  &lt;p&gt;But; I thought I’d better update with the tweaks I’m looking at currently; they have all been ticking along in the back of head for ages, but frankly people kept nagging me to provide them, so who am I to argue?&lt;/p&gt;  &lt;h3&gt;&lt;/h3&gt;  &lt;h3&gt;Caveat&lt;/h3&gt;  &lt;p&gt;This is all work-in-progress; don’t try to pull the trunk and shove it into production! Soon… I should also stress that all of the thoughts described below are &lt;strong&gt;outside&lt;/strong&gt; the interoperable protobuf spec; it’ll still be a valid protobuf stream, but this &lt;strong&gt;only&lt;/strong&gt; applies to protobuf-net talking to protobuf-net.&lt;/p&gt;  &lt;p&gt;So; here’s some common questions I get…&lt;/p&gt;  &lt;h3&gt;Type meta&lt;/h3&gt;  &lt;blockquote&gt;   &lt;p align="right"&gt;The serialization is fine, but I don’t know (and cannot know) all of my types up front. How can I do this?&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Well, protobuf is a contract based format; if you don’t know the types, it will struggle – as will any contract based serializer…&lt;/p&gt;  &lt;blockquote&gt;   &lt;p align="right"&gt;&lt;font color="#666666"&gt;Yes, I get that; now: how do I do it?&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p align="justify"&gt;Now, I’ve held off putting any meta in the stream for various reasons:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;it steps far outside the core protobuf spec&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;it flashes the warning signs of BinaryFormatter, my nemesis&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;But, so many people seem to want this that I think I have to buckle; but on my terms! So in v2, I’m adding the ability to indicate that (on a per-member basis) objects should resolve their type information from the stream. By default, by embedding the assembly-qualified-name, but providing an abstraction layer over that allowing you to provide your own string&amp;lt;===&amp;gt;Type map (and thus avoiding the knots in by stomach caused by too much type dependency).&lt;/p&gt;  &lt;h3 align="justify"&gt;Full graphs&lt;/h3&gt;  &lt;blockquote&gt;   &lt;p align="justify"&gt;&lt;font color="#666666"&gt;The serialization is fine, but my data is a graph, not a tree. How can I do this?&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p align="justify"&gt;Well, protobuf is a tree format; it doesn’t work like that…&lt;/p&gt;  &lt;blockquote&gt;   &lt;p align="right"&gt;&lt;font color="#666666"&gt;Yes, I get that; now: how do I do it?&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p align="justify"&gt;(by the way, are you spotting a pattern in the questions I get?)&lt;/p&gt;  &lt;p&gt;Type meta is something I &lt;em&gt;didn’t&lt;/em&gt; want to add, but graph support is something I have really wanted to sneak in; breaking all the rules with type meta seems a reasonable excuse. So in v2, I’m adding the ability (on a per-member basis) to use reference tracking to (de)serialize a complete object graph (except events; don’t get me &lt;em&gt;started&lt;/em&gt; on that…). A minor complication here is that for technical reasons it is a nightmare to support this concurrently with inheritance (which, btw, the core protobuf doesn’t support – I feel quite the anarchist here…); but I can &lt;em&gt;support&lt;/em&gt; it in conjunction with type meta; so you still get to keep inheritance, but implemented differently.&lt;/p&gt;  &lt;h3&gt;Repeated strings&lt;/h3&gt;  &lt;p&gt;It is fairly common to have repeated string data in a large graph. As an offshoot of full-graph support, we also get a mechanism to support string re-use for free; woot! So again, in v2 I’ll be enabling this on a per-member basis.&lt;/p&gt;  &lt;h3&gt;Footnote&lt;/h3&gt;  &lt;p&gt;All of this goes so far outside of the protobuf spec that I have little right to even call it protobuf-related any more; maybe I should force the caller to explicitly set an EnableImplementationSpecificOptions flag? So there is an portable core with some opt-in hacks for these random options.&lt;/p&gt;  &lt;p&gt;And again; this whole area is under development; I’m working on it, honest!&lt;/p&gt;  &lt;blockquote&gt;   &lt;p align="right"&gt;That’s great! My full-graph of dynamic objects using inheritance and string re-use works fine! Now how do I load it into my c++/java/php/python/whatever client?&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Don’t make me hurt you…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-856677583324482271?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/ohaticyvijo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/856677583324482271/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=856677583324482271" title="15 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/856677583324482271?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/856677583324482271?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/ohaticyvijo/objects-graphs-and-all-that-jazz.html" title="Objects, Graphs and all that Jazz" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>15</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2011/03/objects-graphs-and-all-that-jazz.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YFSHs6fyp7ImA9Wx5UEE4.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-6573927405125234814</id><published>2010-10-13T14:42:00.001-07:00</published><updated>2010-10-13T22:45:19.517-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-13T22:45:19.517-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="serialization" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><title>DataTable – life in the old beast?</title><content type="html">&lt;p&gt;&lt;b&gt;Updated:&lt;/b&gt; Billy referred me to the &lt;a href="http://blogs.msdn.com/b/tess/archive/2008/09/02/outofmemoryexceptions-while-remoting-very-large-datasets.aspx"&gt;binary remoting format&lt;/a&gt; for DataTable; stats for BinaryFormatter now include both xml and binary.&lt;br /&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;This week, someone &lt;a href="http://stackoverflow.com/questions/3916951/wcf-transmit-datatable-as-binary"&gt;asked the fastest way to send a lot of data&lt;/a&gt;, only currently available in a DataTable (as xml), over the wire.&lt;/p&gt;  &lt;p&gt;My &lt;em&gt;immediate&lt;/em&gt; thought was simply GZIP the xml and have done with it, but I was intrigued… can we do better? In particular (just for a complete surprise) I was thinking whether protobuf-net could be used to write them. Now don’t get me wrong; I’m not a big supporter of DataTable, but they are still alive in the wild. And protobuf-net is a general-purpose serializer, so… why not try to be helpful, eh?&lt;/p&gt;  &lt;p&gt;v1 won’t help &lt;em&gt;at all&lt;/em&gt; with this, since the object-model just isn’t primed for extension, but in v2 we have many options. I thought I’d look at some typical data (SalesOrderDetail from AdventureWorks2008R2; 121317 rows and 11 columns), comparing the &lt;a href="http://twitpic.com/2v6vft"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="Lucy" border="0" alt="Lucy" align="right" src="http://lh3.ggpht.com/_feJtUp7IGuI/TLYnwc67h-I/AAAAAAAAAWg/y03j4z68t48/173321129%5B1%5D%5B2%5D.png?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;inbuilt xml support, BinaryFormatter support, and protobuf-net. And each of those uncompressed, via gzip, and via deflate.  &lt;/p&gt;  &lt;p&gt;At this point my new friend Lucy (right) is pestering me for a walk, but… it worked; purely experimental, but committed (&lt;a href="http://code.google.com/p/protobuf-net/source/detail?r=356"&gt;r356&lt;/a&gt;). Results shown below:&lt;/p&gt;  &lt;pre&gt;Table loaded    11 cols 121317 rows&lt;br /&gt;DataTable (xml) (vanilla)               2269ms/6039ms&lt;br /&gt;                                       64,150,771 bytes&lt;br /&gt;DataTable (xml) (gzip)                  4881ms/6714ms&lt;br /&gt;                                       7,136,821 bytes&lt;br /&gt;DataTable (xml) (deflate)               4475ms/6351ms&lt;br /&gt;                                       7,136,803 bytes&lt;br /&gt;BinaryFormatter (rf:xml) (vanilla)      3710ms/6623ms&lt;br /&gt;                                       74,969,470 bytes&lt;br /&gt;BinaryFormatter (rf:xml) (gzip)         6879ms/8312ms&lt;br /&gt;                                       12,495,791 bytes&lt;br /&gt;BinaryFormatter (rf:xml) (deflate)      5979ms/7472ms&lt;br /&gt;                                       12,495,773 bytes&lt;br /&gt;BinaryFormatter (rf:binary) (vanilla)   2006ms/3366ms&lt;br /&gt;                                       11,272,592 bytes&lt;br /&gt;BinaryFormatter (rf:binary) (gzip)      3332ms/4267ms&lt;br /&gt;                                       8,265,057 bytes&lt;br /&gt;BinaryFormatter (rf:binary) (deflate)   3216ms/4130ms&lt;br /&gt;                                       8,265,039 bytes&lt;br /&gt;protobuf-net v2 (vanilla)               316ms/773ms&lt;br /&gt;                                       8,708,846 bytes&lt;br /&gt;protobuf-net v2 (gzip)                  932ms/1096ms&lt;br /&gt;                                       4,797,856 bytes&lt;br /&gt;protobuf-net v2 (deflate)               872ms/1050ms&lt;br /&gt;                                       4,797,838 bytes&lt;/pre&gt;Since “walkies” beckons, I’ll be brief:&lt;ul&gt;  &lt;li&gt;the inbuilt xml and BinaryFormatter (as xml) are both very large natively and compress pretty well, but with noticeable additional CPU costs&lt;/li&gt;&lt;li&gt;with BinaryFormatter using the &lt;i&gt;binary&lt;/i&gt; encoding it does much less work, getting (before compression) into the same size-bracket as the xml&lt;i&gt; &lt;/i&gt;encoding managed &lt;i&gt;with&lt;/i&gt; compression&lt;/li&gt;  &lt;li&gt;protobuf-net is much faster in terms of CPU, but &lt;em&gt;slightly&lt;/em&gt; larger than the gzip xml output&lt;/li&gt;  &lt;li&gt;unusually for protobuf, it compresses quite will – presumably there is enough text in there to make it worthwhile; this then takes roughly half the size and much less CPU (compared to gzip xml)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Overall the current experimental code is &lt;strong&gt;exceptionally&lt;/strong&gt; rough and ready, mainly as an investigation. But… should I pursue this? do people still care about DataTable enough? Or just use gzip/xml in this scenario?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-6573927405125234814?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/I16O15BGZFo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/6573927405125234814/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=6573927405125234814" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6573927405125234814?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6573927405125234814?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/I16O15BGZFo/datatable-life-in-old-beast.html" title="DataTable – life in the old beast?" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_feJtUp7IGuI/TLYnwc67h-I/AAAAAAAAAWg/y03j4z68t48/s72-c/173321129%5B1%5D%5B2%5D.png?imgmax=800" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2010/10/datatable-life-in-old-beast.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cNQXwyfip7ImA9Wx5WEkU.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-7829144306688892642</id><published>2010-09-23T16:32:00.000-07:00</published><updated>2010-09-23T16:38:10.296-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-23T16:38:10.296-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><title>Other news…</title><content type="html">&lt;p&gt;Sorry if this is turning into a bit of a serialization fest; I do &lt;em&gt;have &lt;/em&gt;other coding hobbies; simply this is the thing I’ve been spending my spare time on lately ;p&lt;/p&gt;  &lt;h3&gt;Silverlight WCF&lt;/h3&gt;  &lt;p&gt;It recently came to my attention that &lt;em&gt;possibly&lt;/em&gt; Silverlight &lt;em&gt;does &lt;/em&gt;now support the WCF extension points for swapping the serializer at runtime. Not via xml configuration, but via code configuration. Full details on &lt;a href="http://blogs.msdn.com/b/carlosfigueira/archive/2010/04/29/consuming-rest-json-services-in-silverlight-4.aspx"&gt;Carlos’ Blog&lt;/a&gt;, but that is definitely an area I want to investigate – at least, &lt;a href="http://twitter.com/abdullin/status/25307712742"&gt;if @abdullin will let me&lt;/a&gt;.&lt;/p&gt;  &lt;h3&gt;Interface serialization&lt;/h3&gt;  &lt;p&gt;Something a few people have asked for, and definitely not outside reach. In fact, Wallace Turner kindly donated a v1 patch to enable interface-based serialization. I’m keeping this “on ice” for now, simply to keep my main focus on finishing v2. But this &lt;em&gt;exists&lt;/em&gt; and is certainly on the table for consideration.&lt;/p&gt;  &lt;p&gt;Anyway, enough for now; the day job starts again in not-a-lot-of-hours…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-7829144306688892642?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/M7WhsrXJqHw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/7829144306688892642/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=7829144306688892642" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/7829144306688892642?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/7829144306688892642?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/M7WhsrXJqHw/other-news.html" title="Other news…" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2010/09/other-news.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkABSHs4fip7ImA9Wx5WEkU.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-8276564451739745894</id><published>2010-09-23T16:31:00.001-07:00</published><updated>2010-09-23T16:32:39.536-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-23T16:32:39.536-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><title>protobuf-net on MonoDroid</title><content type="html">&lt;p&gt;I was very pleased to get an invite to the &lt;a href="http://www.go-mono.com/monodroid/"&gt;MonoDroid&lt;/a&gt; (Mono tools / environment for Android) beta earlier in the week, so in addition to a few v2 commits I’ve been playing with shiny new toys.&lt;/p&gt;  &lt;h3&gt;Wow; decent reflection!&lt;/h3&gt;  &lt;p&gt;Initially I made the mistake of thinking that MonoDroid would have the same reflection limitations as (say) &lt;a href="http://monotouch.net/"&gt;MonoTouch&lt;/a&gt;. I even tied myself in knots trying to get around them! Then Jb Evian pointed out that actually MonoDroid can do full meta-programming at runtime! That is a &lt;em&gt;huge&lt;/em&gt; plus for me… so; whack in a few conditional-compilation symbols and – wow! It works!&lt;/p&gt;  &lt;h3&gt;A taster&lt;/h3&gt;  &lt;p&gt;Don’t get &lt;em&gt;too &lt;/em&gt;excited – this is only going to be brief…&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="Yes, another amazing example of my l33t UI skillz" border="0" alt="Yes, another amazing example of my l33t UI skillz" align="left" src="http://lh3.ggpht.com/_feJtUp7IGuI/TJvjauutv-I/AAAAAAAAAWY/AYEcvT_B3zw/image%5B13%5D.png?imgmax=800" width="244" height="132" /&gt; &lt;/p&gt;  &lt;p&gt;Only intended to show something working, but here is v2 on MonoDroid, compiled at runtime, round-tripping some trivial data.&lt;/p&gt;  &lt;p&gt;A small (but significant) step. Actually, the time taken to compile the model and run it the &lt;em&gt;first&lt;/em&gt; time is still a bit slow for my liking – not sure if that is the emulator, the beta, or a general JIT issue – I’ll dig more and investigate rebasing further.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="No really, this is all I have for gfx" border="0" alt="No really, this is all I have for gfx" align="right" src="http://lh6.ggpht.com/_feJtUp7IGuI/TJvjbOQWqRI/AAAAAAAAAWc/u5993NYo3XU/image%5B12%5D.png?imgmax=800" width="244" height="107" /&gt; And of course as a fallback, I can still use runtime usage &lt;em&gt;without&lt;/em&gt; “emit” – it is noticeably slower, but still works.&lt;/p&gt;  &lt;p&gt;Again, without an actual device it is hard to gauge typical performance at this point, but I’m pretty hopeful.&lt;/p&gt;  &lt;h3&gt;So… if that works, what are you waiting for?&lt;/h3&gt;  &lt;p&gt;I still need to &lt;em&gt;finish&lt;/em&gt; v2; some decent commits lately now that I’m all refreshed. The finishing line is within sight… oh, and MonoDroid needs to be released ;p&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-8276564451739745894?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/WuP8ofmGwC0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/8276564451739745894/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=8276564451739745894" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/8276564451739745894?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/8276564451739745894?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/WuP8ofmGwC0/protobuf-net-on-monodroid.html" title="protobuf-net on MonoDroid" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_feJtUp7IGuI/TJvjauutv-I/AAAAAAAAAWY/AYEcvT_B3zw/s72-c/image%5B13%5D.png?imgmax=800" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2010/09/protobuf-net-on-monodroid.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcAQXc9fSp7ImA9Wx5WEkk.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-6208049830069216275</id><published>2010-09-19T23:18:00.001-07:00</published><updated>2010-09-23T05:47:20.965-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-23T05:47:20.965-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><title>protobuf-net; ushort glitch before r274</title><content type="html">&lt;p&gt;Dammit, I hate it when a gremlin shows up. I hate it even more when they show up a year later…&lt;/p&gt;  &lt;p&gt;It turns out that a bug “fix” to ushort (unsigned 16-bit integers) handling back in October 2009 introduced a slight… “nuance” when moving between versions &amp;lt; r274 and &amp;gt;= r274. Basically, due to a braindead bug on my part, it was treating ushort data as strings rather than handling appropriately. This was fixed a year ago, but if you are moving between versions is a PITA.&lt;/p&gt;  &lt;p&gt;Sorry for any inconvenience folks, but… well, it happened. I can’t change that. Anyway, how to fix?! The good news is &lt;b&gt;NO DATA IS LOST&lt;/b&gt; - it is just a bit trickier to access. You wouldn't have encountered the issue if working against rigid .proto / cross-platform definitions (since .proto doesn't have direct ushort support), so I’ll limit myself to the pure .NET scenario. In which case, IMO the easiest fix is to introduce a shim property, so:&lt;/p&gt; &lt;code&gt;[ProtoMember(1)]   &lt;br /&gt;public ushort Foo {get;set;} &lt;/code&gt;  &lt;p&gt;might be updated to:&lt;/p&gt; &lt;code&gt;[ProtoMember(1)]   &lt;br /&gt;private string FooLegacy { // a pass-thru    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; get {return Foo.ToString();}    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; set {Foo = ushort.Parse(value);}    &lt;br /&gt;}    &lt;br /&gt;private bool FooLegacySpecified { // suppress serialization    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; get {return false;}    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; set {}    &lt;br /&gt;}    &lt;br /&gt;[ProtoMember(42)] // any unused field number    &lt;br /&gt;public ushort Foo {get;set;} &lt;/code&gt;  &lt;p&gt;This allows old-style and the &lt;i&gt;correct&lt;/i&gt; data to be used side-by-side (always writing to the new format). For arrays, see my &lt;a href="http://stackoverflow.com/questions/3672777/protobuf-net-r282-having-problems-deserializing-object-serialized-with-r246/3674086#3674086"&gt;longer answer here&lt;/a&gt;, which also switches to the more efficient &amp;quot;packed&amp;quot; encoding, introduced later to the protobuf spec.&lt;/p&gt;  &lt;p&gt;Sorry for any inconvenience folks. Fortunately use of ushort is fairly uncommon in .NET, so &lt;em&gt;my hope&lt;/em&gt; is that there aren't vast hordes of people impacted by this unfortunate foible.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;As a side note, I should add: I considered trying to add automatic handling of old data, but it transpires that the borked data is so similar to "packed" encoding as to be ambiguous in some cases, so trying to guess was too risky. And it would compound the issue by layering hack upon bug.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-6208049830069216275?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/gTrOlwIlarc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/6208049830069216275/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=6208049830069216275" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6208049830069216275?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6208049830069216275?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/gTrOlwIlarc/protobuf-net-ushort-glitch-before-r274.html" title="protobuf-net; ushort glitch before r274" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2010/09/protobuf-net-ushort-glitch-before-r274.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIHRHs8eCp7ImA9Wx5QGU4.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-1926679388757389748</id><published>2010-09-08T01:50:00.001-07:00</published><updated>2010-09-08T02:02:15.570-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-08T02:02:15.570-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>Truer than true</title><content type="html">&lt;p&gt;(&lt;b&gt;edit:&lt;/b&gt; apols for the formatting; google ate my images - have replaced with source, but raw)&lt;/p&gt;&lt;p&gt;I’ve been quiet for a little while, due to general fatigue, changing job etc – but after a holiday I’m back refreshed and renewed.&lt;/p&gt;  &lt;p&gt;So let’s start with a fun edge condition, inspired by my colleague &lt;a href="http://meta.stackoverflow.com/users/115866/balpha"&gt;balpha&lt;/a&gt;, who asked me “does C#/.NET/LINQ guarantee false &amp;lt; true?”.&lt;/p&gt;  &lt;h3&gt;So, is it?&lt;/h3&gt;  &lt;p&gt;I’m leaving LINQ aside, as for anything other than LINQ-to-Objects, all bets are off; so let’s just limit ourselves to C#; in that case the answer is pretty simple, “yes”. &lt;code&gt;System.Boolean&lt;/code&gt; implements &lt;code&gt;IComparable&lt;/code&gt; and &lt;code&gt;IComparable&amp;lt;bool&amp;gt;&lt;/code&gt; such that this will always work. But not all .NET is C# ;p So how can we be evil here?&lt;/p&gt;  &lt;h3&gt;What is a boolean, anyways?&lt;/h3&gt;  &lt;p&gt;First, we need to understand that (in common with many runtimes/languages) the CLI doesn’t really know much about booleans – under the hood they are treated pretty-much the same as integers, with special treatment for “zero” and “not zero”. That means that &lt;em&gt;technically&lt;/em&gt; we aren’t restricted to the expected values – it is simply that C# handles all the logic to make sure you only get sane values. But we can write our own IL – here I’m using &lt;code&gt;DynamicMethod&lt;/code&gt; to create a &lt;code&gt;bool&lt;/code&gt; with underlying value 2:&lt;/p&gt;  &lt;pre&gt;&lt;br /&gt;// write an evil non-C# function that returns something &lt;br /&gt;// unexpected for a bool (but legal IL)&lt;br /&gt;var dm = new DynamicMethod("mwahaha", typeof(bool), null);&lt;br /&gt;var il = dm.GetILGenerator();&lt;br /&gt;il.Emit(OpCodes.Ldc_I4_2);&lt;br /&gt;il.Emit(OpCodes.Ret);&lt;br /&gt;var func = (Func&amp;lt;bool&amp;gt;)dm.CreateDelegate(typeof(Func&amp;lt;bool&amp;gt;));&lt;br /&gt;var superTrue = func();&lt;br /&gt;&lt;/pre&gt; &lt;p&gt;The first thing to note is that you &lt;strong&gt;shouldn’t do this. &lt;/strong&gt;So what does such a beast do? The first thing to note is that at first glance it &lt;em&gt;appears&lt;/em&gt; to work as expected:&lt;/p&gt;  &lt;pre&gt;&lt;br /&gt;// is it true/false?&lt;br /&gt;Console.WriteLine(superTrue); // prints: true&lt;br /&gt;Console.WriteLine(!superTrue); // prints: false&lt;br /&gt;// and does it *equal* true/false?&lt;br /&gt;Console.WriteLine(superTrue == true); // prints: true&lt;br /&gt;Console.WriteLine(superTrue == false); // prints: false&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;so the non-zero / zero handling is just like we expect? Well, no. The compiler isn’t helping us here, as it spots the constants. However, if we compare to &lt;em&gt;variables&lt;/em&gt;, it uses the &lt;em&gt;underlying&lt;/em&gt; value:&lt;/p&gt;  &lt;pre&gt;&lt;br /&gt;// really?&lt;br /&gt;bool normalTrue = bool.Parse("true"), normalFalse = bool.Parse("false");&lt;br /&gt;Console.WriteLine(superTrue == normalTrue); // prints: false&lt;br /&gt;Console.WriteLine(superTrue == normalFalse); // prints: false&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;(I’m using &lt;code&gt;bool.Parse&lt;/code&gt; here to avoid the compiler getting clever)&lt;/p&gt;  &lt;h3&gt;And ordering?&lt;/h3&gt;  &lt;p&gt;We could postulate that this “super-true” is more than “true”, or maybe we might suppose the implementation is going to just treat it as true. In fact, neither is correct – the implementation of &lt;code&gt;CompareTo&lt;/code&gt; (testing in .NET 4) means that it simply breaks:&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;// how about sorting...&lt;br /&gt;Console.WriteLine(superTrue.CompareTo(true)); // prints: 1&lt;br /&gt;Console.WriteLine(true.CompareTo(superTrue)); // prints: 1 - oops!&lt;br /&gt;&lt;/pre&gt; &lt;p&gt;That is going to make sorting very painful.&lt;/p&gt;  &lt;h3&gt;So what is your point?&lt;/h3&gt;  &lt;p&gt;Well, the first thing to note is that I haven’t disproven the original question; as far as I can tell, false is always less than true. However, you &lt;em&gt;can&lt;/em&gt; get some very bizarrely behaved booleans. You would have to be &lt;strong&gt;crazy&lt;/strong&gt; to deliberately introduce such shenanigans into your code, but it is something to perhaps at least &lt;em&gt;know about&lt;/em&gt; as part of defensive programming / data sanitization – I’m fairly sure you could cause some nasty effects by passing 17 in as a &lt;code&gt;bool&lt;/code&gt; to a few places…&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-1926679388757389748?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/0TkR2mOGKCc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/1926679388757389748/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=1926679388757389748" title="10 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/1926679388757389748?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/1926679388757389748?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/0TkR2mOGKCc/truer-than-true.html" title="Truer than true" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>10</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2010/09/truer-than-true.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE4HRXcyfyp7ImA9WxFVFk4.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-9070216655152313381</id><published>2010-06-15T12:38:00.001-07:00</published><updated>2010-06-15T13:15:34.997-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-15T13:15:34.997-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mvc" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>Extending ASP.NET MVC with custom binders and results</title><content type="html">&lt;p&gt;Recently, I was putting together a brief sample for someone who wanted to use protobuf-net with ASP.NET as part of a basic HTTP transport; fairly simple stuff – just using protobuf as the binary body of the HTTP request/response.&lt;/p&gt;  &lt;p&gt;It was a simple enough demo, but it got me wondering: what would be required to do this (more cleanly) in ASP.NET MVC? In many ways we just want something pretty similar to how many people currently use JSON: forget the formal API – just tell me the routes and let me know what data I need.&lt;/p&gt;  &lt;p&gt;It turns out that this is &lt;em&gt;astonishingly&lt;/em&gt; easy…&lt;/p&gt;  &lt;h3&gt;The controller&lt;/h3&gt;  &lt;p&gt;A good way of understanding the big picture is to look at the controller. So let’s take a peek:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_feJtUp7IGuI/TBfWjwMle_I/AAAAAAAAAVQ/c0PMkzaFdYs/s1600-h/image%5B25%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_feJtUp7IGuI/TBfWkkyhf2I/AAAAAAAAAVU/HtA3SRLLVi8/image_thumb%5B15%5D.png?imgmax=800" width="430" height="191" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;One very basic controller, with one action. Things to note:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;We want to read the request parameter (“req”) from the request body&lt;/li&gt;    &lt;li&gt;To do that, we’re using a custom binder, via [ProtoPost] which we’ll see shortly&lt;/li&gt;    &lt;li&gt;We &lt;em&gt;could&lt;/em&gt; have exposed different input arguments separately – it would have added complexity, and isn’t very compatible with the way that requests are written in the .proto language, so I’ve restricted myself to binding a single (composite) parameter&lt;/li&gt;    &lt;li&gt;We run some logic, same as normal&lt;/li&gt;    &lt;li&gt;We return an action-result that will write the response back as protobuf&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The nice thing about this is that (no matter which option you use to control your routes) it is very simple to add actions (as different urls).&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;That might be all you need to know!&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I’ll include more explanation for completeness, but if you want a simple way of throwing objects over http efficiently and in an interoperable way, that might be enough.&lt;/p&gt;  &lt;h3&gt;The binder&lt;/h3&gt;  &lt;p&gt;The binder’s job is it understand the incoming request, and map that into things the controller can understand, such as method variables. There are two parts to a binder: writing the code to handle the input, and telling the system to use it. Writing a binder, it turns out, can be pretty simple (well – if you already have the serialization engine available); here’s all there is:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_feJtUp7IGuI/TBfWlDku1hI/AAAAAAAAAVY/-WYAL9kiJEY/s1600-h/image%5B12%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_feJtUp7IGuI/TBfWl53pnpI/AAAAAAAAAVc/GdTmRR_sXes/image_thumb%5B6%5D.png?imgmax=800" width="431" height="202" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;This simply checks that the caller is doing a POST, and if they are it passes the input stream to protobuf-net, based on the parameter type (which is available from the binding-context).&lt;/p&gt;  &lt;p&gt;The other part is to tell ASP.NET MVC to use it; in my case I’m using a new [ProtoPost] attribute which simply creates the binder:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_feJtUp7IGuI/TBfWmK0f9jI/AAAAAAAAAVg/kSSQjv7Y2SQ/s1600-h/image%5B26%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_feJtUp7IGuI/TBfWmmlc9eI/AAAAAAAAAVk/O0Sk7jaQ7Ro/image_thumb%5B16%5D.png?imgmax=800" width="336" height="130" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h3&gt;The result&lt;/h3&gt;  &lt;p&gt;Just as a controller doesn’t need to know how to parse input, it also doesn’t know how to format output – that is the job of an action-result; we’ll write our own, that we can re-use to write objects to the response stream. Which is actually less work than writing the last sentence!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_feJtUp7IGuI/TBfWnN7g9wI/AAAAAAAAAVo/MNyC7m-Vge0/s1600-h/image%5B24%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_feJtUp7IGuI/TBfWozJHdAI/AAAAAAAAAVs/sShyPF6zczA/image_thumb%5B14%5D.png?imgmax=800" width="471" height="260" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Again – some very basic code that simply takes an object and writes it to the output stream via protobuf-net.&lt;/p&gt;  &lt;h3&gt;Anything else?&lt;/h3&gt;  &lt;p&gt;OK, I’ve taken some shortcuts there. To do it properly you might want to check for an expected content-type, etc – and things like security is left open for your own implementation (just like it would be for any other similar object-passing API). I’m just showing the core object &amp;lt;===&amp;gt; stream code here. But it works, and is painless.&lt;/p&gt;  &lt;p&gt;The example code (include the ASP.NET / IHttpHandler equivalent, and an example client) is all available &lt;a href="http://code.google.com/p/protobuf-net/source/browse/#svn/trunk/BasicHttp"&gt;in the protobuf-net trunk, here&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-9070216655152313381?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/jH6dicpVc4w" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/9070216655152313381/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=9070216655152313381" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/9070216655152313381?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/9070216655152313381?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/jH6dicpVc4w/extending-aspnet-mvc-with-custom.html" title="Extending ASP.NET MVC with custom binders and results" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_feJtUp7IGuI/TBfWkkyhf2I/AAAAAAAAAVU/HtA3SRLLVi8/s72-c/image_thumb%5B15%5D.png?imgmax=800" height="72" width="72" /><thr:total>8</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2010/06/extending-aspnet-mvc-with-custom.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8AQno5fyp7ImA9WxFWGEw.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-6251215516804267164</id><published>2010-06-06T01:26:00.000-07:00</published><updated>2010-06-06T01:27:23.427-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-06T01:27:23.427-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="me" /><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><title>protobuf-net; a status update</title><content type="html">&lt;p&gt;I keep promising “v2” is just around the corner, and (quite reasonably) I get a steady stream of “when” e-mails / tweets etc, so it is time for a status update…&lt;/p&gt;  &lt;p&gt;…but first I must apologise for the delay; the short version is that in the last few weeks I’ve changed jobs, and it has taken a bit of time to get my daily pattern (work time, family time, geek time, etc) sorted. Since I no longer spend 4 hours a day commuting, &lt;em&gt;in theory&lt;/em&gt; I have more time available. In reality I’m spending lots more time with my family, which I don’t regret. But I’m getting back into the “crazy geek” thing ;p&lt;/p&gt;  &lt;h3&gt;So where is protobuf-net?&lt;/h3&gt;  &lt;p&gt;The first thing to note that “v2” is not a minor change; it &lt;strong&gt;completely&lt;/strong&gt; changes the crazy-complex generics pipeline (which &lt;a href="http://marcgravell.blogspot.com/2009/03/compact-framework-woes-revisted.html"&gt;killed CF&lt;/a&gt;, and was generally a bad design choice for lots of reasons), opting instead for a non-generic pipeline coupled with an IL emitter to get the maximum performance. It also introduces a whole new metadata abstraction layer, and static dll usage (so it works on &lt;a href="http://marcgravell.blogspot.com/2010/02/protobuf-net-v2-on-iphone.html"&gt;iPhone&lt;/a&gt; (but don’t ask me how the SDK rules affect this; IANAL), &lt;a href="http://marcgravell.blogspot.com/2010/04/walkthrough-protobuf-net-on-phone-7.html"&gt;Phone 7&lt;/a&gt;, and so that CF doesn’t have to use reflection).&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The numbers&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Tests for new new features (metadata abstraction, IL generation, etc): 100%&lt;/li&gt;    &lt;li&gt;Compatibility tests:79% (228 / 287, plus some skipped that won’t be in the first alpha release)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I should note: my unit tests for this tend, right or wrong, to each cover a number of features; it is &lt;strong&gt;very&lt;/strong&gt; hard to make the regression tests overly granular, but to be honest I think we can all agree that the main objective is &lt;em&gt;not&lt;/em&gt; to have the world’s most beautiful tests, but rather: to check that the system works robustly.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The gaps&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Mapped enums; it’ll handle enums, but it currently only treats them as pass-thrus to the underlying primitive value. It doesn’t currently process [ProtoEnum]. Not hard, just time.&lt;/li&gt;    &lt;li&gt;Member inference (which was the best “v1” could do to allow serialization of types outside your control); this doesn’t involve IL, so not too tricky – and not used by the majority.&lt;/li&gt;    &lt;li&gt;Roundtrip for unexpected fields (currently dropped; this also impacts the memcached transcoder)&lt;/li&gt;    &lt;li&gt;Parse/ToString fallback for unknown types (another “v1” feature)&lt;/li&gt;    &lt;li&gt;Packed arrays (an optional, alternative wire-format for lists/arrays; this won’t affect you if you haven’t heard of it, since it is opt-in)&lt;/li&gt;    &lt;li&gt;*WithLengthPrefix – for reading/writing multiple objects to/from a single stream&lt;/li&gt;    &lt;li&gt;GetProto (this is deferred from the alpha release, as it isn’t “core” functionality, and is &lt;em&gt;significant&lt;/em&gt; work to do properly)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;No show-stoppers; just work to do. Not long now. I’m reluctant to promise a “when” since I’ve delayed already…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-6251215516804267164?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/vL4BmluFOyg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/6251215516804267164/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=6251215516804267164" title="16 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6251215516804267164?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6251215516804267164?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/vL4BmluFOyg/protobuf-net-status-update.html" title="protobuf-net; a status update" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>16</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2010/06/protobuf-net-status-update.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEABQ3szeip7ImA9WxFWEkw.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-4085824957314167516</id><published>2010-05-30T03:45:00.000-07:00</published><updated>2010-05-30T03:52:32.582-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-30T03:52:32.582-07:00</app:edited><title>When to optimize?</title><content type="html">&lt;p&gt;Prompted by a &lt;a href="http://twitter.com/codinghorror/status/15025641432"&gt;tweet earlier&lt;/a&gt;, I thought I’d share some thoughts on optimization. In code, there are diverging views here, varying between the extremes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Forget the performance; write an awesome application, then see (perhaps profile, perhaps just use it) where it sucks &lt;/li&gt;    &lt;li&gt;Performance rules! Give yourself an ulcer trying to eek out every last picosecond of CPU and nibble of RAM! &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="We&amp;#39;ve all been there" border="0" alt="We&amp;#39;ve all been there" align="right" src="http://lh4.ggpht.com/_feJtUp7IGuI/TAJDb_RK4_I/AAAAAAAAAU0/jXLeIS-r1B0/stress2%5B1%5D%5B4%5D.jpg?imgmax=800" width="244" height="241" /&gt; Obviously there is some pragmatic middle-ground in the middle where you need to &lt;em&gt;design&lt;/em&gt; an app deliberately to allow performance, without stressing over every line of code, every stack-frame, etc.&lt;/p&gt;  &lt;h3&gt;Is this juxtaposition valid?&lt;/h3&gt;  &lt;p&gt;I suspect it is. In my day job I’m an app developer: what matters is shipping an app that works, is usable, is clear, doesn’t corrupt the database, doesn’t e-mail real clients from the test server*, etc. Performance is important, but management aren’t going to be impressed with “I shaved 3ms/cycle from the ‘frobing’ loop! oh, yes, but the login page is still broken”.&lt;/p&gt;  &lt;p&gt;But my “for kicks” OSS alter-ego is a &lt;em&gt;library &lt;/em&gt;developer. Shipping your library with great features is important, but library developers are (in my experience at least) far more interested in all the micro-optimisations. And this makes sense; the people &lt;em&gt;using&lt;/em&gt; your library are trusting you to do it well – they’re too busy getting the login page working. And for a library developer, getting these details right is part of &lt;em&gt;how&lt;/em&gt; you deliver the best product.&lt;/p&gt;  &lt;h3&gt;Summary&lt;/h3&gt;  &lt;p&gt;So next time you hear somebody worrying about whether to use string.Concat(string[]), string.Concat(object[]) or StringBuilder: it &lt;em&gt;could&lt;/em&gt; be random micro-optimisation gone wild (and please do kick them); but maybe, just maybe, you’re dealing with a closet library developer.&lt;/p&gt; &lt;small&gt;*=yes, I’ve accidentally done that. Once. Fortunately we caught it quickly, and the data wasn’t rude or anything. Lawsuit avoided.&lt;/small&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-4085824957314167516?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/JMAOWVwiCDU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/4085824957314167516/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=4085824957314167516" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/4085824957314167516?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/4085824957314167516?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/JMAOWVwiCDU/when-to-optimize.html" title="When to optimize?" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_feJtUp7IGuI/TAJDb_RK4_I/AAAAAAAAAU0/jXLeIS-r1B0/s72-c/stress2%5B1%5D%5B4%5D.jpg?imgmax=800" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2010/05/when-to-optimize.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUNQXk5eyp7ImA9WxFQFUs.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-2318174339966453680</id><published>2010-05-06T14:53:00.000-07:00</published><updated>2010-05-11T01:24:50.723-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-11T01:24:50.723-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="4.0" /><title>Strings: sorted</title><content type="html">&lt;p&gt;Sorting data… I don’t mean complex bespoke types that you’ve written – I mean inbuilt types like “string”. You probably wouldn’t think too long about trying to sort strings – you just expect them &lt;em&gt;to work&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;Oddly enough, this wasn’t actually always the case. OK, it is an edge case, but string comparison wasn’t actually guaranteed to be &lt;em&gt;&lt;a href="http://en.wikipedia.org/wiki/Transitive_relation"&gt;transitive&lt;/a&gt;&lt;/em&gt;. By this I mean that if we’ve got three values A, B and C, and we’ve tested that A comes before B, and B comes before C – then you might reasonably deduce that A comes before C. This is a key requirement for sorting (and has always been documented as such). But it &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/details/236900/string-compare-not-always-transitive#details"&gt;wasn’t always the case&lt;/a&gt;!&lt;/p&gt;  &lt;p&gt;Why is this bad? At best case, your data can choose random-looking sort orders. At worst case a “sort” operation may loop forever, attempting to shuffle data that is teasing it.&lt;/p&gt;  &lt;p&gt;Even though this oddity was rare, it was problem enough for it to come up in the wild, way back when usenet was in vogue (in other news: &lt;a href="http://www.microsoft.com/communities/newsgroups/default.mspx"&gt;Microsoft is shutting down their usenet farm&lt;/a&gt;… is that news to anyone?).&lt;/p&gt;  &lt;p&gt;It was news to me, but while &lt;a href="http://stackoverflow.com/questions/2784344/c-system-stackoverflowexception-with-lambda/2784389#2784389"&gt;discussing this curio&lt;/a&gt;, somebody observed that it is now fixed in .NET 4.0; the nature of the fix means that the code in the connect article (above) needs re-ordering to show it working and not-working as you flip between framework versions; here’s the updated sample:&lt;/p&gt;  &lt;pre&gt;        string s1 = "-0.67:-0.33:0.33";&lt;br /&gt;      string s2 = "-0.67:0.33:-0.33";&lt;br /&gt;      string s3 = "0.67:-0.33:0.33";&lt;br /&gt;    &lt;br /&gt;      Console.WriteLine(s1.CompareTo(s2));&lt;br /&gt;      Console.WriteLine(s2.CompareTo(s3));&lt;br /&gt;      Console.WriteLine(s1.CompareTo(s3));&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In .NET &amp;lt; 4.0 this shows “-1 –1 1” (this is a &lt;strong&gt;fail&lt;/strong&gt;). In .NET 4.0, it shows “1 1 1” (a pass). I tried a range of combinations and couldn’t make it misbehave. A small matter, maybe, but I’m much happier knowing that this has finally been tucked up in bed.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-2318174339966453680?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/KJWW77LuDOM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/2318174339966453680/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=2318174339966453680" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/2318174339966453680?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/2318174339966453680?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/KJWW77LuDOM/strings-sorted.html" title="Strings: sorted" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><thr:total>3</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2010/05/strings-sorted.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QEQXc_cSp7ImA9WxFRFkg.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-8559749379905883169</id><published>2010-04-30T13:27:00.000-07:00</published><updated>2010-04-30T13:28:20.949-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-30T13:28:20.949-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="serialization" /><category scheme="http://www.blogger.com/atom/ns#" term="phone-7" /><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><category scheme="http://www.blogger.com/atom/ns#" term="cf" /><title>Walkthrough: protobuf-net on Phone 7</title><content type="html">&lt;p&gt;Now’s my chance to demonstrate the (pre-alpha) “v2” protobuf-net API, while at the same time showing it working on &lt;a href="http://windowsteamblog.com/blogs/wpdev/archive/2010/04/29/windows-phone-developer-tools-ctp-refresh.aspx"&gt;Phone 7&lt;/a&gt;. In particular, this shows the new pre-compilation functionality, which is vital for good performance on Phone 7, iPhone, XNA, Compact Framework, etc (since they have scant meta-programming).&lt;/p&gt;  &lt;p&gt;But first…&lt;/p&gt;  &lt;h2&gt;Why? Just why?&lt;/h2&gt;  &lt;p&gt;You have a mobile device; data should be considered a limited resource, both in terms of financial cost (data plans etc) and bandwidth-related performance. Therefore we want to send less over the wire.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Google’s protobuf wire-format is &lt;em&gt;extremely &lt;/em&gt;dense. In &lt;em&gt;theory &lt;/em&gt;you can get a few bytes tighter if you squeeze every nibble manually, but you’ll go crazy in the process.&lt;/li&gt;    &lt;li&gt;Mobile devices rarely have full meta-programming; we don’t want reflection (too slow), so we want &lt;em&gt;fully &lt;/em&gt;pre-compiled serializers.&lt;/li&gt;    &lt;li&gt;Code-generation is one option, but most code-gen APIs want you to use &lt;em&gt;their &lt;/em&gt;object model. Thanks very much, but I already &lt;em&gt;have &lt;/em&gt;an object model. I’ll use that, ta.&lt;/li&gt;    &lt;li&gt;Shiny.&lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;Building your domain model&lt;/h2&gt;  &lt;p&gt;You &lt;em&gt;can&lt;/em&gt; use protobuf-net from a .proto (Google’s DSL for describing protobuf schemas), but it is my belief that most .NET developers want to work with their &lt;em&gt;existing&lt;/em&gt; model. So let’s start with a basic model.&lt;/p&gt;  &lt;p&gt;For this demo, I’m starting with a Silverlight library project to represent my model (or it could also be a &lt;a href="http://en.wikipedia.org/wiki/Data_transfer_object"&gt;DTO layer&lt;/a&gt;). There are various ways of setting this up, but this is the simplest while I work out the kinks…&lt;/p&gt;  &lt;p&gt;My model is very basic; just an order header / detail pair. For simplicity I’m using the protobuf-net attributes to allocate field-numbers to the properties, but there are may other ways of doing this now (including support for vanilla objects with no adornments). Here we go; very simple:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_feJtUp7IGuI/S9s9OnhVIyI/AAAAAAAAATQ/bMiqJnyPrSM/s1600-h/image%5B34%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_feJtUp7IGuI/S9s9P1LQqyI/AAAAAAAAATU/7VFhfRQJ-20/image_thumb%5B18%5D.png?imgmax=800" width="442" height="214" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h2&gt;Generating a serialization assembly&lt;/h2&gt;  &lt;p&gt;This is the most obvious difference in “v2”; you can now pre-generate the serialization code into a fully static-typed assembly. The “generate at runtime” model is still supported for “regular” .NET, and has also had a complete overhaul improving performance noticeably.&lt;/p&gt;  &lt;p&gt;“The plan” here is to write a simply utility exe that you can call in your build process to do this step, but I don’t have that complete yet. Instead, just for this demo, I’m going to use “regular” .NET console exe, referencing the “regular” protobuf-net assembly (and the DTO assembly), with an entire 4 lines of code:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_feJtUp7IGuI/S9s9QhWIQkI/AAAAAAAAATY/6CX0wmyWx2g/s1600-h/image%5B38%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_feJtUp7IGuI/S9s9RctBJxI/AAAAAAAAATc/BwwRRsfmhaU/image_thumb%5B20%5D.png?imgmax=800" width="448" height="140" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This tells the API what types we are interested in, and offers a wide range of options for changing how the model is mapped. We’re passing in “true” to let it figure out the details itself.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_feJtUp7IGuI/S9s9SCvbSaI/AAAAAAAAATg/iYgyYgNcYj8/s1600-h/image%5B64%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://lh5.ggpht.com/_feJtUp7IGuI/S9s9STmMPxI/AAAAAAAAATk/cSbuI-QpYHI/image_thumb%5B34%5D.png?imgmax=800" width="154" height="197" /&gt;&lt;/a&gt;Running this exe generates “MySerializer.dll”, which is our serialization assembly with a class “OrderSerializer”. It still needs some utility code from protobuf-net, so in our Phone 7 app we’ll need references to the DTO assembly, the serializer assembly and the Phone 7 version of protobuf-net.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Now all we need to do is use the serializer! In “v1” we would have used static methods on “ProtoBuf.Serializer”, but instead we want to use our specific pre-generated type:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_feJtUp7IGuI/S9s9S11OD5I/AAAAAAAAATo/jfe_spdBjOI/s1600-h/image%5B44%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_feJtUp7IGuI/S9s9TTWx0FI/AAAAAAAAATs/AEtdGyXiip0/image_thumb%5B22%5D.png?imgmax=800" width="244" height="24" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;We also need to create some sample data to play with:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_feJtUp7IGuI/S9s9UAuQRRI/AAAAAAAAATw/58k3i_KfZno/s1600-h/image%5B48%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_feJtUp7IGuI/S9s9Uy5QEGI/AAAAAAAAAT0/xTn4O8i1fwg/image_thumb%5B24%5D.png?imgmax=800" width="359" height="201" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Next, purely for illustration we’ll ignore the handy “DeepClone” method, and serialize / deserialize the object via a MemoryStream:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_feJtUp7IGuI/S9s9Va_6XmI/AAAAAAAAAT4/bUlETxLUnVs/s1600-h/image%5B54%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_feJtUp7IGuI/S9s9WCMT7pI/AAAAAAAAAT8/4Tg-pA1OKHw/image_thumb%5B28%5D.png?imgmax=800" width="308" height="182" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;And because I have extremely limited UI skills, I’ll just throw the cloned data into a ListBox:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_feJtUp7IGuI/S9s9WuB7ptI/AAAAAAAAAUA/vH4-bHOnVro/s1600-h/image%5B58%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_feJtUp7IGuI/S9s9XvS_MQI/AAAAAAAAAUE/CEbOazajk6o/image_thumb%5B30%5D.png?imgmax=800" width="345" height="170" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_feJtUp7IGuI/S9s9YeapQ2I/AAAAAAAAAUI/PC4M6IoAtLQ/s1600-h/image%5B62%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://lh5.ggpht.com/_feJtUp7IGuI/S9s9Y7vGn8I/AAAAAAAAAUM/069WOxbmFXU/image_thumb%5B32%5D.png?imgmax=800" width="145" height="244" /&gt;&lt;/a&gt;Et voila; working protobuf-net serialization via a pre-generated serialization dll, on Phone 7.&lt;/p&gt;  &lt;p&gt;Initial performance tests seem to indicate that it is in the region of 30-50 times faster than the DataContractSerializer that ships with Phone 7, and the protobuf wire format typically takes about 20% of the bandwidth. Win win.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h2&gt;Caveats&lt;/h2&gt;  &lt;p&gt;The “v2” code isn’t complete yet! I’m still working through all the compatibility tests. It is getting there, though. It is a week or so away from a stable beta, I suspect.&lt;/p&gt;  &lt;p&gt;Additionally, I’m still working through some of the issues associated with using “regular” .NET to generate the assembly for a light framework such as CF / Phone 7. Some combinations seem to work better than others.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8184237816669520763-8559749379905883169?l=marcgravell.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/dteSxs2MVTs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/8559749379905883169/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=8559749379905883169" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/8559749379905883169?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/8559749379905883169?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/dteSxs2MVTs/walkthrough-protobuf-net-on-phone-7.html" title="Walkthrough: protobuf-net on Phone 7" /><author><name>Marc Gravell</name><uri>http://www.blogger.com/profile/01023334706549710089</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_feJtUp7IGuI/TA-NNRO9KsI/AAAAAAAAAU4/4a0UAeDCCtI/s1600-R/b4ae7f8b50a2c32287e456394570679e%3Fs%3D128%26d%3Didenticon%26r%3DPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_feJtUp7IGuI/S9s9P1LQqyI/AAAAAAAAATU/7VFhfRQJ-20/s72-c/image_thumb%5B18%5D.png?imgmax=800" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2010/04/walkthrough-protobuf-net-on-phone-7.html</feedburner:origLink></entry></feed>

