<?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:blogger="http://schemas.google.com/blogger/2008" 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;D08HQn06fSp7ImA9WhBVGUo.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763</id><updated>2013-04-26T04:30:33.315-07: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="ikvm" /><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>122</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;DkQFSHc6eyp7ImA9WhBVGU8.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-3778094688159940919</id><published>2013-04-25T14:06:00.001-07:00</published><updated>2013-04-25T14:11:59.913-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-25T14:11:59.913-07:00</app:edited><title>Fun with dynamic - how to build a dynamic object</title><content type="html">&lt;h3&gt;The project: build a redis client&lt;/h3&gt;  &lt;p&gt;The &lt;code&gt;dynamic&lt;/code&gt; feature in C# 4 is powerful when used appropriately. I thought it was about time I wrote a piece on &lt;em&gt;how to do that&lt;/em&gt;. And … because I like &lt;a href="http://redis.io/"&gt;redis&lt;/a&gt; so much I thought it would make a perfect example.&lt;/p&gt;  &lt;p&gt;Now, the observant among you may be thinking “but Marc, you’ve already &lt;a href="https://code.google.com/p/booksleeve/"&gt;written a redis client&lt;/a&gt;” – in which case I agree (and incidentally I congratulate you on getting hyperlinks into speech – no mean feat); but that isn’t the point! This toy client isn’t meant to compete: BookSleeve is heavily optimised to allow really fast and efficient usage. This one is &lt;em&gt;just for fun&lt;/em&gt;. If you like it and it works for you, great! All the code for this is &lt;a href="https://code.google.com/p/simple-redis/"&gt;available on google-code&lt;/a&gt;.&lt;/p&gt;  &lt;h3&gt;What we want&lt;/h3&gt;  &lt;p&gt;I want to be able to do things like:&lt;/p&gt;  &lt;pre&gt;// increment and fetch new&lt;br /&gt;int hitCount = client.incr(&amp;quot;hits&amp;quot;);&lt;br /&gt;// fetch next, if any (else null)&lt;br /&gt;string nextWorkItem = client.lpop(&amp;quot;pending&amp;quot;);&lt;/pre&gt;&lt;p&gt;but without the client knowing &lt;em&gt;anything &lt;/em&gt;about redis except the &lt;a href="http://redis.io/topics/protocol"&gt;binary wire protocol&lt;/a&gt; – those commands are entirely dynamic. Actually a nice advantage of this is that the client doesn’t need to be updated as new redis features are released… but I digress!&lt;/p&gt;&lt;h3&gt;Getting started&lt;/h3&gt;&lt;p&gt;The key in implementing a &lt;code&gt;dynamic&lt;/code&gt; API is implementing &lt;code&gt;IDynamicMetaObjectProvider&lt;/code&gt; – although frankly I don’t propose doing that; I’m just going to subclass &lt;code&gt;DynamicObject&lt;/code&gt; which does a lot of the work for us. So here's our first step:&lt;/code&gt; &lt;/p&gt;&lt;pre&gt;public sealed class RedisClient : DynamicObject, IDisposable {...}&lt;/pre&gt;&lt;p&gt;This gives us the start of a client that will respond to &lt;code&gt;dynamic&lt;/code&gt;; although it doesn't actually &lt;em&gt;do&lt;/em&gt; anything yet - we have to tell our object to handle dynamic method calls, which we do by overriding &lt;code&gt;TryInvokeMember&lt;/code&gt;. Again, keep in mind that this is only a toy, and we’ll do this by simply writing the command name and parameters (in redis format) down the wire, and reading one result in redis format (note that this means that we’ll pay the full latency price per operation, which isn’t ideal – and that we can’t act as a &lt;a href="http://redis.io/topics/pubsub"&gt;redis pub/sub&lt;/a&gt; subscriber – that would simply not work, since replies don’t match neatly to commands then):&lt;/p&gt;&lt;pre&gt;public override bool TryInvokeMember(&lt;br /&gt;    InvokeMemberBinder binder,&lt;br /&gt;    object[] args, out object result)&lt;br /&gt;{&lt;br /&gt;    WriteCommand(binder.Name, args);&lt;br /&gt;    result = ReadResult();&lt;br /&gt;    var err = result as RedisExceptionResult;&lt;br /&gt;    if (err != null) throw err.GetException();&lt;br /&gt;    return true;&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;In particular, note that the name of the method requested is available as &lt;code&gt;binder.Name&lt;/code&gt;, and the parameters are just an &lt;code&gt;object[]&lt;/code&gt;.&lt;/p&gt;&lt;h3&gt;Writing the command&lt;/h3&gt;&lt;p&gt;I won't dwell on the redis protocol details (feel free to read the specification), but &lt;em&gt;basically&lt;/em&gt; we need to write the number of arguments for the command (where the command-name itself counts as an argument), followed by the command-name, followed by each of the parameters. To avoid packet-fragmentation, we’ll use some buffering into a &lt;code&gt;BufferedStream&lt;/code&gt; which we hold in &lt;code&gt;outStream&lt;/code&gt;, which in turn writes to a &lt;code&gt;NetworkStream&lt;/code&gt; which we hold in &lt;code&gt;netStream&lt;/code&gt; - and obviously after each command we need to flush those to ensure they get to the server, so we get:&lt;/p&gt;&lt;pre&gt;private void WriteCommand(string name, object[] args)&lt;br /&gt;{&lt;br /&gt;    WriteRaw(outStream, '*');&lt;br /&gt;    WriteRaw(outStream, 1 + args.Length);&lt;br /&gt;    WriteEndLine();&lt;br /&gt;    WriteArg(name);&lt;br /&gt;    for (int i = 0; i &amp;lt; args.Length; i++)&lt;br /&gt;    {&lt;br /&gt;        WriteArg(args[i]);&lt;br /&gt;    }&lt;br /&gt;    // and make sure we aren't holding onto any data...&lt;br /&gt;    outStream.Flush(); // flushes to netStream&lt;br /&gt;    netStream.Flush(); // just to be sure! (although this is a no-op, IIRC)&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;And for each argument, we need to write the length of the data, followed by the data itself. I won't detail each the various formats for different types of data, but: to avoid having to test &amp;quot;what type of data is this?&amp;quot;, we'll cheat by having a few overloads of a method we'll call &lt;code&gt;WriteRaw&lt;/code&gt;, and use &lt;code&gt;dynamic&lt;/code&gt; to get the runtime to pick between the overloads for us... sneaky:&lt;/p&gt;&lt;pre&gt;private void WriteArg(object value)&lt;br /&gt;{&lt;br /&gt;    // need to know the length, so: write to our memory-stream&lt;br /&gt;    // first&lt;br /&gt;    buffer.SetLength(0);&lt;br /&gt;    WriteRaw(buffer, (dynamic)value);&lt;br /&gt;    // now write that to the (bufferred) output&lt;br /&gt;    WriteRaw(outStream, '$');&lt;br /&gt;    WriteRaw(outStream, (int)buffer.Length);&lt;br /&gt;    WriteEndLine();&lt;br /&gt;    WriteRaw(outStream, new ArraySegment&lt;byte&gt;(buffer.GetBuffer(), 0, (int)buffer.Length));&lt;br /&gt;    WriteEndLine();&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Did you spot the cheeky &lt;code&gt;dynamic&lt;/code&gt; in there? Since we're already in &lt;code&gt;dynamic&lt;/code&gt;-land, it is hard to say that this is going to have any negative impact... so; why not? It means that if I need to support a new data-type, I just add a new &lt;code&gt;WriteRaw&lt;/code&gt; to match, and: job done - and frankly, that's about it for sending the data.&lt;/p&gt;&lt;h3&gt;Reading the response&lt;/h3&gt;&lt;p&gt; After that, we need to refer to the specification again to see what replies look like - it turns out that they're &lt;em&gt;basically&lt;/em&gt; the same format as the outbound data. But we have some ambiguity - does the user want their data as a &lt;code&gt;byte[]&lt;/code&gt;? or as a decoded &lt;code&gt;string&lt;/code&gt;? or maybe they want &lt;code&gt;int&lt;/code&gt;? The nice thing is: we can let them tell us, by providing a result that supports conversions via &lt;code&gt;dynamic&lt;/code&gt; - so when they type:&lt;/p&gt;&lt;pre&gt;byte[] blob = client.get(&amp;quot;my_image&amp;quot;);&lt;br /&gt;string name = client.get(&amp;quot;name&amp;quot;);&lt;/pre&gt;&lt;p&gt;they get the binary and text correctly. So we can subclass &lt;code&gt;DynamicObject&lt;/code&gt; again for a class that holds the raw result, and override another method - &lt;code&gt;TryConvert&lt;/code&gt; this time. We get passed in a different binder, this time with access to the requested type in &lt;code&gt;binder.Type&lt;/code&gt; - which we can then use to unscramble the data accordingly. This implementation is a less interesting and more tedious (testing different matched types), so I’ll leave that out of the blog. The only thing left to do (as shown in the &lt;code&gt;TryInvokeMember&lt;/code&gt;) is to check if the response is an error-message from the server, and turn that into a thrown &lt;code&gt;Exception&lt;/code&gt;, so that it feels intuitively .NET. The reason I can’t do this directly when reading the reply comes down to some implementation details – some replies are themselves composed of multiple &lt;em&gt;nested&lt;/em&gt; replies, and I want to re-use the code internally for reading those. We can’t do that if it throws when hitting an error a few levels down – the stream could be left in an incomplete state (i.e. we might not have finished reading the outer-most reply).&lt;/p&gt;&lt;h3&gt;Summary&lt;/h3&gt;&lt;p&gt;And: that's it! A redis client written from scratch in a little over an hour; but more importantly, a complete &lt;code&gt;dynamic&lt;/code&gt; API illustration. Well, maybe not &lt;em&gt;complete&lt;/em&gt;, but as you can imagine: the other available operations (properties, indexers, operators, etc) work very similarly. I hope it is illustrative. Again, all the code for this is &lt;a href="https://code.google.com/p/simple-redis/"&gt;available on google-code&lt;/a&gt;.&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/-OPF9DKNwNk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/3778094688159940919/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=3778094688159940919" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/3778094688159940919?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/3778094688159940919?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/-OPF9DKNwNk/fun-with-dynamic-how-to-build-dynamic.html" title="Fun with dynamic - how to build a dynamic object" /><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/2013/04/fun-with-dynamic-how-to-build-dynamic.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUcDQXg-eyp7ImA9WhBSGE8.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-4116510528974574016</id><published>2013-02-25T13:14:00.000-08:00</published><updated>2013-02-25T13:17:50.653-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-25T13:17:50.653-08:00</app:edited><title>How many ways can you mess up IO?</title><content type="html">&lt;p&gt;There are so many interesting ways that people find to make a mess of reading binary data, but actually it doesn’t need to be hard. This post is intended to describe some of the more common misunderstandings people have.&lt;/p&gt;  &lt;h3&gt;Text encodings: what they are not&lt;/h3&gt;  &lt;p&gt;Text is simple, right?&lt;/p&gt;  &lt;p&gt;Text encodings are great; you use them (whether you know it or not) all the time, whenever your computer opens any kind of text file, or downloads text (such as the ubiquitous html and json) from the internet. If you don’t know what an encoding is, then first: &lt;a href="http://www.joelonsoftware.com/articles/Unicode.html"&gt;go and read Joel’s treatise on the subject&lt;/a&gt;. No really, go read that and then come back.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-DTSUAmunDGE/USvUp7cC-hI/AAAAAAAAAqI/NE4Ve0wkQ3A/s1600-h/1%25255B2%25255D.jpg"&gt;&lt;img title="1" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: right; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="1" align="right" src="http://lh5.ggpht.com/-95TXx5KA5Ms/USvUqxru0qI/AAAAAAAAAqM/Y6rtNrvDq58/1_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;So now you know: an encoding is a way of working with character data (you know... words etc) over a binary medium (such as a file on disk, or a network socket). Common encodings are things like UTF-8, UTF-7, UTF-16 (in either endian-ness), UTF-32, or “Windows-1252” - however, there is a wide range of encodings available. Some (in particular the UTF-* encodings) can handle most-any unicode character, but many are restricted to the characters used most commonly in a particular locale. Ultimately, an encoding defines a map between characters and bytes, for example defining that “abc” should be represented as the bytes 00-61-00-62-00-63 (and equally, that the bytes 00-61-00-62-00-63 can be interpreted as the text “abc”).&lt;/p&gt;  &lt;p&gt;Here’s the thing an encoding &lt;strong&gt;is not&lt;/strong&gt;: it is &lt;em&gt;not &lt;/em&gt;a way to turn arbitrary bytes into text for storage. You would be amazed how often people try this, but: that simply doesn’t work. If an encoding tries to read something that isn’t text data, then at best: it will throw an error. At worst, it will silently corrupt the data without realizing it has made a mistake. If you want to store arbitrary binary data as text, then there are other tools for that: primarily, things like base-n. In this case, it is the text that is specially formatted. For example, we might need to convey the bytes 07-A2-00-B2-EE-02 using only text.The observant will notice that I’ve just done exactly that using hexadecimal (base-16), but that it took 17 characters (12 without the dashes) to represent just 6 bytes of actual data. A common alternative to reduce this overhead is base-64, which uses characters that avoid the “control characters” likely to cause problems, while also staying in the first range 0-127, which is the most reliable region. Our 6 bytes become “B6IAsu4C” when stored as a base-64 string. Most platforms have utility methods that provide translation to and from base-64.&lt;/p&gt;  &lt;p&gt;The key in choosing between a text-encoding and something like base-64 is simple: all you need to figure out is: which of these two things can have arbitrary contents, and which is required to follow rules (otherwise it is nonsensical)?&lt;/p&gt;  &lt;p&gt;arbitrary* text / rules-based binary: use a text encoding    &lt;br /&gt;arbitrary binary / rules-based text: use base-64 (or similar)&lt;/p&gt;  &lt;p&gt;*=at least, for the characters that the encoding supports, since not every encoding supports every character.&lt;/p&gt;  &lt;p&gt;One last thing to say about encodings: don’t use the “system default” encoding - ever. This goes back to the old days of 8-bit systems where your text console needed a code-page that fitted into a single byte but reached at least most of the characters the user was likely to need. For me, this is &lt;a href="http://en.wikipedia.org/wiki/Windows-1252"&gt;code-page 1252&lt;/a&gt;, but yours may be different. It is exceptionally rare that this is what you want; if in doubt, explicitly specify something like UTF-8. Sometimes you can use byte-order-mark detection, but this is also pretty unreliable - many files omit a BOM. The best answer, obviously, is: define and document what encoding you are planning to use. Then use it.&lt;/p&gt;  &lt;h3&gt;Network packets: what you send is not (usually) what you get&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-KZvY9KrnzN0/USvUrdM9ppI/AAAAAAAAAqY/MphGpoIehYQ/s1600-h/3%25255B2%25255D.jpg"&gt;&lt;img title="3" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; float: left; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="3" align="left" src="http://lh4.ggpht.com/-I8QRjj30oyk/USvUsRaDgwI/AAAAAAAAAqg/zvCM45cCVWA/3_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;TCP usually works as a &lt;em&gt;stream&lt;/em&gt; of data. When you send things, it is usually not guaranteed that it will arrive at the destination in exactly the same chunks that you send. For example, let’s say that     &lt;br /&gt;you try to “send” 3 messages over the same socket using your chosen network library- one with 10 bytes, one with 4 bytes, and one with 8 bytes. You might think that the receiving client can call “read” 3 times and get 10 bytes, 4 bytes and 8 bytes - but it is much more interesting than that. Because it is just a stream, this is simply very unlikely to be what happens. The client could find they get 1 message with 22 bytes. Or 22 messages each with 1 byte. Or any other combination. They could get 10 bytes, 10 bytes, and the last 2 bytes never arrive (because of some network issue). All that TCP guarantees is that whatever portion of the data does make it to the receiver, it will be the correct bytes in the correct order.&lt;/p&gt;  &lt;p&gt;Because of this, if you want to send multiple messages over the same socket it is necessary to implement some kind of “framing” protocol - i.e. some way of splitting the data back into logical pieces at the other end. How you do this is up to you, and often depends on the data being sent. For example, text-based protocols often detect a “sentinel” value to split messages (possibly a carriage return, line-feed, or some other “control character” rarely seen in regular text; the characters with values 0 (“nul”) and 3 (“etx”) are also popular choices.&lt;/p&gt;  &lt;p&gt;If your messages are binary then it is more challenging, as usually there aren’t really any safe “sentinel” bytes to choose from - so commonly some header information is sent before each message that includes (perhaps only includes) the length of the message that follows. This could be as simple as dumping the 4-byte (32-bit) or 8-byte (64-bit) native representation of the length onto the stream (although you also need to decide whether it is “big endian” or “little endian”, obviously). There are also a range of variable-length representations, for when most messages are expected to be small, but the protocol needs to allow for much longer messages. The key thing here is that you must decide how you are going to do this, and clearly document it for consumers. This of course has the unfortunate requirement that you must actually know the length of the data you want to write before you write it - not always convenient. To help with this, some protocols (for example, the more recent web-sockets protocols) allow you to further break down a single message into multiple fragments that the client must stitch back together into a single logical piece - with an additional marker (perhaps a trailing zero-length message, or a special bit set in the header message) to indicate the end of the logical message.&lt;/p&gt;  &lt;h3&gt;Learning to read&lt;/h3&gt;  &lt;p&gt;Most frameworks have a “read” API that looks something like:&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; int read(byte[] buffer, int offset, int count)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-tWVKqdukWD4/USvUtJl0nxI/AAAAAAAAAqk/sk4GmCeiaa8/s1600-h/2%25255B2%25255D.jpg"&gt;&lt;img title="2" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; float: right; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="2" align="right" src="http://lh3.ggpht.com/-B7-H3IEy8Wg/USvUuNAvxDI/AAAAAAAAAqw/KDRJ9Nyb7NI/2_thumb.jpg?imgmax=800" width="244" height="163" /&gt;&lt;/a&gt;(or something appropriately similar for asynchronous access). The point being that you supply a buffer (somewhere for it to put the data), tell it where in that buffer to start writing (often, but not always, 0, and how much data you want it to read. It then goes away and fetches some data for you. Here’s the rub: in most cases, the last parameter is just a maximum - it is not “get this much data”; it is “get at most this much data”. The return value tells you what it could do: this could be non-positive if no more data will ever be available (the stream has ended), it could be count - which is to say: it could fetch all the data you wanted, or it could be any other value greater than zero and less than count. Because of this, reading often involves a loop; for example, let’s say we want to write a method to read an exact number of bytes; me might do that as:&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; void readExact(byte[] buffer, int offset, int count) {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int bytesRead;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if(count &amp;lt; 0) {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new ArgumentOutOfRangeException(“count”);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; while(count != 0 &amp;amp;&amp;amp;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (bytesRead = source.read(buffer, offset, count)) &amp;gt; 0) {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; offset += bytesRead;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; count -= bytesRead;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if(count != 0) throw new EndOfStreamException();     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;  &lt;p&gt;Dissecting that:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;first we check that we aren’t requesting a negative amount of data, which is clearly silly &lt;/li&gt;    &lt;li&gt;then in a loop, we:      &lt;ul&gt;       &lt;li&gt;check to see if we want more data, then try to read at most count more data &lt;/li&gt;        &lt;li&gt;if the stream ends, we break out &lt;/li&gt;        &lt;li&gt;otherwise, we increment out offset, so that if we need to do another read, we don’t over-stamp the data we just fetched) - and decrement count, because we now have less work required &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;finally, we check whether we still have data outstanding, because the stream terminated before we expected to - perhaps raising an error to indicate this &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;   &lt;br /&gt;This is a fairly classic pattern for reading data that shows how to process the number of bytes obtained in each iteration.&lt;/p&gt;  &lt;h3&gt;Gotchas when buffering data in memory&lt;/h3&gt;  &lt;p&gt;Sometimes it isn’t possible to process all the data in a single buffer; in many cases it becomes necessary to use an in-memory store of data that you have received but still need to process (perhaps because you need yet more data before you can make proper sense of it). A common way to do this is to make use of a “memory-stream” - an in-memory object that acts like a stream, but that simply uses local memory rather than a disk or network socket. You basically “write” to the memory-stream until you think you have something you can process, then “read” from it. But did you spot the deliberate mistake? Most memory-streams acts like an old-fashioned VCR: if you record a show, hit “stop”, and then hit “play” - you will find that you are unexpectedly either watching a black screen, or something that you recorded 3 weeks ago. We forgot to rewind it. Essentially, the memory-stream has a single cursor position; after writing the data, the cursor is at the end of the data: what follows is either all zeros, or garbage from the last thing that happened to be in that space. Fortunately, rewinding a memory-stream is usually trivial:&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; stream.Position = 0;&lt;/p&gt;  &lt;p&gt;There’s a second very common confusion with memory-streams; sometimes, after writing to it you want to get the contents, but as a raw buffer (byte[]) rather than as a stream. Often, there are two different APIs for this:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;one which gives you a brand new buffer of the current logical length of the stream, copying the data into the new buffer &lt;/li&gt;    &lt;li&gt;one which hands you the oversized buffer that it is using internally - oversized so that it doesn’t need to allocate a new backing buffer every time you write to it &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;They both have uses; the second is often more efficient, as it avoids an allocation - but it is only useful if you also track the logical length of the data (often via stream.Length or stream.getLength()). To go back to our VCR analogy: one creates a brand new cassette of exactly the 37.5 minutes we recorded, and copies the video - the other simply hands us the existing 180 minute cassette: this is only useful if we also say “the bit you want is the first 37.5 minutes”.&lt;/p&gt;  &lt;h3&gt;Conclusion&lt;/h3&gt;  &lt;p&gt;This isn’t &lt;em&gt;actually&lt;/em&gt; all that complex, but people tend to bring a lot of incorrect preconceptions to the table, which results in the same bugs – over and over and over. So let’s all save some time, and do it right. Please?&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/cuFK5TS1ryg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/4116510528974574016/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=4116510528974574016" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/4116510528974574016?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/4116510528974574016?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/cuFK5TS1ryg/how-many-ways-can-you-mess-up-io.html" title="How many ways can you mess up IO?" /><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/-95TXx5KA5Ms/USvUqxru0qI/AAAAAAAAAqM/Y6rtNrvDq58/s72-c/1_thumb.jpg?imgmax=800" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2013/02/how-many-ways-can-you-mess-up-io.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYFRng8fip7ImA9WhJaGUk.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-8564749491687521019</id><published>2012-10-10T15:29:00.001-07:00</published><updated>2012-10-11T02:18:37.676-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-11T02:18:37.676-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="community" /><category scheme="http://www.blogger.com/atom/ns#" term="redis" /><title>Multiplexed transactions in BookSleeve</title><content type="html">&lt;h3&gt;Short version, for the impatient&lt;/h3&gt;  &lt;p&gt;BookSleeve now has support for transactions using &lt;code&gt;WATCH&lt;/code&gt; and pre-conditions. If you don’t know what BookSleeve or redis is, this won’t be of interest to you.&lt;/p&gt;  &lt;h3&gt;Background&lt;/h3&gt;  &lt;p&gt;We use redis extensively as part of our caching (and a few other things) technologies at Stack Exchange, and as part of doing that efficiently, we put together &lt;a href="http://code.google.com/p/booksleeve/"&gt;BookSleeve&lt;/a&gt;, which is a high-performance multiplexer over a redis connection. In English, what that means is: you can share a single redis connection from lots of different threads, and it will worry about delivering the commands efficiently and shipping results back to the appropriate callers, &lt;strong&gt;without &lt;/strong&gt;200 commands having to pay the penalty of 200 latency. Redis even includes transaction support for complex operations, however, previously I’ve always been a bit stumped how to fit this into BookSleeve…&lt;/p&gt;  &lt;h3&gt;How do transactions work in redis?&lt;/h3&gt;  &lt;p&gt;You see, redis transactions are not like SQL transactions. A transaction is defined by a &lt;code&gt;MULTI&lt;/code&gt; … &lt;code&gt;EXEC&lt;/code&gt; block, with everything between the &lt;code&gt;MULTI&lt;/code&gt; and the &lt;code&gt;EXEC&lt;/code&gt; being processed as a single atomic unit (meaning: redis doesn’t process any requests from other connections during that time - don’t worry if that sounds draconian, redis manages extraordinarily well on a single thread anyway). That’s pretty easy to fit into a multiplexer, as we can just have a structure to buffer up commands, and send them when complete – so that already exists in BookSleeve:&lt;/p&gt;  &lt;pre&gt;using (var tran = conn.CreateTransaction()) &lt;br /&gt;{ &lt;br /&gt;    tran.Strings.Set(0, &amp;quot;foo&amp;quot;, &amp;quot;abc&amp;quot;); &lt;br /&gt;    tran.Strings.Set(0, &amp;quot;bar&amp;quot;, &amp;quot;def&amp;quot;); &lt;br /&gt;    tran.Execute(); &lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;But here’s the gotcha: between the &lt;code&gt;MULTI&lt;/code&gt; and the &lt;code&gt;EXEC&lt;/code&gt;, you &lt;strong&gt;don’t get results&lt;/strong&gt; – you only get results when you commit the transaction. This means that you can’t easily request information in the middle of a transaction and then make a decision on that for what you do next – which makes a lot of sense really, since while you’re doing that thinking and network-IO, &lt;strong&gt;every&lt;/strong&gt; other connection would be stalled. A sane decision really.&lt;/p&gt;&lt;p&gt;To get around this limitation, &lt;a href="http://redis.io/topics/transactions"&gt;redis transactions&lt;/a&gt; actually allow a bit more cleverness… you can issue a &lt;code&gt;WATCH&lt;/code&gt; command against keys of your choice, and then if somebody changes that key, your transaction automatically gets killed. So, a typical cycle might be:&lt;/p&gt;&lt;pre&gt;WATCH SomeKeyName&lt;br /&gt;GET SomeKeyName&lt;br /&gt;{some test on the value back in your client code, then}&lt;br /&gt;MULTI&lt;br /&gt;SET SomeKeyName SomeNewValue&lt;br /&gt;EXEC&lt;br /&gt;{or if you decided you didn't like it after all}&lt;br /&gt;UNWATCH&lt;/pre&gt;&lt;p&gt;And importantly, because of the &lt;code&gt;WATCH&lt;/code&gt;, if another connection comes along and changes &lt;code&gt;SomeKeyName&lt;/code&gt;, then the &lt;code&gt;EXEC&lt;/code&gt; does &lt;strong&gt;nothing&lt;/strong&gt;, and returns a reply that robustly indicates the cancellation. This actually allows a lot of very subtle usage, while allowing everything to happen at the server as a single unit of work.&lt;/p&gt;&lt;h3&gt;So what is the problem? And what did you do?&lt;/h3&gt;&lt;p&gt;The painful bit here is simply: &lt;code&gt;WATCH &lt;/code&gt;doesn’t work in a multiplexer. As soon as one caller issues a &lt;code&gt;WATCH&lt;/code&gt;, either you need to stop accepting work from other callers, or you now have no idea what each caller thinks it is watching (which is very important). Another approach would be to somehow have the user write callbacks that happen as part of a transaction, but what I absolutely don’t want to do is expose anything in BookSleeve that inadvertently allow one caller to break everybody, by being too slow – so callbacks: not really an option. So for a long time, BookSleeve only made use of &lt;code&gt;WATCH &lt;/code&gt;etc internally, and didn’t expose it to the caller. But that has finally changed!&lt;/p&gt;&lt;p&gt;I’ve just committed my first stab at improving this, basically by implementing a number of pre-canned pre-conditions that can be enforced on a transaction. The “pre-canned” is there to avoid the issue of opening up massive performance issues, but in reality they are very simple. For example, a previous internal usage of &lt;code&gt;WATCH&lt;/code&gt; was to take an exclusive lock (by marking a key as in-use). Until today, that was about 100 lines of complex code that needed to know about the full gory details of the redis protocol – where-as now it is just:&lt;/p&gt;&lt;pre&gt;TaskCompletionSource&amp;lt;bool&amp;gt; result = new TaskCompletionSource&amp;lt;bool&amp;gt;();&lt;br /&gt;            &lt;br /&gt;using (var tran = CreateTransaction())&lt;br /&gt;{&lt;br /&gt;    tran.AddCondition(Condition.KeyNotExists(db, key));&lt;br /&gt;    tran.Strings.Set(db, key, value, expirySeconds);&lt;br /&gt;    tran.Execute().ContinueWith(takeLockContinuation);&lt;br /&gt;}&lt;br /&gt;return result.Task;&lt;/pre&gt;&lt;p&gt;where &lt;code&gt;takeLockContinuation&lt;/code&gt; is just a static delegate instance that take the &lt;code&gt;Task&amp;lt;bool&amp;gt;&lt;/code&gt; result from the &lt;code&gt;Execute&lt;/code&gt; call, and sets that into &lt;code&gt;result&lt;/code&gt; (plus handling task faults, cancellation, etc). Crucially, the condition (&lt;code&gt;Condition.KeyNotExists&lt;/code&gt; in this case) takes care of &lt;strong&gt;both&lt;/strong&gt; the &lt;code&gt;WATCH&lt;/code&gt; steps, &lt;em&gt;and&lt;/em&gt; the actual validation / enforcement. Basically, if there are pre-conditions (there can be multiple), then they are all sent to the server, and only if they all return the expected results is the &lt;code&gt;MULTI&lt;/code&gt; / &lt;code&gt;EXEC&lt;/code&gt; block sent – otherwise an &lt;code&gt;UNWATCH&lt;/code&gt; is sent instead. Simple, elegant (IMO), and efficient.&lt;/p&gt;&lt;p&gt;The available pre-conditions are pretty limited at the moment, but I’ll try to add all the obvious ones I can think of (exists/not-exists for keys/hashes, equals/not-equals for keys/hashes, maybe a few inequalities, maybe something involving ttl). But &lt;strong&gt;finally&lt;/strong&gt; I have a &lt;code&gt;WATCH&lt;/code&gt; implementation that isn’t entirely sucky for a multiplexer. At the moment this is in the code repository only; I'll push to NuGet when I have a few more pre-conditions implemented.&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/6JaHsyCdx_I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/8564749491687521019/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=8564749491687521019" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/8564749491687521019?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/8564749491687521019?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/6JaHsyCdx_I/multiplexed-transactions-in-booksleeve.html" title="Multiplexed transactions in 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><thr:total>6</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2012/10/multiplexed-transactions-in-booksleeve.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IMRHs_fSp7ImA9WhJUEE8.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-6389749193598294095</id><published>2012-09-06T06:47:00.001-07:00</published><updated>2012-09-07T05:39:45.545-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-09-07T05:39:45.545-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>Iterator blocks, missing methods, and .NET 4.5</title><content type="html">&lt;p&gt;We had some fun a while ago where we had a flurry of MissingMethodException occurring on some boxes, in particular, complaining that Environment.CurrentManagedThreadId was missing. And sure enough, this is a 4.5 method, and the affected servers were 4.0 – so it was kinda valid, but completely unexpected. At the time, our most pragmatic option was just: deploy 4.5, but we’ve finally had time to go back and understand it!&lt;/p&gt;  &lt;p&gt;This happened after we upgraded our build server to 4.5, for some initial 4.5 usage – but all our core projects were still 4.0 at the time.&lt;/p&gt;  &lt;p&gt;Fix first:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;MAKE SURE YOUR BUILD SERVER HAS THE REFERENCE ASSEMBLIES FOR 4.0!&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;These are typically somewhere like:&lt;/p&gt;  &lt;p&gt;C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0&lt;/p&gt;  &lt;p&gt;Now, the full story:&lt;/p&gt;  &lt;p&gt;fact 1: 4.5 is an in-place over-the-top install on top of 4.0, in the GAC; once you have installed 4.5, 4.0 runs with the 4.5 assemblies&lt;/p&gt;  &lt;p&gt;fact 2: if your build server doesn’t have the reference assemblies, it looks in the GAC – so… once you’ve installed 4.5, it will get 4.5 &lt;em&gt;even if you asked&lt;/em&gt; (in your project) for 4.0&lt;/p&gt;  &lt;p&gt;fact 3: the c# compiler has a detail relating to iterator blocks (aka "yield return" and "yield break") that involves threading, i.e. "which thread am I?"&lt;/p&gt;  &lt;p&gt;fact 4: the implementation for this &lt;strong&gt;changes&lt;/strong&gt; between 4.0 and 4.5; in 4.0, it uses (in the generated iterator-type’s constructor) Thread.CurrentThread.ManagedThreadId – but in 4.5 it uses Environment.CurrentManagedThreadId; it makes this decision based on the framework version it finds it has loaded (taking into account targeting etc)&lt;/p&gt;  &lt;p&gt;Put these pieces together, and you can get a scenario where a 4.0 project that uses 4.0-only methods, &lt;em&gt;seems &lt;/em&gt;to build successfully, but builds in a way that &lt;strong&gt;will only work&lt;/strong&gt; on 4.5; it will &lt;strong&gt;never&lt;/strong&gt; work on 4.0.&lt;/p&gt;  &lt;p&gt;Fun fun fun!&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/7qCPQ7XQ5Hg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/6389749193598294095/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=6389749193598294095" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6389749193598294095?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6389749193598294095?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/7qCPQ7XQ5Hg/iterator-blocks-missing-methods-and-net.html" title="Iterator blocks, missing methods, and .NET 4.5" /><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>6</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2012/09/iterator-blocks-missing-methods-and-net.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAER3o5fyp7ImA9WhJWEk4.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-4144161107343955142</id><published>2012-08-17T12:45:00.001-07:00</published><updated>2012-08-17T13:01:46.427-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-08-17T13:01:46.427-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><category scheme="http://www.blogger.com/atom/ns#" term="metaprogramming" /><title>Taking meta-programming beyond crazy</title><content type="html">&lt;p&gt;Firstly, a brief note that protobuf-net is up to r580 now, on both &lt;a href="http://nuget.org/packages/protobuf-net/2.0.0.580"&gt;nuget&lt;/a&gt; and &lt;a href="http://code.google.com/p/protobuf-net/downloads/list"&gt;google-code&lt;/a&gt;; mainly small tweaks while I build up enough energy to tackle a few larger pieces (some knotty interface / dynamic / base-class improvements are &lt;a href="https://trello.com/board/protobuf-net-road-map/500900581f3aedaf06ded6ca"&gt;next on the list&lt;/a&gt;)&lt;/p&gt;  &lt;h3&gt;Pushing both ends&lt;/h3&gt;  &lt;p&gt;Aimed to time with the .NET 4.5 release (and perhaps more notably, the .NETCore and .NETPortable profiles), I’ve recently spent a &lt;strong&gt;lot&lt;/strong&gt; of time on meta-programming, culminating in the &lt;a href="http://marcgravell.blogspot.co.uk/2012/07/introducing-protobuf-net-precompiler.html"&gt;new precompiler&lt;/a&gt; that allows these slimmed down and highly restrictive frameworks to still have fast serialization (static IL, etc).&lt;/p&gt;  &lt;p&gt;While there, I set myself a silly stretch goal; for the main purpose simply of &lt;em&gt;to see if I could do it&lt;/em&gt; – which was: to get the whole shabang working on .NET 1.1 too. This would give me a fair claim to supporting the &lt;em&gt;entire&lt;/em&gt; .NET framework. So, for a bit of reminiscing – what does that need?&lt;/p&gt;  &lt;h5&gt;Generics&lt;/h5&gt;  &lt;p&gt;Generics were introduced in .NET 2. v1 of protobuf-net made &lt;strong&gt;massive&lt;/strong&gt; usage of generics; so much so that it actually killed the runtime on some platforms (see &lt;a href="http://marcgravell.blogspot.co.uk/2009/05/generics-and-when-not-to.html"&gt;here&lt;/a&gt;, &lt;a href="http://marcgravell.blogspot.co.uk/2008/11/cf-woes.html"&gt;here&lt;/a&gt; and &lt;a href="http://marcgravell.blogspot.co.uk/2009/03/compact-framework-woes-revisted.html"&gt;here&lt;/a&gt;). So removing most of the generics was &lt;em&gt;already&lt;/em&gt; a primary design goal in v2.&lt;/p&gt;  &lt;p&gt;Perhaps the most significant problem I hit here was trying to decide on a core collection type for the internal state. As it turns out, there’s no free lunch here; there is &lt;strong&gt;no&lt;/strong&gt; collection type that is common to all frameworks – some don’t have ArrayList. In the end, I wrote my own simple collection – not just for this, but also because I wanted a collection that was thread-safe for iterations competing with appends (iterators only read what existed when it started iterators).&lt;/p&gt;  &lt;h5&gt;Language&lt;/h5&gt;  &lt;p&gt;You’d be amazed what you miss when you try to design something to compile on down-level compilers. For a dare, go into project-properties, the “Build” tab, and click “Advanced…” – and change the “Language Version” to something like ISO-1 (C# 1.2) or ISO-2 (C# 2.0) – see what breaks. Obviously you expect generics to disappear, but you also lose partial methods, partial classes, iterator blocks, lambdas, extension methods, null-coalescing, static classes, etc – and just some technically legal syntax that the early compilers simply struggle with. protobuf-net is configured to build in ISO-2 in the IDE, but with #if-regions to rip out the last few generics in the .NET 1.1 build. Writing iterator blocks… not fun.&lt;/p&gt;  &lt;h5&gt;Framework&lt;/h5&gt;  &lt;p&gt;There’s a silly number of variances in the core BCL between different frameworks; even things like string.IsNullOrEmpty or StringBuilder.AppendLine() aren’t all-encompassing. I ended up with a utility class with a decent number of methods to hide the differences (behind yet more #if-regions). But by far the craziest problem: reflection. And protobuf-net, at least in “Full” mode (see &lt;a href="http://marcgravell.blogspot.co.uk/2012/07/some-internals-of-protobuf-net.html"&gt;here&lt;/a&gt; for an overview of “CoreOnly” vs “Full”), uses plenty of reflection. Oddly enough, the reflection in .NET 1.1 isn’t bad – sure, it would be nice to have DynamicMethod, but I can live without it. Getting this working on .NET 1.1 was &lt;em&gt;painless&lt;/em&gt; compared to .NETCore.&lt;/p&gt;  &lt;p&gt;Aside / rant: how much do I hate “.GetTypeInfo()” on .NETCore? With the fiery rage of 2 stars slowly crashing into each-other. Oh, I’m sure that the differences to Type / TypeInfo make &lt;em&gt;perfect sense&lt;/em&gt; for application-developers in .NETCore, who probably should be limiting their use of reflection, but for library authors: this change &lt;strong&gt;really, really hurts&lt;/strong&gt;. The one things that lets me keep civil about this change is that in “CoreOnly” + “precompiler” we do all the reflection work up-front using the &lt;strong&gt;regular&lt;/strong&gt; reflection API, so &lt;em&gt;for me at least&lt;/em&gt; most of this ugly is just a cruel artefact. But still: &lt;em&gt;grrrrrrrrrrrrrr&lt;/em&gt;.&lt;/p&gt;  &lt;h5&gt;Opcodes&lt;/h5&gt;  &lt;p&gt;There are a number of opcodes that simply don’t exist back on 1.1; if I’ve done my compare correctly, this is: Unbox_Any, Readonly, Constrained, Ldelem and Stelem. The good news is that most of these exist only to support generics, and are pretty easy to substitute if you know that you aren’t dealing with generics.&lt;/p&gt;    &lt;h5&gt;Metadata Version&lt;/h5&gt;  &lt;p&gt;.NET 1.1 uses an earlier version of the metadata packaging format than all the others use. This is yet another thing that the inbuilt Reflection.Emit can’t help, but - my new favorite metaprogramming tool to the rescue: IKVM.Reflection &lt;em&gt;supports this&lt;/em&gt;. I have to offer yet another thanks to Jeroen Frijters who showed me the correct incantations to make things happy: beyond the basics of IKVM, the key part here is a voodoo call to IKVM’s implementation of AssemblyBuilder:&lt;/p&gt;  &lt;pre&gt;asm.__SetImageRuntimeVersion(&amp;quot;v1.1.4322&amp;quot;, 0x10000);&lt;/pre&gt;&lt;p&gt;The 0x10000 here is a magic number that specifies the .NET 1.1 metadata format. For reference, 0x20000 is the version you want the rest of the time. As always, IKVM.Reflection seems to have considered everything; it is the gold standard of assembly writing tools. Awesome job, Jeroen. I jokingly half-expect to find that &lt;a href="http://blogs.msdn.com/b/visualstudio/archive/2012/06/05/announcing-microsoft-roslyn-june-2012-ctp.aspx"&gt;Roslyn&lt;/a&gt; has a a reference to IKVM.Reflection ;p&lt;/p&gt;&lt;h3&gt;Putting the pieces together&lt;/h3&gt;&lt;p&gt;But! Once you’ve dealt with all those trivial problems; &lt;em&gt;it works&lt;/em&gt;. I’m happy to say that protobuf-net now has “CoreOnly” and “Full” builds, and support from “precompiler”. So if you still have .NET 1.1 applications (and I promise not to judge you… much), you can now use protobuf-net with as many optimizations as it is capable of. Which is cute:&lt;/p&gt;&lt;small&gt; &lt;pre&gt;C:\SomePath&amp;gt;AnotherPath\precompile.exe Net11_Poco.dll -o:MyCrazy.dll -t:MySerializer&lt;br /&gt;&lt;br /&gt;protobuf-net pre-compiler&lt;br /&gt;Detected framework: C:\Windows\Microsoft.NET\Framework\v1.1.4322&lt;br /&gt;Resolved C:\Windows\Microsoft.NET\Framework\v1.1.4322\mscorlib.dll&lt;br /&gt;Resolved C:\Windows\Microsoft.NET\Framework\v1.1.4322\System.dll&lt;br /&gt;Resolved protobuf-net.dll&lt;br /&gt;Adding DAL.DatabaseCompat...&lt;br /&gt;Resolved C:\Windows\Microsoft.NET\Framework\v1.1.4322\System.Xml.dll&lt;br /&gt;Adding DAL.DatabaseCompatRem...&lt;br /&gt;Adding DAL.OrderCompat...&lt;br /&gt;Adding DAL.OrderLineCompat...&lt;br /&gt;Adding DAL.VariousFieldTypes...&lt;br /&gt;Compiling MySerializer to MyCrazy.dll...&lt;br /&gt;All done&lt;br /&gt;&lt;br /&gt;C:\SomePath&amp;gt;peverify MyCrazy.dll&lt;br /&gt;&lt;br /&gt;Microsoft (R) .NET Framework PE Verifier  Version 1.1.4322.573&lt;br /&gt;Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.&lt;br /&gt;&lt;br /&gt;All Classes and Methods in MyCrazy.dll Verified&lt;/pre&gt;&lt;/small&gt;&lt;p&gt;In case it isn’t obvious, “Net11_Poco.dll” is a .NET 1.1 dll created in Visual Studio 2003; “precompiler” has then detected the 1.1-ness, bound IKVM to the .NET 1.1 framework, and compiled a protobuf-net custom serializer for that model, as a legal .NET 1.1 dll.&lt;/p&gt;&lt;h3&gt;Questionable sanity&lt;/h3&gt;&lt;p&gt;Another way of reading all this is: I’ve possibly now crossed the line between “eccentric” and “batshit crazy”. I don’t have a &lt;em&gt;need&lt;/em&gt; to use .NET 1.1, but I would be overjoyed if someone else gets some genuine usage out of this. Mainly, I just wanted to learn some things, challenge myself, and take a bit of professional pride in doing something &lt;em&gt;fully and properly&lt;/em&gt; – just because: I can.&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/KxmWUQkr_o4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/4144161107343955142/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=4144161107343955142" title="12 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/4144161107343955142?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/4144161107343955142?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/KxmWUQkr_o4/taking-meta-programming-beyond-crazy.html" title="Taking meta-programming beyond crazy" /><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>12</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2012/08/taking-meta-programming-beyond-crazy.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEFR3o8eip7ImA9WhJRFEU.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-5446758327228732256</id><published>2012-07-16T16:15:00.001-07:00</published><updated>2012-07-16T16:16:56.472-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-16T16:16:56.472-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" /><category scheme="http://www.blogger.com/atom/ns#" term="metaprogramming" /><title>Introducing the protobuf-net precompiler</title><content type="html">&lt;p&gt;Over the last few posts (&lt;a href="http://marcgravell.blogspot.com/2012/07/some-internals-of-protobuf-net.html"&gt;here&lt;/a&gt; and &lt;a href="http://marcgravell.blogspot.com/2012/07/enter-ikvm.html"&gt;here&lt;/a&gt;) I’ve given a few hints as to compiling for other platforms. Basically, this all relates to how well protobuf-net works on platforms like iOS, WinRT/Metro, Silverlight, Phone 7, etc. These heavily restricted runtimes don’t allow much meta-programming, and they might be running on low-power CPUs, so reflection (even if possible) is not ideal.&lt;/p&gt;  &lt;p&gt;I’ve played with assembly generation before, but with mixed results. For example, &lt;a href="http://marcgravell.blogspot.com/2010/04/walkthrough-protobuf-net-on-phone-7.html"&gt;here for Phone 7&lt;/a&gt;. This could just about work for some frameworks, but was patchy on some, and won’t work at all for others.&lt;/p&gt;  &lt;p&gt;Well, all that IKVM shininess has opened up a whole new set of tools. The small beauty that I’m ridiculously pleased with is a new utility exe in the SVN trunk (will be part of a proper release soon): &lt;em&gt;precompile&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;This unassuming little tool works a bit like “sgen”, but with the ability to target multiple frameworks. What it does is:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;inspect the input assembly (or assemblies) to resolve (if it can) the target framework &lt;/li&gt;    &lt;li&gt;initialize an IKVM universe targeting that framework &lt;/li&gt;    &lt;li&gt;load the core framework libraries, protobuf-net, and the input assemblies into the IKVM universe &lt;/li&gt;    &lt;li&gt;scan the input assemblies for types marked [ProtoContract] &lt;/li&gt;    &lt;li&gt;add those to a protobuf-net model &lt;/li&gt;    &lt;li&gt;compile the model to a type / assembly of your choosing &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;To use that in a project you might:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;create a new DTO project in your chosen framework, and compile it &lt;/li&gt;    &lt;li&gt;execute &lt;em&gt;precompile&lt;/em&gt; to generate to a serializer assembly &lt;/li&gt;    &lt;li&gt;from your application project, reference the DTO and serializer assemblies &lt;/li&gt;    &lt;li&gt;use the type you created &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;For example, say I create a new Phone 7 DTO assembly, called PhoneDto (because it is late and I lack imagination). I can then create a serialization assembly via:&lt;/p&gt;  &lt;pre&gt;precompile {some path}\PhoneDto.dll –o:PhoneSerializer.dll –t:MySerializer&lt;/pre&gt;&lt;p&gt;This will generate a library called PhoneSerializer.dll, which you can reference from your main project (in addition to the DTO and the protobuf-net core).&lt;/p&gt;&lt;p&gt;Then, just use &lt;code&gt;MySerializer&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;var ser = new MySerializer();&lt;br /&gt;ser.Serialize(output, obj);&lt;/pre&gt;&lt;p&gt;I hope this finally solves a number of tooling issues. I’m pretty pleased with it. I’ve tested it against a range of different frameworks, and it has worked well – but if you get problems, just let me know (comment here, or email me, or log an issue on the protobuf-net project site).&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/PXjuGQ7gzPU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/5446758327228732256/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=5446758327228732256" title="22 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/5446758327228732256?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/5446758327228732256?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/PXjuGQ7gzPU/introducing-protobuf-net-precompiler.html" title="Introducing the protobuf-net precompiler" /><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>22</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2012/07/introducing-protobuf-net-precompiler.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUARHk6fip7ImA9WhJREks.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-686713038942443409</id><published>2012-07-14T03:35:00.001-07:00</published><updated>2012-07-14T03:37:25.716-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-14T03:37:25.716-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="reflection" /><category scheme="http://www.blogger.com/atom/ns#" term="serialization" /><category scheme="http://www.blogger.com/atom/ns#" term="protobuf-net" /><category scheme="http://www.blogger.com/atom/ns#" term="ikvm" /><category scheme="http://www.blogger.com/atom/ns#" term="metaprogramming" /><title>Enter the IKVM</title><content type="html">&lt;p&gt;aka Meta-programming and Metro for .NET&lt;/p&gt;  &lt;p&gt;In my &lt;a href="http://marcgravell.blogspot.co.uk/2012/07/some-internals-of-protobuf-net.html"&gt;previous blog entry&lt;/a&gt; I gave an overview of how protobuf-net is arranged internally, and hinted that it all falls apart for Metro. So: what goes wrong? Currently, protobuf-net has a lot (and I do mean a lot) of code built on top of &lt;a href="http://msdn.microsoft.com/en-us/library/system.reflection.emit.ilgenerator.aspx"&gt;ILGenerator&lt;/a&gt;, the reflection class that underpins meta-programming. This class is great for hardcore library builders: you can build individual methods (via &lt;a href="http://msdn.microsoft.com/en-us/library/system.reflection.emit.dynamicmethod.aspx"&gt;DynamicMethod&lt;/a&gt;) or entire assemblies (via &lt;a href="http://msdn.microsoft.com/en-us/library/system.reflection.emit.assemblybuilder.aspx"&gt;AssemblyBuilder&lt;/a&gt;). It is very low level, since you are writing raw IL – but I’m not &lt;em&gt;completely&lt;/em&gt; crazy, so I wrap that up in some utility methods. There are a few problem., though:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;ILGenerator usually expects be be working on the current framework &lt;/li&gt;    &lt;li&gt;Even though you can use a “reflection only load”, this still fails horribly for System.Runtime.dll (aka Metro for .NET) &lt;/li&gt;    &lt;li&gt;In early versions of .NET (and I try to support .NET 2 and upwards), the ability to properly inspect attribute data against reflection-only types/members (&lt;a href="http://msdn.microsoft.com/en-us/library/system.reflection.memberinfo.getcustomattributesdata.aspx"&gt;GetCustomAttributesData&lt;/a&gt;) is simply missing &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So… basically, it all falls to pieces for generating as assembly targeting Metro for .NET, based on a Metro for .NET input assembly.&lt;/p&gt;  &lt;p&gt;What I would &lt;em&gt;need&lt;/em&gt; is some kind of utility that is:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Broadly similar to Reflection.Emit, so I don’t have to rewrite a few thousand lines of code (since I want to keep that code for the runtime meta-programming on full .NET) &lt;/li&gt;    &lt;li&gt;Able to load and work with alternative frameworks without getting confused &lt;/li&gt;    &lt;li&gt;Able to give full attribute information, even on .NET 2 &lt;/li&gt;    &lt;li&gt;Inbuilt or free, to match the existing license &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Who would go to the trouble of writing such a thing?&lt;/h3&gt;  &lt;p&gt;Maybe somebody who is already writing compiler-like tools that aren’t tied to a specific framework, and who has run into the existing limitations of Reflection.Emit? Maybe somebody writing a Java/.NET bridge? Like &lt;a href="http://www.ikvm.net/"&gt;IKVM.NET&lt;/a&gt; ?&lt;/p&gt;  &lt;p&gt;Actually, for my purposes I don’t need most of IKVM. I just need one tiny piece of it: &lt;a href="http://weblog.ikvm.net/PermaLink.aspx?guid=d0dc2476-471b-45f3-96bf-a90bc2f5800b"&gt;IKVM.Reflection&lt;/a&gt;. This library was specifically written to mimic the existing Reflection.Emit API, but without all the problems. In particular, it has a &lt;a href="http://ikvm.cvs.sourceforge.net/viewvc/ikvm/ikvm/reflect/Universe.cs?view=markup"&gt;Universe&lt;/a&gt; class that is a bit like an AppDomain; you load assemblies into a Universe, and that is what is used for resolution etc after that. &lt;a href="http://weblog.ikvm.net/PermaLink.aspx?guid=cc8a8bf9-3451-42cc-8f95-2b201078cb16"&gt;Here’s a simple example&lt;/a&gt; – which will immediately make sense to anyone used to Reflection.Emit – or &lt;a href="http://pastie.org/4254766"&gt;another example specifically targeting Metro for .NET&lt;/a&gt;. The nice thing about the API is that &lt;em&gt;mostly&lt;/em&gt; I can change between IKVM and Reflection.Emit via a simple:&lt;/p&gt;  &lt;pre&gt;#if FEAT_IKVM&lt;br /&gt;using Type = IKVM.Reflection.Type;&lt;br /&gt;using IKVM.Reflection;&lt;br /&gt;#else&lt;br /&gt;using System.Reflection;&lt;br /&gt;#endif&lt;/pre&gt;&lt;p&gt;OK, I would be grossly exaggerating if I claimed that was the &lt;em&gt;only &lt;/em&gt;change I had to make, but that’s the most demonstrable bit. What this means is that &lt;strong&gt;just for my cross-platform compiler&lt;/strong&gt;, everything in the Model, Strategy and Compiler modules (&lt;a href="http://marcgravell.blogspot.co.uk/2012/07/some-internals-of-protobuf-net.html"&gt;see previous blog&lt;/a&gt;) switches to IKVM terminology. The Core still uses System terminology, and the Runtime doesn’t apply (I obviously can’t &lt;em&gt;instantiate/execute &lt;/em&gt;types/methods from another framework, even if I can inspect them).&lt;/p&gt;&lt;p&gt;With this technique, I can now successfully load a Metro for .NET assembly (such as a DTO), and generate a fully static-compiled assembly (“Standalone” on the diagram) targeting Metro for .NET. No reflection at runtime, no nasty hacks – just: an assembly that wasn’t generated by the MS tools.&lt;/p&gt;&lt;p&gt;I’m still working on turning this into a slicker tool (comparable to, say, &lt;a href="http://msdn.microsoft.com/en-us/library/bk3w6240(v=vs.100).aspx"&gt;SGEN&lt;/a&gt;), but a working illustration is in the repo; in particular, see MetroDTO (some sample DTOs), TestIkvm (my proof-of-concept compiler hard-coded to MetroDTO), and Metro_DevRig (which shows the generated assembly working in a Metro for .NET application, including performance comparisons to XmlSerializer and DataContractSerializer).&lt;/p&gt;&lt;p&gt;Additionally, it seems extremely likely that the same tool should be able to write platform-targeted assemblies for Silverlight, Phone 7, XNA, CF, etc. Which is nice.&lt;/p&gt;&lt;h3&gt;Thanks and Acknowledgements&lt;/h3&gt;&lt;p&gt;I’m &lt;em&gt;hugely&lt;/em&gt; indebted to &lt;strong&gt;Jeroen Frijters &lt;/strong&gt;in all of this; both for providing IKVM.Reflection, and for his direct and very prompt assistance when playing with all the above. Mainly for correcting my own brain-dead mistakes, but also for a very quick bug-fix when needed. The library is awesome, thanks.&lt;/p&gt;&lt;p&gt;(as a small caveat, note that protobuf-net is currently exposing a locally built version of IKVM.Reflection; this will be rectified after the next dev build of IKVM)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/16XdaGVURwA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/686713038942443409/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=686713038942443409" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/686713038942443409?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/686713038942443409?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/16XdaGVURwA/enter-ikvm.html" title="Enter the IKVM" /><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/2012/07/enter-ikvm.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YDRH0zcSp7ImA9WhJREUU.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-7005759289637418286</id><published>2012-07-13T05:59:00.001-07:00</published><updated>2012-07-13T06:12:55.389-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-13T06:12:55.389-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>Some internals of protobuf-net</title><content type="html">&lt;p&gt;This post is a bit of background explanation for my next, much more interesting (IMO) post. But in order for that one to make sense without being too long, I wanted to talk about the “what?” and “why?” &lt;em&gt;first&lt;/em&gt;, and then discuss the “how?” after. Make sense?&lt;/p&gt;  &lt;p&gt;First, I’ll whet your appetite with this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-XVO5QZpy43A/UAAbmF_ReaI/AAAAAAAAAcM/jZtg4TPZgEk/s1600-h/image%25255B2%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 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://lh3.ggpht.com/-_RM1xIYcv6Q/UAAbnPrKjqI/AAAAAAAAAcU/DqyPqkM-CDI/image_thumb.png?imgmax=800" width="244" height="237" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This is protobuf-net running nice and fast (much faster than XmlSerializer or DataContractSerializer) on .NET for Metro style apps. Which is a pretty neat trick, because Metro &lt;em&gt;doesn’t allow&lt;/em&gt; any of the usual tricks that protobuf-net uses.&lt;/p&gt;  &lt;p&gt;So what &lt;em&gt;does&lt;/em&gt; it use?&lt;/p&gt;  &lt;h3&gt;A walkthrough of protobuf-net&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-5EKTAo-72BY/UAAbnqJ4mUI/AAAAAAAAAcc/6JcfycoDKs8/s1600-h/image%25255B6%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="left" src="http://lh5.ggpht.com/-F8H3dCWUs54/UAAbosmif_I/AAAAAAAAAck/tYeaV_Ddj4Q/image_thumb%25255B2%25255D.png?imgmax=800" width="167" height="102" /&gt;&lt;/a&gt;The first piece of protobuf-net is the &lt;em&gt;core&lt;/em&gt; – this is basically the fundamental reader/writer API (think: XmlReader/XmlWriter), and some utility methods. Every build of protobuf-net includes the core, although many parts may have different implementations on a per-platform basis.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-zDoL-_MCcOk/UAAbpumHOVI/AAAAAAAAAcs/TCWuv0XP9UE/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; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="left" src="http://lh3.ggpht.com/-fNqz-F7KUYQ/UAAbqUBRRjI/AAAAAAAAAc0/fIxQ397Mb9s/image_thumb%25255B4%25255D.png?imgmax=800" width="166" height="102" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Next we have the model; this is where the user defines the types that are going to be serialized by the model. In many cases, the model is populated automatically as you serialize items (it figures out what is needed). The model doesn’t know how to do anything – it only knows the configuration.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-7d34xINwwyE/UAAbrDyeY6I/AAAAAAAAAc8/LFGb1dz4amU/s1600-h/image%25255B14%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="left" src="http://lh4.ggpht.com/-yfOKCAi8pWE/UAAbsJybwJI/AAAAAAAAAdA/rneCR0CTKz0/image_thumb%25255B6%25255D.png?imgmax=800" width="165" height="101" /&gt;&lt;/a&gt;&lt;/p&gt;          &lt;p&gt;Next comes the strategy; a series of decorators and other structures that turn that configuration into something resembling a sensible way to handle, each configuration, building from simpler steps.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-oyjvSr-D8KU/UAAbsoTC-pI/AAAAAAAAAdI/KKOiypzziLo/s1600-h/image%25255B18%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="left" src="http://lh5.ggpht.com/-wQhGCbswDL4/UAAbtZGrDDI/AAAAAAAAAdQ/gR5pGlI9SMk/image_thumb%25255B8%25255D.png?imgmax=800" width="160" height="98" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;And then given a strategy, we need some mechanism to &lt;em&gt;implement&lt;/em&gt; that strategy. A simple option is &lt;em&gt;reflection&lt;/em&gt;, which is convenient and available on most platforms, but comparatively slow.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-KzY9BoWtIqE/UAAbuPXkzrI/AAAAAAAAAdc/WKAMePtAL1U/s1600-h/image%25255B22%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="left" src="http://lh4.ggpht.com/-jpVoSR_vrKU/UAAbuyjkx4I/AAAAAAAAAdk/FAeRDCF6YqM/image_thumb%25255B10%25255D.png?imgmax=800" width="157" height="96" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;A much more elegant approach is to use meta-programming to turn a strategy into regular IL code. This is pretty complex, but leads to very fast results. Unfortunately, a lot of light-weight platforms do not allow this.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-NBwKaelbtn4/UAAbvuv_RBI/AAAAAAAAAds/acFOE9YmCSg/s1600-h/image%25255B26%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="left" src="http://lh6.ggpht.com/-KGHIBXuOqhc/UAAbwVPg5QI/AAAAAAAAAd0/rLwD-s5Zvg0/image_thumb%25255B12%25255D.png?imgmax=800" width="154" height="95" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Which is a shame, because once you have a working compiler, you can go so far as to generate (via a utility exe at build time) a standalone serialization assembly, which then doesn’t need to do any thinking at runtime.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-tfKF6dgAiNs/UAAbxLQxKZI/AAAAAAAAAd4/3ZRUDVVABhY/s1600-h/image%25255B31%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="left" src="http://lh5.ggpht.com/-seZ9AA7QlGo/UAAbyNNMITI/AAAAAAAAAeE/iwb5fJ6LpX8/image_thumb%25255B15%25255D.png?imgmax=800" width="153" height="100" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In fact, if you do this &lt;em&gt;you don’t even need anything else&lt;/em&gt; – just the core and a serialization assembly. This technique allows you to generate, with a little voodoo, a pair of small assemblies that can be used on platforms such as MonoTouch, &lt;a href="http://www.frictionpointstudios.com/blog/2011/3/31/using-protobuf-net-serialization-in-unity-iphone.html"&gt;as described here&lt;/a&gt;.&lt;/p&gt;  &lt;h3&gt;So you just did that, right? Doesn’t sound too bad…&lt;/h3&gt;  &lt;p&gt;You’d think so, wouldn’t you? Unfortunately, there’s a stumbling block. Generating a standalone assembly is … complex. It only works on full .NET for starters, but also: Reflection.Emit only works with full .NET assemblies. You can’t load your Metro DTO into regular .NET, spin up a TypeBuilder, and run with it; a: you won’t be able to load the types correctly (since your Metro DTO targets an entirely different framework), and b: what you generate won’t be convincing as a Metro dll. We get away with it for MonoTouch, but that is just because the Xamarin folks are evil geniuses.&lt;/p&gt;  &lt;p&gt;What we need, then, is some way of generating a Metro serialization dll, after inspecting a Metro DTO dll, but presumably as a build tool running on regular .NET. &lt;em&gt;That&lt;/em&gt;, as they say, gets tricky. And that is for next time.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/kT0y_UhZqYU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/7005759289637418286/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=7005759289637418286" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/7005759289637418286?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/7005759289637418286?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/kT0y_UhZqYU/some-internals-of-protobuf-net.html" title="Some internals of protobuf-net" /><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/-_RM1xIYcv6Q/UAAbnPrKjqI/AAAAAAAAAcU/DqyPqkM-CDI/s72-c/image_thumb.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2012/07/some-internals-of-protobuf-net.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08BQn8zfyp7ImA9WhVaFU0.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-6257783323822496906</id><published>2012-06-12T04:50:00.001-07:00</published><updated>2012-06-12T04:50:53.187-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-06-12T04:50:53.187-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><title>The question I was asked at DDD South West…</title><content type="html">&lt;p&gt;…about 20 times during and after my last presentation sessions had nothing to do with my content. I am choosing (hoping?) to believe that this is because I articulated myself so clearly and accurately.&lt;/p&gt;  &lt;p&gt;No, the question everyone asked me was:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;What was putting those method-end markers in the IDE?&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;i.e.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-TV2ZErTqyjQ/T9ctGbhbU1I/AAAAAAAAAbs/g-F-Rlmuro4/s1600-h/image%25255B5%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://lh3.ggpht.com/-yxNVq-zS6sM/T9ctHOePJPI/AAAAAAAAAb0/NwOj_QysCro/image_thumb%25255B3%25255D.png?imgmax=800" width="366" height="347" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Well, I didn’t want to mess around with my laptop too much at the event, as I had a re-run session later that day. The first rule of presenting: don’t mess around with your laptop just before you present!&lt;/p&gt;  &lt;p&gt;But – I finally tracked it down; this is &lt;a href="http://vscommands.squaredinfinity.com/features"&gt;VSCommands&lt;/a&gt; “Enable Code Block End Tagger”. It comes with cute options too, for example: to only display the end tag when the start is not visible (which you can see above – no noise is added for the constructor or indexer, since you can see the start and end at the same time).&lt;/p&gt;  &lt;p&gt;It’s a nice tool, and it has VS 2012 support already, apparently (I haven’t had time to test it). Heck, how many IDE tools do you know that have an option to display your stackoverflow reputation and recent activity? (this is not a joke). Or more importantly, has a tool to stop the annoying “drag/drop a file in solution explorer, when I clearly didn’t &lt;em&gt;intend&lt;/em&gt; to totally and utterly shaft the solution” (they call it by a different name, but that’s what I would have called it).&lt;/p&gt;  &lt;p&gt;(anti-disclosure; no I don’t get anything from them for saying that it is a good tool – it just is)&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/iqcPo76TxJc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/6257783323822496906/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=6257783323822496906" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6257783323822496906?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6257783323822496906?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/iqcPo76TxJc/question-i-was-asked-at-ddd-south-west.html" title="The question I was asked at DDD South West…" /><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/-yxNVq-zS6sM/T9ctHOePJPI/AAAAAAAAAb0/NwOj_QysCro/s72-c/image_thumb%25255B3%25255D.png?imgmax=800" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2012/06/question-i-was-asked-at-ddd-south-west.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYDSXs7eCp7ImA9WhRbFUw.&quot;"><id>tag:blogger.com,1999:blog-8184237816669520763.post-6345571859002025960</id><published>2012-02-06T00:30:00.001-08:00</published><updated>2012-02-06T00:32:58.500-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-06T00:32:58.500-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>Abstractions are only a tool; you don’t need to be</title><content type="html">&lt;p&gt;Abstractions abstractions abstractions. &lt;code&gt;IAbstraction&lt;/code&gt; and &lt;code&gt;AbstractionFactory&lt;/code&gt;.&lt;/p&gt;  &lt;p&gt;Ah, joy.&lt;/p&gt;  &lt;p&gt;I get very very confused when I see people saying things like “but it must be done via EF” (substitute EF for &lt;em&gt;any &lt;/em&gt;other tool), when the thing they are trying to do is clearly not suited to the abstraction.&lt;/p&gt;  &lt;p&gt;Abstractions, as tools, are simply a way of reducing the overhead / complexity of doing something specific (managing the relationship between objects and a database in the case of EF). Sometimes they are fairly tight; sometimes &lt;a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html"&gt;they are leaky&lt;/a&gt;. But; to use any abstraction, it is &lt;strong&gt;absolutely critical&lt;/strong&gt; to be aware of two related things:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;where the limits of the abstraction &lt;em&gt;end&lt;/em&gt;&lt;/li&gt;    &lt;li&gt;how the underlying “thing” works&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I get so weary of people using things like EF in the hope that they then “don’t need to learn SQL”. This is a false and destructive aim. You, as a professional developer, wouldn’t try to write a web-page without knowing at least the &lt;em&gt;fundamentals&lt;/em&gt; of html and css? Would you? Really?&lt;/p&gt;  &lt;p&gt;In the same way; occasionally, a tool simply isn’t aimed at the job you want to do. If you want to avoid pain, you need to recognise this &lt;em&gt;as soon as possible&lt;/em&gt;. I’ve seen some horrible horrible ugliness intended to strong-arm an existing tool to do something that it didn’t want to. In most cases, simply using a different tool for that piece (yes, you are allowed to use more than one), or writing the code directly, would have been simpler, less buggy, and wouldn’t take a great big core-dump all over your shiny code. Code matters; don’t contaminate it.&lt;/p&gt;  &lt;p&gt;[end rant]&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeCodeAndMoreCode/~4/nGDM6MVeAdM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marcgravell.blogspot.com/feeds/6345571859002025960/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8184237816669520763&amp;postID=6345571859002025960" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6345571859002025960?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8184237816669520763/posts/default/6345571859002025960?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/CodeCodeAndMoreCode/~3/nGDM6MVeAdM/abstractions-are-only-tool-you-dont.html" title="Abstractions are only a tool; you don’t need to be" /><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>7</thr:total><feedburner:origLink>http://marcgravell.blogspot.com/2012/02/abstractions-are-only-tool-you-dont.html</feedburner:origLink></entry><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;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="33 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>33</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;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="22 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>22</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;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;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;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;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;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;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;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;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="47 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>47</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;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;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;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;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="40 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>40</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;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></feed>
