<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Merbist &#187; Matt Aimonetti</title>
	<atom:link href="http://merbist.com/author/admin/feed/" rel="self" type="application/rss+xml" />
	<link>http://merbist.com</link>
	<description>Random thoughts of a software developer</description>
	<lastBuildDate>Tue, 03 Jan 2012 02:34:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Books to read in 2012 &#8211; recommended to me by Twitter</title>
		<link>http://merbist.com/2011/12/30/books-to-read-in-2012-recommended-to-me-by-twitter/</link>
		<comments>http://merbist.com/2011/12/30/books-to-read-in-2012-recommended-to-me-by-twitter/#comments</comments>
		<pubDate>Fri, 30 Dec 2011 23:28:13 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1215</guid>
		<description><![CDATA[Today, I asked on Twitter what non-technical books I should read in 2012. I was nicely surprised to see so many of my followers send recommendations. Here is a list of 25 books that like-minded people suggested I read. Hopefully you will find a book or two to read too. Feel free to send more recommendations [...]]]></description>
			<content:encoded><![CDATA[<p>Today, I asked on Twitter what non-technical books I should read in 2012.</p>
<p>I was nicely surprised to see so many of my followers send recommendations. Here is a list of 25 books that like-minded people suggested I read. Hopefully you will find a book or two to read too. Feel free to send more recommendations via the comments.</p>
<p>&nbsp;</p>
<table>
<tbody>
<tr>
<td><a href="http://www.amazon.com/gp/product/0307593312/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307593312"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0307593312&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307593312" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0307593312/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307593312" target="_blank">1Q84 by Haruki Murakami</a></td>
<td>suggested by <a title="@mrb_bk" href="https://twitter.com/#!/mrb_bk" target="_blank">@mrb_bk</a> and <a href="https://twitter.com/#!/chadfowler" target="_blank">@chadfowler</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0385240899/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0385240899"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0385240899&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0385240899" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0385240899/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0385240899">The Floating Opera and The End of the Road by John Barth</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0385240899" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@chadfowler" href="https://twitter.com/#!/chadfowler" target="_blank">@chadfowler</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0613663616/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0613663616"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0613663616&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0613663616" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0613663616/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0613663616">Into Thin Air by Jon Krakauer</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0613663616" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@bradly" href="https://twitter.com/#!/bradly" target="_blank">@bradly</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0375714367/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0375714367"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0375714367&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0375714367" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0375714367/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0375714367">Cutting for Stone by Abraham Verghese</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0375714367" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@bradly" href="https://twitter.com/#!/bradly" target="_blank">@bradly</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0452011876/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0452011876"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0452011876&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0452011876" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0452011876/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0452011876">Atlas Shrugged by Ayn Rand</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0452011876" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@bradly" href="https://twitter.com/#!/bradly" target="_blank">@bradly</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0307474720/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307474720"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0307474720&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307474720" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0307474720/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307474720">Cien años de soledad by Gabriel Garcia Marquez</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307474720" alt="" width="1" height="1" border="0" /> (es)</td>
<td>suggested by <a title="@romanandreg" href="https://twitter.com/#!/romanandreg" target="_blank">@romanandreg</a> &amp; <a href="https://twitter.com/#!/jrfernandez" target="_blank">@jrfernandez</a> &amp; <a href="https://twitter.com/#!/edgarschmidt" data-user-id="15151306">@edgarschmidt</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0060883286/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0060883286"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0060883286&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0060883286" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0060883286/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0060883286">One Hundred Years of Solitude by Gabriel García Marquez</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0060883286" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@romanandreg" href="https://twitter.com/#!/romanandreg" target="_blank">@romanandreg</a> &amp; <a href="https://twitter.com/#!/jrfernandez" target="_blank">@jrfernandez</a> &amp; <a href="https://twitter.com/#!/edgarschmidt" data-user-id="15151306">@edgarschmidt</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0553348981/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0553348981"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0553348981&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0553348981" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0553348981/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0553348981">Jitterbug Perfume by Tom Robbins</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0553348981" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@supaspoida" href="https://twitter.com/#!/supaspoida" target="_blank">@supaspoida</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0062041266/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0062041266"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0062041266&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0062041266" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0062041266/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0062041266">The Sisters Brothers by Patrick deWitt</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0062041266" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@dennismajor1" href="https://twitter.com/#!/dennismajor1" target="_blank">@dennismajor1</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0312278497/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0312278497"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0312278497&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0312278497" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0312278497/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0312278497">The Glass Bead Game by Hermann Hesse</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0312278497" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@dj2sincl" href="https://twitter.com/#!/dj2sincl" target="_blank">@dj2sincl</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0679775439/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0679775439"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0679775439&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0679775439" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0679775439/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0679775439">The Wind-Up Bird Chronicle by Haruki Murakami</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0679775439" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@chadfowler" href="https://twitter.com/#!/chadfowler" target="_blank">@chadfowler</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0983873100/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0983873100"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0983873100&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0983873100" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0983873100/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0983873100">Mindfire by Scott Berkun</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0983873100" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@lucasdicioccio" href="https://twitter.com/#!/lucasdicioccio" target="_blank">@lucasdicioccio</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/2226052577/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=2226052577"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=2226052577&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=2226052577" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/2226052577/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=2226052577">Les Fourmis by Bernard Werber</a> (fr)</td>
<td>suggested by <a title="@twitty_tim" href="https://twitter.com/#!/twitty_tim" target="_blank">@twitty_tim</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0375725849/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0375725849"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0375725849&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0375725849" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0375725849/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0375725849">Perfume: The Story of a Murderer by Patrick Suskind</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0375725849" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@twitty_tim" href="https://twitter.com/#!/twitty_tim" target="_blank">@twitty_tim</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/1613820259/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1613820259"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=1613820259&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=1613820259" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/1613820259/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1613820259">Les Miserables by Victor Hugo</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=1613820259" alt="" width="1" height="1" border="0" /> (en, free ebook)</td>
<td>suggested by <a title="@tutec" href="https://twitter.com/#!/tutec" target="_blank">@tutec</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0307292134/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307292134"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0307292134&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307292134" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0307292134/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307292134">Song Of Ice and Fire by George R.R. Martin</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307292134" alt="" width="1" height="1" border="0" /> (Game of Thrones saga)</td>
<td>suggested by <a title="@eeppa" href="https://twitter.com/#!/eeppa" target="_blank">@eeppa</a> &amp; <a href="http://twitter.com/jarin" target="_blank">@jarin</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0765329468/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0765329468"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0765329468&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0765329468" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0765329468/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0765329468">Clockwork Century by Cherie Priest</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0765329468" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@eeppa" href="https://twitter.com/#!/eeppa" target="_blank">@eeppa</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/1590201183/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1590201183"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=1590201183&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=1590201183" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/1590201183/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1590201183">The Darkness that Comes Before by R. Scott Bakker</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=1590201183" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@eeppa" href="https://twitter.com/#!/eeppa" target="_blank">@eeppa</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/B003GAN3VE/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B003GAN3VE"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=B003GAN3VE&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=B003GAN3VE" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/B003GAN3VE/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B003GAN3VE">Drood by Dan Simmons</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=B003GAN3VE" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@eeppa" href="https://twitter.com/#!/eeppa" target="_blank">@eeppa</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0316068225/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0316068225"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0316068225&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0316068225" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0316068225/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0316068225">This Is Water by David Foster Wallace</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0316068225" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@atduskgreg" href="https://twitter.com/#!/atduskgreg" target="_blank">@atduskgreg</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/B005DI71QA/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B005DI71QA"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=B005DI71QA&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=B005DI71QA" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/B005DI71QA/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B005DI71QA">Anathem by Neal Stephenson</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=B005DI71QA" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@jarin" href="https://twitter.com/#!/jarin" target="_blank">@jarin</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0812550706/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0812550706"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0812550706&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0812550706" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0812550706/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0812550706">Ender&#8217;s Game by Orson Scott Card</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0812550706" alt="" width="1" height="1" border="0" /> (entire saga)</td>
<td>suggested by <a title="@jarin" href="https://twitter.com/#!/jarin" target="_blank">@jarin</a> &amp; <a href="https://twitter.com/#!/edgarschmidt" target="_blank" data-user-id="15151306">@edgarschmidt</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/344245302X/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=344245302X"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=344245302X&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=344245302X" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/344245302X/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=344245302X">Snow Crash by Neal Stephenson</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=344245302X" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@jarin" href="https://twitter.com/#!/jarin" target="_blank">@jarin</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/1422171647/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1422171647"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=1422171647&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=1422171647" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/1422171647/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1422171647">Fixing the Game by Roger L. Martin</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=1422171647" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@jarkko" href="https://twitter.com/#!/jarkko" target="_blank">@jarkko</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0307387895/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307387895"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0307387895&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307387895" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0307387895/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307387895">The Road by Cormac McCarthy</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307387895" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@mrreynolds" href="https://twitter.com/#!/mrreynolds" target="_blank">@mrreynolds</a></td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2011/12/30/books-to-read-in-2012-recommended-to-me-by-twitter/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Developing a Curriculum</title>
		<link>http://merbist.com/2011/12/21/developing-a-curriculum/</link>
		<comments>http://merbist.com/2011/12/21/developing-a-curriculum/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 14:57:27 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[education]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1207</guid>
		<description><![CDATA[Recently I asked a friend of mine to give me pointers on how to develop a curriculum (he used to teach an education PHD program), after discussing his response on Twitter, people asked me to put it somewhere, so here it is: Process to develop a curriculum: Purpose. Know why you&#8217;re doing what you&#8217;re doing. [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I asked a friend of mine to give me pointers on how to develop a curriculum (he used to teach an education PHD program), after discussing his response on Twitter, people asked me to put it somewhere, so here it is:</p>
<p>Process to develop a curriculum:</p>
<p><span style="text-decoration: underline;"><strong>Purpose</strong></span>. <em>Know why you&#8217;re doing what you&#8217;re doing.</em></p>
<ul>
<li>You know how to do this.</li>
</ul>
<p><span style="text-decoration: underline;"><strong>Product</strong></span>. <em>Start with the end in mind.</em></p>
<ul>
<li>What does the student look like when they walk out the door at the end of the training.</li>
<li>Usually, we break these down into <strong>Knowledge</strong>, <strong>Skills</strong>, or <strong>Attitudes</strong>.</li>
<li>Sometimes it&#8217;s helpful to see a photograph or drawing of a someone who finished the program and just talk about what they can do that makes them successful.</li>
<li>This &#8220;product&#8221; should be connected and help you accomplish your mission</li>
</ul>
<p><span style="text-decoration: underline;"><strong>Practices</strong></span>. <em>Then ask yourself, &#8220;How do people become like this?&#8221;</em></p>
<ul>
<li>If you can break down your Product into 3-5 bit-sized chunks, then see how people learn each one of those skills, gain each one of those knowledge points, and how to they gain the attitudes you want them to have.</li>
<li>This one is much easier the more experience you have in seeing people develop the &#8220;Product.&#8221;</li>
<li>This is also easier to determine when you understand <a href="http://en.wikipedia.org/wiki/Learning_theory_(education)" target="_blank">Learning Theory</a>.</li>
<li>The results from this section will result in a list of:</li>
<ul>
<li>       Activities or experiences</li>
<li>       Resources. What books, website, teachers, software, etc. will help them learn more effectively and efficiently</li>
<li>       Assessments. How you would know if the activity was helpful?</li>
</ul>
</ul>
<p><span style="text-decoration: underline;"><strong>Plans</strong></span>. <em>Make your plans based on the practices you&#8217;ve determined you&#8217;ve needed.</em></p>
<p>&nbsp;</p>
<p>On a related topic, Chad Fowler posted an interesting <a href="http://chadfowler.com/2011/12/21/re-thinking-software-development-education" target="_blank">blog post about what LivingSocial is doing to change the software development education</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2011/12/21/developing-a-curriculum/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>My RubyConf 2011 talk is online</title>
		<link>http://merbist.com/2011/12/09/my-rubyconf-2011-talk-is-online/</link>
		<comments>http://merbist.com/2011/12/09/my-rubyconf-2011-talk-is-online/#comments</comments>
		<pubDate>Fri, 09 Dec 2011 14:47:59 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[garbage collector]]></category>
		<category><![CDATA[gil]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1203</guid>
		<description><![CDATA[I realize I forgot to mention that my RubyConf talk is now online on the confreaks site (wait until the end, Matz actually answers a question from the audience). I wrote a couple follow up posts you might also be interested in: About concurrency and the GIL Data safety and GIL removal]]></description>
			<content:encoded><![CDATA[<p>I realize I forgot to mention that my RubyConf talk is now online on the <a href="http://confreaks.net/videos/714-rubyconf2011-complex-ruby-concepts-dummified">confreaks site</a> (wait until the end, Matz actually answers a question from the audience).</p>
<p><img class="aligncenter" src="https://img.skitch.com/20111209-pdfksgd2sufg8ywrpnjd4dnru4.jpg" alt="Photo of Matt Aimonetti giving a talk at RubyConf 2011 with one of his slides showing how thread scheduling works" width="653" height="422" /></p>
<p>I wrote a couple follow up posts you might also be interested in:</p>
<ul>
<li><a title="About concurrency and the GIL" href="http://merbist.com/2011/10/03/about-concurrency-and-the-gil/">About concurrency and the GIL</a></li>
<li><a title="Data safety and GIL removal" href="http://merbist.com/2011/10/18/data-safety-and-gil-removal/">Data safety and GIL removal</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2011/12/09/my-rubyconf-2011-talk-is-online/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Data safety and GIL removal</title>
		<link>http://merbist.com/2011/10/18/data-safety-and-gil-removal/</link>
		<comments>http://merbist.com/2011/10/18/data-safety-and-gil-removal/#comments</comments>
		<pubDate>Tue, 18 Oct 2011 23:19:17 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[gil]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1188</guid>
		<description><![CDATA[After my recent RubyConf talk and follow up post addressing the Ruby &#38; Python&#8217;s Global Interpreter Lock (aka GVL/Global VM Lock). a lot of people asked me to explain what I meant by &#8220;data safety&#8221;. While my point isn&#8217;t to defend one approach or the other, I spent a lot of time explaining why C [...]]]></description>
			<content:encoded><![CDATA[<p>After my recent <a title="RubyConf 2011 slides" href="http://rubyconf11.merbist.com" target="_blank">RubyConf talk</a> and <a title="About concurrency and the GIL" href="http://merbist.com/2011/10/03/about-concurrency-and-the-gil/" target="_blank">follow up post addressing the Ruby &amp; Python&#8217;s Global Interpreter Lock</a> (aka GVL/Global VM Lock). a lot of people asked me to explain what I meant by &#8220;data safety&#8221;. While my point isn&#8217;t to defend one approach or the other, I spent a lot of time explaining why C Ruby and C Python use a GIL and where it matters and where it matters less. As a reminder and as mentioned by Matz himself, the main reason why C Ruby still has a GIL is data safety. But if this point isn&#8217;t clear to you, you might be missing the main argument supporting the use of a GIL.</p>
<p>Showing obvious concrete examples of data corruption due to unsafe threaded code isn&#8217;t actually as easy at it sounds. First of all, even with a GIL, developers can write unsafe threaded code. So we need to focus only on the safety problems raised by removing the GIL. To demonstrate what I mean, I will try to create some race conditions and show you the unexpected results you might get. Again, before you go crazy on the comments, remember that threaded code is indeterministic and the code below might potentially work on your machine and that&#8217;s exactly why it is hard to demonstrate. Race conditions depend on many things, but in this case I will focus on race conditions affecting basic data structures since it might be the most surprising.</p>
<h2>Example:</h2>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">@<span style="color:#CC0066; font-weight:bold;">array</span>, threads = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
<span style="color:#006666;">4</span>.<span style="color:#9900CC;">times</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  threads <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#CC00FF; font-weight:bold;">Thread</span>.<span style="color:#9900CC;">new</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">1</span>..<span style="color:#006666;">100</span>_000<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>n<span style="color:#006600; font-weight:bold;">|</span> @<span style="color:#CC0066; font-weight:bold;">array</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> n<span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
threads.<span style="color:#9900CC;">each</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span> t.<span style="color:#9900CC;">join</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#CC0066; font-weight:bold;">puts</span> @<span style="color:#CC0066; font-weight:bold;">array</span>.<span style="color:#9900CC;">size</span></pre></div></div>

<p>In the above example, I&#8217;m creating an instance variable of Array type and I start 4 threads. Each of these threads adds 100,000 items to the array. We then wait for all the threads to be done and check the size of the array.</p>
<p>If you run this code in C Ruby the end result will be as expected:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#006666;">400000</span></pre></div></div>

<p>Now if you switch to JRuby you might be surprised by the output. If you are lucky you will see the following:</p>
<pre>ConcurrencyError: Detected invalid array contents due to unsynchronized modifications with concurrent users
        &lt;&lt; at org/jruby/RubyArray.java:1147
  __file__ at demo.rb:3
      each at org/jruby/RubyRange.java:407
  __file__ at demo.rb:3
      call at org/jruby/RubyProc.java:274
      call at org/jruby/RubyProc.java:233</pre>
<p>This is actually a good thing. JRuby detects that you are unsafely modifying an instance variable across threads and that data corruption will occur. However, the exception doesn&#8217;t always get raised and you will potentially see results such as:</p>
<pre>335467
342397
341080</pre>
<p>This is a sign that the data was corrupted but that JRuby didn&#8217;t catch the unsynchronized modification. On the other hand MacRuby and Rubinius 2 (dev) won&#8217;t raise any exceptions and will just corrupt the data, outputting something like:</p>
<pre>294278
285755
280704
279865</pre>
<p>In other words, if not manually synchronized, shared data can easily be corrupted. You might have two threads modifying the value of the same variable and one of the two threads will step on top of the other leaving you with a race condition. You only need 2 threads accessing the same instance variable at the same time to get a race condition. My example uses more threads and more mutations to make the problem more obvious. Note that TDD wouldn&#8217;t catch such an issue and even extensive testing will provide very little guarantee that your code is thread safe.</p>
<p>&nbsp;</p>
<h2>So what? Thread safety isn&#8217;t a new problem.</h2>
<p>That&#8217;s absolutely correct, ask any decent Java developer out there, he/she will tell how locks are used to &#8220;easily&#8221; synchronize objects to make your code thread safe. They might also mention the deadlocks and other issues related to that, but that&#8217;s a different story. One might also argue that when you write web apps, there is very little shared data and the chances of corrupting data across concurrent requests is very small since most of the data is kept in a shared data store outside of the process.</p>
<p>All these arguments are absolutely valid, the challenge is that you have a large community and a large amount of code out there that expects a certain behavior. And removing the GIL does change this behavior. It might not be a big deal for you because you know how to deal with thread safety, but it might be a big deal for others and C Ruby is by far the most used Ruby implementation. It&#8217;s basically like saying that automatic cars shouldn&#8217;t be made and sold, and everybody has to switch to stick shifts. They have better gas mileage, I personally enjoy driving then and they are cheaper to build. Removing the GIL is a bit like that. There is a cost associated with this decision and while this cost isn&#8217;t insane, the people in charge prefer to not pay it.</p>
<p>&nbsp;</p>
<h2>Screw that, I&#8217;ll switch to Node.js</h2>
<p>I heard a lot of people telling me they were looking into using Node.js because it has a better design and no GIL. While I like Node.js and if I were to implement a chat room or an app keeping connections for a long time, I would certainly compare it closely to EventMachine, I also think that this argument related to the GIL is absurd. First, you have other Ruby implementations which don&#8217;t have a GIL and are really stable (i.e: JRuby) but then Node basically works the same as Ruby with a GIL. Yes, Node is evented and single threaded but when you think about it, it behaves the same as Ruby 1.9 with its GIL. Many requests come in and they are handled one after the other and because IO requests are non-blocking, multiple requests can be processed concurrently but not in parallel. Well folks, that&#8217;s exactly how C Ruby works too, and unlike popular believe, most if not all the popular libraries making IO requests are non blocking (when using 1.9). So, next time you try to justify you wanting to toy with Node, please don&#8217;t use the GIL argument.</p>
<p>&nbsp;</p>
<h2>What should I do?</h2>
<p>As always, evaluate your needs and see what makes sense for your project. Start by making sure you are using Ruby 1.9 and your code makes good use of threading. Then look at your app and how it behaves, is it CPU-bound or IO-bound. Most web apps out there are IO-bound (waiting for the DB, redis or API calls), and when doing an IO call, Ruby&#8217;s GIL is released allowing another thread to do its work. In that case, not having a GIL in your Ruby implementation won&#8217;t help you. However, if your app is CPU-bound, then switching to JRuby or Rubinius might be beneficial. However, don&#8217;t assume anything until you proved it and remember that making such a change will more than likely require some architectural redesign, especially if using JRuby.  But, hey, it might totally be worth it as many proved it in the past.</p>
<p>&nbsp;</p>
<p>I hope I was able to clarify things a bit further. If you wish to dig further, I would highly recommend you read the many discussions the Python community had in the last few years.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2011/10/18/data-safety-and-gil-removal/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>About management</title>
		<link>http://merbist.com/2011/10/11/about-management/</link>
		<comments>http://merbist.com/2011/10/11/about-management/#comments</comments>
		<pubDate>Wed, 12 Oct 2011 06:53:40 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1173</guid>
		<description><![CDATA[I decided to save myself a session to the shrink and instead just write down my reflection on management. Who knows, some of you might help me and/or challenge my thought process. I recently read a great management book called the five dysfunctions of a team by Patrick Lencioni . Instead of telling you what [...]]]></description>
			<content:encoded><![CDATA[<p>I decided to save myself a session to the shrink and instead just write down my reflection on management. Who knows, some of you might help me and/or challenge my thought process.</p>
<p>I recently read a great management book called the <a title="5 dysfunctions of a team" href="https://www.amazon.com/dp/B000UCUX0K/ref=as_li_ss_til?tag=merbist-20&amp;camp=213381&amp;creative=390973&amp;linkCode=as4&amp;creativeASIN=B000UCUX0K&amp;adid=0BP6N5GHZD0EW2N7QVZR&amp;" target="_blank">five dysfunctions of a team by Patrick Lencioni</a> . Instead of telling you what to do, the author highlights behavior patterns that are related to each other and when aggregated result in dysfunctional teams. I really liked the book because instead of a being a cookbook/playbook, this is more a fail book, in other words, it illustrates what you don&#8217;t want to do and explains why. It highlights very well the relation between various behaviors and nicely illustrates why teams of brilliant people can fail. The <a href="https://www.amazon.com/dp/B000UCUX0K/ref=as_li_ss_til?tag=merbist-20&amp;camp=213381&amp;creative=390973&amp;linkCode=as4&amp;creativeASIN=B000UCUX0K&amp;adid=0BP6N5GHZD0EW2N7QVZR&amp;" target="_blank">Kindle version is at less than $5, go get it</a> and read it on your iPhone/iPad/computer/browser…</p>
<div style="margin-left: 50%;"><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&#038;bc1=000000&#038;IS2=1&#038;bg1=FFFFFF&#038;fc1=000000&#038;lc1=0000FF&#038;t=merbist-20&#038;o=1&#038;p=8&#038;l=as4&#038;m=amazon&#038;f=ifr&#038;ref=ss_til&#038;asins=B000UCUX0K" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe></div>
<p>So this book somewhat changed my perception of management and leadership. Interesting enough, at Sony, my previous employer, they make a distinction between management and leadership. While they hope managers can be leaders, they don&#8217;t require them to be and to be honest very few are. I&#8217;m not sure that&#8217;s a good or a bad things, but I, for sure, was under different expectations. Finally, I spent a large amount of my life on the internet working on/with projects where meritocracy, respect and honor were key. The &#8220;ranking&#8221; is purely based on what your peers think of you and not based on your age/sex/origin/diploma/bank account. I do realize that this model has many pros but also some pretty major cons. My only point is that it did affect my worldview. In my world, seniority, a killer  job title or a fancy suit won&#8217;t buy you my automatic respect. On the other hand, job well done, great vision, honesty, over achievement will!</p>
<p>Taking these few trains of thoughts in consideration, I started thinking about my own expectations for a good manager/leader. I figured that if I were able to do that, I could possibly be able to define a work environment where I could thrive and maybe one day become a good &#8220;manager/leader&#8221;.</p>
<p>I&#8217;ve always questioned my ability to be a good leader. While most of the time, I have an opinion and can easily decide what I think should be done, I have a hard time relating to people who can&#8217;t see the &#8220;big picture&#8221;. While I usually can get decent results, I&#8217;m aware that it can unfortunately sometime be at the cost of a few bruised egos. I also know I have high expectations for myself and for others and I have a hard time understanding how some people can be ok with the &#8220;status-quo&#8221;. I&#8217;m a perfectionist who is only happy when he outperforms his previous achievement. I was raised to challenge and always push myself further, focusing on concrete end-results and achieved goals. And to be honest, that&#8217;s what I enjoy. But I also know for a fact, that many people are not like that and I can&#8217;t blame them for looking at things from a different angle and not sharing the same motivations. Furthermore, I know that most people actually don&#8217;t have the same driven temperament and that&#8217;s why I&#8217;ve questioned my abilities to lead others.</p>
<p>However, different temperaments can work together as long as there is respect. And by respect, I mean that everyone feel that they were being heard and know that their input was considered and addressed even though the outcome might not be as hoped for. But for respect to happen, you first need trust. And when people trust each other, Lencioni explains that <em>&#8220;people don&#8217;t hold back one with another. They are unafraid to air their dirty laundry. They admit their mistakes, their weaknesses, and their concerns without fear of reprisal&#8221;</em>. I think that as simple as it seems, it is the key to a successful team. A good leader should be able to create such an atmosphere where people can trust each other. In fact, I think that if a manger/leader/executive can manage to build trust as defined earlier, his technical skills or lack of vision don&#8217;t matter as much. He/she will be able to rely on people he trusts to help him make the right decisions. Of course, there is much more than to be a good leader, but I think that with this base, great things can be built, and without it, a much greater effort is required to get some good results.</p>
<p>Based on my findings, I think that I need to work on my communication so others don&#8217;t feel that they have to hold back and make sure everyone feels that their opinions were considered and addressed. To do that a key element is to admit my mistakes and weaknesses and asking others to help me improve. That&#8217;s it, sorry for the boring, not technical post. I promise the next one will have at least a code sample.</p>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2011/10/11/about-management/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>About concurrency and the GIL</title>
		<link>http://merbist.com/2011/10/03/about-concurrency-and-the-gil/</link>
		<comments>http://merbist.com/2011/10/03/about-concurrency-and-the-gil/#comments</comments>
		<pubDate>Tue, 04 Oct 2011 05:23:54 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[fibers]]></category>
		<category><![CDATA[gil]]></category>
		<category><![CDATA[jruby]]></category>
		<category><![CDATA[macruby]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[rubinius]]></category>
		<category><![CDATA[rubyconf]]></category>
		<category><![CDATA[threads]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1146</guid>
		<description><![CDATA[During RubyConf 2011, concurrency was a really hot topic. This is not a new issue, and the JRuby team has been talking about true concurrency for quite a while . The Global Interpreter Lock has also been in a subject a lot of discussions in the Python community and it&#8217;s not surprising that the Ruby [...]]]></description>
			<content:encoded><![CDATA[<p>During RubyConf 2011, concurrency was a really hot topic. This is not a new issue, and the JRuby team has been talking about true concurrency for quite a while . The Global Interpreter Lock has also been in a subject a<a href="http://wiki.python.org/moin/GlobalInterpreterLock" target="_blank"> lot of discussions in the Python community</a> and it&#8217;s not surprising that the Ruby community experiences the same debates since the evolution of their implementations are somewhat similar. (There might also be some tension between <a href="http://engineyard.com" target="_blank">EngineYard</a> hiring the JRuby and Rubinius teams and <a href="http://heroku.com" target="_blank">Heroku</a> which <a href="http://blog.heroku.com/archives/2011/7/12/matz_joins_heroku/" target="_blank">recently hired Matz</a> (Ruby&#8217;s creator) and <a href="https://github.com/nobu" target="_blank">Nobu</a>, the #1 C Ruby contributor)</p>
<p>The GIL was probably even more of a hot topic now that <a href="http://rubini.us/" target="_blank">Rubinius</a> is about the join <a href="http://jruby.org" target="_blank">JRuby</a> and <a href="http://macruby.org" target="_blank">MacRuby</a> in the realm of GIL-less Ruby implementations.</p>
<p>During my RubyConf talk (<a href="http://rubyconf11.merbist.com/">slides here</a>), I tried to explain how C Ruby works and why some decisions like having a GIL were made and why the Ruby core team isn&#8217;t planning on removing this GIL anytime soon. The GIL is something a lot of Rubyists love to hate, but a lot of people don&#8217;t seem to question why it&#8217;s here and why Matz doesn&#8217;t want to remove it. Defending the C Ruby decision isn&#8217;t quite easy for me since I spend my free time working on an alternative Ruby implementation which doesn&#8217;t use a GIL (MacRuby). However, I think it&#8217;s important that people understand why the MRI team (C Ruby team) and some Pythonistas feels so strongly about the GIL.</p>
<p><strong>What is the GIL?</strong></p>
<p>Here is a quote from the <a href="http://wiki.python.org/moin/GlobalInterpreterLock" target="_blank">Python wiki</a>:</p>
<blockquote><p>In CPython, the <strong>global interpreter lock</strong>, or <strong>GIL</strong>, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython&#8217;s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.) [...] The GIL is controversial because it prevents multithreaded CPython programs from taking full advantage of multiprocessor systems in certain situations. Note that potentially blocking or long-running operations, such as I/O, image processing, and <a href="http://wiki.python.org/moin/NumPy">NumPy</a> number crunching, happen <em>outside</em> the GIL. Therefore it is only in multithreaded programs that spend a lot of time inside the GIL, interpreting CPython bytecode, that the GIL becomes a bottleneck.</p></blockquote>
<p>The same basically applies to C Ruby. To illustrate the quote above, here is a diagram representing two threads being executed by C Ruby:</p>
<p style="text-align: center;"><a href="http://rubyconf11.merbist.com/#44"><img class="aligncenter" title="Ruby fair thread scheduling" src="http://rubyconf11.merbist.com/images/thread_scheduling.023.jpg" alt="" width="614" height="461" /></a></p>
<p>Such a scheduling isn&#8217;t a problem at all when you only have 1 cpu, since a cpu can only execute a piece of code at a time and context switching happens all the time to allow the machine to run multiple processes/threads in parallel. The problem is when you have more than 1 CPU because in that case, if you were to only run 1 Ruby process, then you would most of the time only use 1 cpu at a time. If you are running on a 8 cpu box, that&#8217;s not cool at all! A lot of people stop at this explanation and imagine that their server can only handle one request at a time and they they rush to sign Greenpeace petitions asking Matz to make Ruby greener by optimizing Ruby and saving CPU cycles. Well, the reality is slightly different, I&#8217;ll get back to that in a minute. Before I explain &#8220;ways to achieve true concurrency with CRuby, let me explain why C Ruby uses a GIL and why each implementation has to make an important choice and in this case both CPython and C Ruby chose to keep their GIL.</p>
<p>&nbsp;</p>
<h3>Why a GIL in the first place?</h3>
<ul>
<li>It makes developer&#8217;s lives easier (it&#8217;s harder to corrupt data)</li>
<li>It avoids race conditions within C extensions</li>
<li>It makes C extensions development easier (no write barriers..)</li>
<li>Most of the C libraries which are wrapped are not thread safe</li>
<li>Parts of Ruby&#8217;s implementation aren&#8217;t threadsafe (Hash for instance)</li>
</ul>
<div>As you can see the arguments can be organized in two main categories: data safety and C extensions/implementation. An implementation which doesn&#8217;t rely too much on C extensions (because they run a bit slow, or because code written in a different language is preferred) is only faced with one argument: data safety.</div>
<p>&nbsp;</p>
<h3></h3>
<h3>Should C Ruby remove its GIL?</h3>
<ul>
<li>No: it potentially makes Ruby code unsafe(r)</li>
<li>No: it would break existing C extensions</li>
<li>No: it would make writing C extensions harder</li>
<li>No: it&#8217;s a lot of work to change make C Ruby threadsafe</li>
<li>No: Ruby is fast enough in most cases</li>
<li>No: Memory optimization and GC is more important to tackle first</li>
<li>No: C Ruby code would run slower</li>
<li>Yes: we really need better/real concurrency</li>
<li>Yes: <a href="https://plus.google.com/107994348420168435683/posts/993U42yVbfk" target="_blank">Rubber boots analogy (Gustavo Niemeyer)</a></li>
</ul>
<div>Don&#8217;t count the amount of pros/cons to jump to the conclusion that removing the GIL is a bad idea. A lot of the arguments for removing the GIL are related. At the end of the day it boils down to data safety. During the Q&amp;A section of my RubyConf talk, Matz came up on stage and said data safety was the main reason why C Ruby still has a GIL. Again, this is a topic which was discussed at length in the Python community and I&#8217;d encourage you to read arguments from the <a href="http://www.jython.org/" target="_blank">Jython</a> (the equivalent of JRuby for Python) developers, <a href="http://codespeak.net/pypy/dist/pypy/doc/faq.html#does-pypy-have-a-gil-why" target="_blank">the PyPy</a> (the equivalent of Rubinius in the Python community) and CPython developers. (a good collection of arguments are actually available in the comments related to the <a href="https://plus.google.com/107994348420168435683/posts/993U42yVbfk" target="_blank">rubber boots post mentioned earlier</a>)</div>
<p>&nbsp;</p>
<h3>How can true concurrency be achieved using CRuby?</h3>
<div>
<ul>
<li>Run multiple processes (which you probably do if you use Thin, Unicorn or Passenger)</li>
<li>Use event-driven programming with a process per CPU</li>
<li>MultiVMs in a process. Koichi presented his plan to run multiple VMs within a process.  Each VM would have its own GIL and inter VM communication would be faster than inter process. This approach would solve most of the concurrency issues but at the cost of memory.</li>
</ul>
<div>Note:  forking a process only saves memory when using REE since it implements a GC patch that makes the forking process Copy on Write friendly. The Ruby core team worked on a patch for Ruby 1.9 to achieve the same result. <a href="http://twitter.com/#!/nari_en" target="_blank">Nari</a> &amp; <a href="http://twitter.com/#!/yukihiro_matz" target="_blank">Matz</a> are currently working on improving the implementation to make sure overall performance isn&#8217;t affected.</div>
</div>
<p>Finally, when developing web applications, each thread spend quite a lot of time in IOs which, as mentioned above won&#8217;t block the thread scheduler. So if you receive two quasi-concurrent requests you might not even be affected by the GIL as illustrated in <a href="http://yehudakatz.com/2010/08/14/threads-in-ruby-enough-already/" target="_blank">this diagram from Yehuda Katz</a>:</p>
<p><img class="aligncenter" title="rails threads" src="http://yehudakatz.com/wp-content/uploads/2010/08/Untitled.002.png" alt="" width="768" height="432" /></p>
<p>This is a simplified diagram but you can see that a good chunk of the request life cycle in a Ruby app doesn&#8217;t require the Ruby thread to be active (CPU Idle blocks) and therefore these 2 requests would be processed almost concurrently.</p>
<div>
<p>To boil it down to something simplified, when it comes to the GIL, an implementor has to chose between data safety and memory usage. But it is important to note that context switching between threads is faster than context switching between processes and data safety can and is often achieved in environments without a GIL, but it requires more knowledge and work on the developer side.</p>
<p>&nbsp;</p>
<h3>Conclusion</h3>
<div>The decision to keep or remove the GIL is a bit less simple that it is often described. I respect Matz&#8217; decision to keep the GIL even though, I would personally prefer to push the data safety responsibility to the developers. However, I do know that many Ruby developers would end up shooting themselves in the foot and I understand that Matz prefers to avoid that and work on other ways to achieve true concurrency without removing the GIL. What is great with our ecosystem is that we have some diversity, and if you think that a GIL less model is what you need, we have some great alternative implementations that will let you make this choice. I hope that this article will help some Ruby developers understand and appreciate C Ruby&#8217;s decision and what this decision means to them on a daily basis.</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2011/10/03/about-concurrency-and-the-gil/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>How to &#8211; cross domain ajax to a Ruby app</title>
		<link>http://merbist.com/2011/09/14/how-to-cross-domain-ajax-in-a-ruby-app/</link>
		<comments>http://merbist.com/2011/09/14/how-to-cross-domain-ajax-in-a-ruby-app/#comments</comments>
		<pubDate>Thu, 15 Sep 2011 00:11:41 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[html5]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1133</guid>
		<description><![CDATA[In some cases, you might have a bunch of apps running on different domains/subdomains and/or ports and you would like to make ajax requests between these services. The problem is that browsers wouldn&#8217;t let you make such requests because of the Same Origin Policy which only allowed them to make request to resources within the same domain. [...]]]></description>
			<content:encoded><![CDATA[<p>In some cases, you might have a bunch of apps running on different domains/subdomains and/or ports and you would like to make ajax requests between these services. The problem is that browsers wouldn&#8217;t let you make such requests because of the Same Origin Policy which only allowed them to make request to resources within the same domain.</p>
<p>However, most browsers (IE 8+, Firefox 3.5+, Safari 4+, Chrome) implement a simple way to allow cross domain requests as defined in this <a href="http://www.w3.org/TR/cors/">w3C document</a>.</p>
<p>Of course, if your users have an old version of their browser, you  might have to look into jsonp or something else such as cheating by using iframes &amp; setting document.domain. Let&#8217;s pretend for a minute that 100% of your users are on Chrome. The only thing you need to do is set a response header listing the accepted domains or &#8220;*&#8221; for all. A simple Rack middleware to do that would look like that.</p>
<p>&nbsp;</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> XOriginEnabler
  ORIGIN_HEADER = <span style="color:#996600;">&quot;Access-Control-Allow-Origin&quot;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>app, accepted_domain=<span style="color:#996600;">&quot;*&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@app</span> = app
    <span style="color:#0066ff; font-weight:bold;">@accepted_domain</span> = accepted_domain
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> call<span style="color:#006600; font-weight:bold;">&#40;</span>env<span style="color:#006600; font-weight:bold;">&#41;</span>
    status, header, body = <span style="color:#0066ff; font-weight:bold;">@app</span>.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span>env<span style="color:#006600; font-weight:bold;">&#41;</span>
    header<span style="color:#006600; font-weight:bold;">&#91;</span>ORIGIN_HEADER<span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#0066ff; font-weight:bold;">@accepted_domain</span>
    <span style="color:#006600; font-weight:bold;">&#91;</span>status, header, body<span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>And to use the middleware you would need to set it for use:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">use XOriginEnabler</pre></div></div>

<p>To enable all requests from whatever origin, or pass the white listed domain(s) as shown below.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">use XOriginEnabler, <span style="color:#996600;">&quot;demo.mysite.com demo.mysite.fr demo.techcrunch.com&quot;</span></pre></div></div>

<p>For a full featured middleware, see <a href="https://github.com/cyu/rack-cors">this project</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2011/09/14/how-to-cross-domain-ajax-in-a-ruby-app/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Ruby optimization example and explanation</title>
		<link>http://merbist.com/2011/09/05/ruby-optimization-example-and-explaination/</link>
		<comments>http://merbist.com/2011/09/05/ruby-optimization-example-and-explaination/#comments</comments>
		<pubDate>Mon, 05 Sep 2011 22:58:21 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[scalability]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1124</guid>
		<description><![CDATA[Recently I wrote a small DSL that allows the user to define some code that then gets executed later on and in different contexts. Imagine something like Sinatra where each route action is defined in a block and then executed in context of an incoming request. The challenge is that blocks come with their context and [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I wrote a small DSL that allows the user to define some code that then gets executed later on and in different contexts. Imagine something like Sinatra where each route action is defined in a block and then executed in context of an incoming request.</p>
<p>The challenge is that blocks come with their context and you can&#8217;t execute a block in the context of another one.</p>
<p>Here is a reduction of the challenge I was trying to solve:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> SolutionZero
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>origin, <span style="color:#006600; font-weight:bold;">&amp;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@origin</span> = origin
    <span style="color:#0066ff; font-weight:bold;">@block</span> = block
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> dispatch
    <span style="color:#0066ff; font-weight:bold;">@block</span>.<span style="color:#9900CC;">call</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
SolutionZero.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">42</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#0066ff; font-weight:bold;">@origin</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006666;">1</span> <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">dispatch</span>
<span style="color:#008000; font-style:italic;"># undefined method `+' for nil:NilClass (NoMethodError)</span></pre></div></div>

<p>The problem is that the block refers to the @origin instance variable which is not available in its context.<br />
My first workaround was to use instance_eval:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> SolutionOne
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>origin, <span style="color:#006600; font-weight:bold;">&amp;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@origin</span> = origin
    <span style="color:#0066ff; font-weight:bold;">@block</span> = block
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> dispatch
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">instance_eval</span> <span style="color:#006600; font-weight:bold;">&amp;</span>@block
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
SolutionOne.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">40</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#0066ff; font-weight:bold;">@origin</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">dispatch</span>
<span style="color:#008000; font-style:italic;"># 42</span></pre></div></div>

<p>My workaround worked fine, since the block was evaluated in the context of the instance and therefore the @origin ivar is made available to block context. Technically, I was good to go, but I wasn&#8217;t really pleased with this solution. First using instance_eval often an indication that you are trying to take a shortcut. Then having to convert my block stored as a block back into a proc every single dispatch makes me sad. Finally, I think that this code is probably not performing as well as it could, mainly due to unnecessary object allocations and code evaluation.<br />
I did some benchmarks replacing <a title="instance_eval" href="https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1323" target="_blank">instance_eval</a> by <a title="instance_exec" href="https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1355" target="_blank">instance_exec</a> since looking at the C code, instance_exec should be slightly faster. Turns out, it is not so I probably missed something when reading the implementation code.</p>
<p>I wrote some more benchmarks and profiled a loop of 2 million dispatches (only the #disptach method call on the same object). The GC profiler report showed that the GC was invoked 287 times and each invocation was blocking the execution for about 0.15ms.<br />
Using Ruby&#8217;s <a href="http://ruby-doc.org/core/classes/ObjectSpace.html#M001526" target="_blank">ObjectSpace</a> and <a href="http://ruby-doc.org/core/classes/GC.html#M001373" target="_blank">disabling the GC</a> during the benchmark, I could see that each loop allocates an object of type T_NODE which is more than likely our @block ivar converted back into a block. This is quite a waste. Furthermore, having to evaluate our block in a different context every single call surely isn&#8217;t good for performance.</p>
<p>So instead of doing the work at run time, why not doing it at load time? By that I mean that we can optimize the #dispatch method if we could &#8220;precompile&#8221; the method body instead of &#8220;proxying&#8221; the dispatch to an instance_eval call. Here is the code:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> SolutionTwo
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>origin, <span style="color:#006600; font-weight:bold;">&amp;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@origin</span> = origin
    implementation<span style="color:#006600; font-weight:bold;">&#40;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  private
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> implementation<span style="color:#006600; font-weight:bold;">&#40;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
    mod = <span style="color:#9966CC; font-weight:bold;">Module</span>.<span style="color:#9900CC;">new</span>
    mod.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:define_method</span>, <span style="color:#ff3333; font-weight:bold;">:dispatch</span>, block<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">extend</span> mod
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
SolutionTwo.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">40</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#0066ff; font-weight:bold;">@origin</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">dispatch</span>
<span style="color:#008000; font-style:italic;"># 42</span></pre></div></div>

<p>This optimization is based on the fact that the benchmark (and the real life usage) creates the instance once and then calls #dispatch many times. So by making the initialization of our instance a bit slower, we can drastically improve the performance of the method call. We also still need to execute our block in the right context. And finally, each instance might have a different way to dispatch since it is defined dynamically at initialization. To work around all these issues, we create a new module on which we define a new method called dispatch and the body of this method is the passed block. Then we simply our instance using our new module.</p>
<p>Now every time we call #dispatch, a real method is dispatched which is much faster than doing an eval and no objects are allocated. Running the profiler and the benchmarks script used earlier, we can confirm that the GC doesn&#8217;t run a single time and that the optimized code runs 2X faster!</p>
<p>&nbsp;</p>
<p>Once again, it&#8217;s yet another example showing that you <a href="http://merbist.com/2010/07/29/object-allocation-why-you-should-care/" target="_blank">should care about object allocation</a> when dealing with code in the critical path. It also shows how to work around the block bindings. Now, it doesn&#8217;t mean that you have to obsess about object allocation and performance, even if my last implementation is 2X faster than the previous, we are only talking about a few microseconds per dispatch. That said microseconds do add up and creating too many objects will slow down even your faster code since the GC will stop-the-world as its cleaning up your memory. In real life, you probably don&#8217;t have to worry too much about low level details like that, unless you are working on a framework or sharing your code with others. But at least you can learn and understand why one approach is faster than the other, it might not be useful to you right away, but if you take programming as a craft, it&#8217;s good to understand how things work under the hood so you can make educated decisions.<br />
&nbsp;</p>
<h3>Update:</h3>
<p>@apeiros in the comments suggested a solution that works &#038; performs the same as my solution, but is much cleaner:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> SolutionTwo
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>origin, <span style="color:#006600; font-weight:bold;">&amp;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@origin</span> = origin
    define_singleton_method<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:dispatch</span>, block<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> block_given?
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2011/09/05/ruby-optimization-example-and-explaination/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Deploying a Rails 3.1 app &#8211; gotchas</title>
		<link>http://merbist.com/2011/08/30/deploying-a-rails-3-1-app-gotchas/</link>
		<comments>http://merbist.com/2011/08/30/deploying-a-rails-3-1-app-gotchas/#comments</comments>
		<pubDate>Wed, 31 Aug 2011 01:20:34 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1115</guid>
		<description><![CDATA[Recently I had to build a new app as part of my research &#38; development job at LivingSocial. My goal was to get the app up and running in just a few weeks, solid application architecture and graphic design included. When you need to build an app quickly and you want it to have some [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I had to build a new app as part of my research &amp; development job at <a href="http://livingsocial.com" target="_blank">LivingSocial</a>. My goal was to get the app up and running in just a few weeks, solid application architecture and graphic design included.<br />
When you need to build an app quickly and you want it to have some solid foundations, Rails is quite useful.<br />
I used Rails 3.1RCx so if we would to keep my app and push it to production, the engineering team wouldn&#8217;t have to update it and the transition should be seamless. I also quite like <a href="http://jashkenas.github.com/coffee-script/" target="_blank">CoffeeScript</a> and the app being quite heavy on JavaScript, the choice was easy. Furthermore, my coworker <a title="Bruce Williams" href="http://codefluency.com/" target="_blank">Bruce Williams</a> is a fan of <a title="SCSS" href="http://sass-lang.com/" target="_blank">SCSS</a> and he&#8217;s writing a <a href="http://pragprog.com/" target="_blank">PragProg</a> book called &#8220;The Rails View&#8221; with other LivingSocialist: <a href="http://www.boboroshi.com/" target="_blank">John Athayde</a>. So you got the point, I&#8217;m using Rails3.1, but this post is about the challenges I faced when it was time to deploy and the solutions I found.</p>
<p>I&#8217;ll skip the intro to Rails 3.1 and how to use the new asset pipeline, refer to the <a title="Asset Pipeline" href="http://guides.rubyonrails.org/asset_pipeline.html" target="_blank">Rails guide</a> or one of the mainly posts referenced in t<a href="http://jasonrudolph.com/blog/2011/06/06/helpful-resources-for-upgrading-to-rails-3-1/" target="_blank">his post</a> (if I had properly read the <a href="http://guides.rubyonrails.org/asset_pipeline.html" target="_blank">guide</a>, it would have saved me some valuable time, trust me, read it carefuly).</p>
<p>At that point last night, I had my app working great locally, Bruce created some awesome scss code using mixins and nested rules, the HTML was clean and working great, my <a href="http://jashkenas.github.com/coffee-script/" target="_blank">CoffeeScript</a> was brewing nicely, all was great until I tried to deploy to our QA environment.</p>
<h3>JavaScript runtime dependency</h3>
<p>The first thing you will notice is that you need the proper JavaScript runtime so the asset pipeline works properly. Not a big deal, you&#8217;ll find a lot of documentation about that. The problem is that you need to update your production environment or use depend on gem that will compile the required runtime (sounds dirty to me). So if you are deploying to many machines and you are using an image solution (EC2 AMI or other), you will need to update your image or spin new instances via updated chef/puppet recipes. In this case, the awesome team at LivingSocial had an image ready for me, so that wasn&#8217;t a big deal, but still, you need to take that in consideration as you are planning to update.</p>
<p>So the asset pipeline optimizes your asset management by processing/compiling asset files for you and optimizing their delivery. Instead of serving static files directly via public/images or public/javascripts you know serve them via the asset pipeline which will take care of compiling your CoffeeScript, grouping and minifying your JS and preprocessing all sorts of format. It also optimizes the caching process by giving a unique filename to each file based on the file metadata and gziping files. This is great, but you really, really, really don&#8217;t want to have your apps take care of that in production. Why wasting precious resources to serve assets when they can be prepared ahead of time. (by making Rails serve static assets, you are seriously reducing the throughput of  your app, please think of the children (or the dolphins/trees if you don&#8217;t like children))</p>
<h3>Capistrano</h3>
<p>Rails obviously has a preprocessor available as a rake task and you should update your deployment recipe to use that new feature. Here is my Capistrano code:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">after <span style="color:#996600;">'deploy:update_code'</span>, <span style="color:#996600;">'deploy:compile_assets'</span>
namespace <span style="color:#ff3333; font-weight:bold;">:deploy</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  task <span style="color:#ff3333; font-weight:bold;">:compile_assets</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    run <span style="color:#996600;">&quot;cd #{release_path}; RAILS_ENV=production rake assets:precompile&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Well, my real code doesn&#8217;t hardcode the RAILS_ENV constant value, it&#8217;s in fact set in each env file, but I simplified it since most people only use 1 env outside of dev &amp; test.</p>
<p>What that will do is compile all the files and dump them in public/assets/. But the file I had called bubble.png now becomes bubble-27543c671a3ab45141ee0d3216085009.png which means that my app is totally broken because images use in Bruce SCSS don&#8217;t load, my js files don&#8217;t load and the app is totally broken. Now this is least fun part, that I wish I had known before. This is where you go back and change your code so it uses magic to get the right file names.</p>
<h3>Images</h3>
<p>Fixing images was actually quite simple, in all my views, I just had to make sure I was using the image_tag helper everywhere.</p>
<h3>CSS</h3>
<p>SCSS files were a bit more tricky, I had to use the new scss preprocessor helpers you will find in the <a href="http://guides.rubyonrails.org/asset_pipeline.html" target="_blank">Rails guide</a> (image_path and image_url). I first looked into using erb, but turned out it wasn&#8217;t needed and the end result is much cleaner.</p>
<h3>Javascript/CoffeeScript</h3>
<p>For the CoffeeScript files, I was referring to image assets in the code and of course all the links were broken. So I had to use ERB in my coffee which looked funky but it worked.</p>
<p>But to get that to work, you need to rename your coffee script and append erb at the end. For instance my feature.js.coffee script had to be renamed feature.js.coffee.erb. That made me cry a little inside, but oh well, at least its not a XML config file. Maybe soon we will start seeing code in filenames or filenames called my_feature.js.compressed.minified.coffee.erb.from_rails.mattetti.org<br />
Also, be careful about the order of the file extensions, otherwise it won&#8217;t work. I thought I was done, ready to deploy my apps and this time the assets will show up properly. Turns out I was wrong <img src='http://merbist.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<h3>Rails asset precompilation env specific configuration.</h3>
<p>My css looked good, the precompiling task had run fine but I was missing some js files. I scratched my head as I could only see some of my js files. I then realized that all my JS files were there but some of my CoffeeScript files were missing. The answer was given to me by Bruce who asked me if I had updated my &#8220;config.assets.precompile&#8221; setting. Sometimes I feel that Rails is trying to compete with Struts and here I was really surprised that by default Rails, in production mode only precompiles all static JS and application.js files, but none of the other dynamic js files. Now it does precompile all the scss files, but for a reason I just don&#8217;t understand, it&#8217;s not the case for the JS files. So, you have to go edit production.rb in the config/environments folder and add the other js files you would like Rails to precompile for you.</p>
<p>After making all these changes, I was able to redeploy my app and everything was working again. (you might want to tweak your apache/nginx config as explained in the <a href="http://guides.rubyonrails.org/asset_pipeline.html" target="_blank">Rails guide</a>)</p>
<p>&nbsp;</p>
<h3>Conclusion</h3>
<p>Don&#8217;t be fooled like me and expect that because you have an app running locally, deployment will work right away. Make sure to read about the new features and what&#8217;s needed. Overall, I think that the asset pipeline is a nice addon to Rails and if you don&#8217;t feel like using it, just can put/leave all your files in the public folder and everything will work just like before. I do have to say that I was surprised to see that even in a brand new Rails 3.1 project, Rails isn&#8217;t running in threaded mode by default. But that&#8217;s a different (old) story and I guess people still get more excited about asset management than framework raw performance <img src='http://merbist.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2011/08/30/deploying-a-rails-3-1-app-gotchas/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>First step in scaling a web site: HTTP caching</title>
		<link>http://merbist.com/2011/07/11/first-step-in-scaling-a-web-site-http-caching/</link>
		<comments>http://merbist.com/2011/07/11/first-step-in-scaling-a-web-site-http-caching/#comments</comments>
		<pubDate>Mon, 11 Jul 2011 18:21:02 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Misc]]></category>
		<category><![CDATA[Software Design]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[http cache]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[scaling]]></category>
		<category><![CDATA[varnish]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1094</guid>
		<description><![CDATA[Today my friend Patrick Crowley and I were talking about scaling his website: http://cinematreasures.org since an article covering his work will soon be published in a very popular newspaper. Patrick&#8217;s site is hosted on Heroku which comes by default with Varnish caching enabled. The challenge is that a lot of people using the Rails framework are used [...]]]></description>
			<content:encoded><![CDATA[<p>Today my friend <a title="Patrick Crowley" href="http://twitter.com/mokolabs" target="_blank">Patrick Crowley</a> and I were talking about scaling his website: <a title="Cinema Treasures" href="http://cinematreasures.org/" target="_blank">http://cinematreasures.org</a> since an article covering his work will soon be published in a very popular newspaper. Patrick&#8217;s site is hosted on <a title="Heroku" href="http://www.heroku.com/" target="_blank">Heroku</a> which comes by default with <a title="Varnish" href="https://www.varnish-cache.org/" target="_blank">Varnish caching</a> enabled.</p>
<p>The challenge is that a lot of people using the Rails framework are used to doing page caching instead of relying on HTTP caching, even though this feature was added a long time ago. The major problem with page caching is that it doesn&#8217;t scale that well as soon as you run more than one server. Indeed you would need to store the page content to a shared drive between your servers or use memcached and do some work to avoid hitting your app every single time. On the other hand, HTTP caching is extremely easy to handle at the application level and it will dramatically reduce the amount of requests hitting your app. Let me explain a little more about HTTP caching.</p>
<p>Ryan Tomako wrote an <a title="HTTP caching" href="http://tomayko.com/writings/things-caches-do" target="_blank">excellent post</a> about the details of caching, I strongly recommend you <a title="HTTP Caching" href="http://tomayko.com/writings/things-caches-do" target="_blank">read it</a>. In a nutshell, the HTTP caching layer (usually) seats before your application layer and allows you, the developer to store some responses that can be send back to the users based on optional conditions. That might still seem vague, let&#8217;s take a concrete example. If you look at <a href="http://cinematreasures.org" target="_blank">http://cinematreasures.org</a>&#8216;s home page you can see that it&#8217;s an agglomerate of various information:</p>
<p style="text-align: center;"><a href="http://cinematreasures.org"><img class="aligncenter" title="CinemaTreasures homepage" src="https://img.skitch.com/20110709-dnxjhikxr14tdr7e35n97madhn.jpg" alt="CinemaTreasures homepage" width="606" height="568" /></a></p>
<p>And the bottom of the page contains even more dynamic data such as the popular movie theater photos, latest movie theater videos and latest tweets. One might look at that and say that this page can&#8217;t really be cached and that the caching should be done at the model layer (i.e. cache the data coming from the database). I would certainly agree that caching the data layer is probably a good idea, but you shouldn&#8217;t start by that. In fact without caching, this page renders fast enough. The problem is when someone like <a href="http://rogerebert.suntimes.com/" target="_blank">Roger Ebert</a> tweets about <a title="Roger Ebert - Cinema Treasures" href="http://twitter.com/#!/ebertchicago/status/85912164648497152" target="_blank">CinemaTreasures</a> the load on the app peaks significantly. At the point, the amount of concurrent connections your app can handle gets put to the challenge. Even though your page load is &#8220;fast enough&#8221;, requests will queue up and some will eventually time out. That&#8217;s actually a perfect case of HTTP caching.</p>
<p>What we want to do in that case is to cache a version of the home page in Varnish for 60 seconds. During that time, all requests coming to the site, will be served by Varnish and will all get the same cached content. That allows our servers to handle the non cached requests and therefore increase our throughput. What&#8217;s even better, is that if a user refreshes the home page in his/her browser during the first 60 seconds the requests won&#8217;t even make it all the way to our servers. All of that thanks to conditions set on the response. The first user hitting the HTTP cache layer (Varnish in this case) won&#8217;t find a fresh cached response, so varnish will forward the request to our application layer which will send back the homepage to varnish and tell Varnish that this content is good for a full minute so please don&#8217;t ask for it again until a minute from now. Varnish serves this response to the users&#8217; browser and let the browser know that the server said that the response was good enough for a minute so don&#8217;t bother asking for it again. But now, if during these 60 seconds another user comes in, he will hit Varnish and Varnish will have the cached response from the first user and because the cache is still fresh (it&#8217;s not been 60 seconds since the first request) and the cache is public, then the same response will be sent to the second user.</p>
<p>As you can see, the real strength of HTTP caching is the fact that it&#8217;s a conditional caching. It&#8217;s based on the request&#8217;s URL and some &#8220;flags&#8221; set in the request/response headers.</p>
<p>Setting these conditions in your app is actually very simple since you just need to set the response&#8217;s headers. If you are using a Ruby framework you will more than likely have access to the request object via the &#8220;request&#8221; method and you can set the headers directly like that: &#8220;<span class="Apple-style-span" style="font-family: Consolas, Monaco, monospace; font-size: 12px; line-height: 18px; white-space: pre;">response.headers['Cache-Control'] = &#8216;public, max-age=60&#8242;&#8221;</span>.<br />
In Rails, you can actually use a helper method instead: <span class="Apple-style-span" style="font-family: Consolas, Monaco, monospace; font-size: 12px; line-height: 18px; white-space: pre;">expires_in 1.minute, :public => true</span>.</p>
<p>You might have a case where you HAVE TO serve fresh content if available and can&#8217;t serve stale cached content even for a few seconds. In this case, you can rely on the Etag header value. The Etag is meant to validate the freshness of a cached response. Think of it as a signature (unique ID) that is set on the response and used by the client (or cache layer) to see if the server response has changed or not. The way it works is that the client keeps track of the Etag received for each request (attached to the cached response) and then sends it with the next requests. The HTTP layer or application sees the Etag in the request and can check if it is still valid and the content didn&#8217;t change. If that&#8217;s the case, an empty response can be sent with a special HTTP status code (304) to let know the client that the old cached value is still good to be used.  Rails has a helper called &#8220;stale?&#8221; that helps you do the Etag/last modified check and allows you to not fetch all the objects from the database by doing a cheap check on an attribute (For instance you can check the updated_at value and use that as a condition to pull an object and its relationships).</p>
<p>So I explain HTTP caching, I often hear people telling me: &#8220;that&#8217;s great Matt, but you know what, that won&#8217;t work for us because we have custom content that we display specifically to our users&#8221;. So in that case, you can always set the Cache-Control header to private which will only cache the response in the client&#8217;s browser and not the cache layer. That&#8217;s good to some extent, but it can definitely be improved by rethinking a bit your view layer. In most web apps, the page content is rendered by server side code (Rails, Django, node.js, PHP..) and sent to the user all prepared for him. There are a few challenges with this approach, the biggest one is that the server has to wait until everything is ready (all data fetched, view rendered etc&#8230;) before sending back a response and before the client&#8217;s browser can start rendering (there are ways to chunk the response but that&#8217;s besides the scope of this post). The other is that the same expensive content has to be calculated/rendered for two different users because you might be inserting the username of the current user at the top of the page for instance. A classic way to deal with that is often to use fragment caching, where the expensive rendering is cached and reused by different requests. That&#8217;s good but if the only reason to do that is because we are displaying some user specific data, there is a simpler way: async page rendering. The concept is extremely simple: remove all user specific content from the rendered page and then inject the user content in a second step once the page is displayed. The advantage is that now the full page can be cached in Varnish (or Squid or whatever you use for HTTP caching). To inject the user content, the easiest way is to use JavaScript.</p>
<p>Let&#8217;s stay on CinemaTreasures, when you&#8217;re logged in, the username is shown on the top of each page:</p>
<div class="wp-caption aligncenter" style="width: 584px"><img title="cinema treasures Login" src="https://img.skitch.com/20110710-mh5tqxuw1txf9kppn1smkkarrs.jpg" alt="" width="574" height="140" /><p class="wp-caption-text">Once logged in, the username is displayed on all pages</p></div>
<p>The only things that differs from the page rendered when the user is not logged in and when he is, are these 2 links and an avatar. So let&#8217;s write some code to inject that after rendering the page.</p>
<p>In Rails, in the sessions controller or whatever code logs you in, you need to create a new cookie containing the username:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">cookies<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:username</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#006600; font-weight:bold;">&#123;</span>
         <span style="color:#ff3333; font-weight:bold;">:value</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> session<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:username</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
         <span style="color:#ff3333; font-weight:bold;">:expires</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">2</span>.<span style="color:#9900CC;">days</span>.<span style="color:#9900CC;">from_now</span>,
         <span style="color:#ff3333; font-weight:bold;">:domain</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;.cinematreasures.org&quot;</span>
       <span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>As you can see, we don&#8217;t store the data in the session cookie and the data won&#8217;t be encrypted. You need to be careful that someone changing his cookie value can&#8217;t access data he/should shouldn&#8217;t. But that&#8217;s a different discussion. Now that the cookie is set, we can read it from JavaScript when the page is loaded.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">document.<span style="color: #660066;">observe</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;dom:loaded&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  displayLoggedinUserLinks<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> readCookie<span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
     <span style="color: #003366; font-weight: bold;">var</span> nameEQ <span style="color: #339933;">=</span> <span style="color: #000066;">name</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;=&quot;</span><span style="color: #339933;">;</span>
     <span style="color: #003366; font-weight: bold;">var</span> ca <span style="color: #339933;">=</span> document.<span style="color: #660066;">cookie</span>.<span style="color: #660066;">split</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">';'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i<span style="color: #339933;">=</span><span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>i <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> ca.<span style="color: #660066;">length</span><span style="color: #339933;">;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          <span style="color: #003366; font-weight: bold;">var</span> c <span style="color: #339933;">=</span> ca<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
          <span style="color: #000066; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>c.<span style="color: #660066;">charAt</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">==</span><span style="color: #3366CC;">' '</span><span style="color: #009900;">&#41;</span> c <span style="color: #339933;">=</span> c.<span style="color: #660066;">substring</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span>c.<span style="color: #660066;">length</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
          <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>c.<span style="color: #660066;">indexOf</span><span style="color: #009900;">&#40;</span>nameEQ<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">return</span> c.<span style="color: #660066;">substring</span><span style="color: #009900;">&#40;</span>nameEQ.<span style="color: #660066;">length</span><span style="color: #339933;">,</span>c.<span style="color: #660066;">length</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     <span style="color: #009900;">&#125;</span>
     <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> displayLoggedinUserLinks<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> username            <span style="color: #339933;">=</span> readCookie<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'username'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> loginLink           <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'login'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> logout              <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'logout'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>username <span style="color: #339933;">==</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    loginLink.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    logout.<span style="color: #660066;">hide</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #000066; font-weight: bold;">else</span><span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// user is logged in and we have his/her username</span>
    loginLink.<span style="color: #660066;">hide</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>userGreetings<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> userGreetings.<span style="color: #660066;">update</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;&lt;span id='username'&gt;username&lt;/span&gt;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
    logout.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    showAvatar<span style="color: #009900;">&#40;</span>username<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The code above doesn&#8217;t do much, once the DOM is loaded, the displayLoggedinUserLinks() function gets trigger. This function reads the cookie via the readCookie() function and if a username is found, the login link is hidden, the user name is displayed, as well as the logout link and the avatar. (You can also use a jQuery cookie plugin to handle the cookie, but this is an old example using Prototype, replace the code accordingly)<br />
When the user logs out, we just need to delete the username cookie and the cached page will be rendered properly. In Rails, you would do delete the cookie like that: <span class="Apple-style-span" style="font-family: Consolas, Monaco, monospace; font-size: 12px; line-height: 18px; white-space: pre;">cookies.delete(&#8216;username&#8217;)</span>.<br />
Quite often you might even want to make an Ajax call to get some information such as the number of user messages or notifications. Using jQuery or whatever JS framework you fancy you can do that once the page is rendered. Here is an example, on this page, you can see the learderboards for MLB The Show. The leaderboards don&#8217;t change that often, especially the overall leaderboards so they can be cached for a little while, however the player&#8217;s presence can change anytime. The smart way to deal with that, would be to cache the  leaderboards for a few seconds/minutes and make an ajax call to a presence service passing it a list of user ids collected from the DOM. The service called via Ajax could also be cached  depending on the requirements.</p>
<p>Now there is one more problem that people using might encouter: flash notices. For those of you not familiar with Rails, flash notices are messages set in the controller and passed to the view via the session (at least last time I checked). The problem happens if I&#8217;m the home page isn&#8217;t cached anymore and I logged in which redirects me to the home page with a flash message like so:</p>
<p><img class="aligncenter" title="flash message" src="https://img.skitch.com/20110710-1u6dn8rrc6r62rsg6niphhd2pi.jpg" alt="" width="990" height="219" /></p>
<p>The problem is that the message is part of the rendered page and now for 60 seconds, all people hitting the home page will get the same message. This is why you would want to write a helper that would put this message in a custom cookie that you&#8217;d pull JS and then delete once displayed. You could use a helper like that to set the cookie:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> flash_notice_cookie<span style="color:#006600; font-weight:bold;">&#40;</span>msg, expiration=<span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  cookies<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:flash_notice</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#006600; font-weight:bold;">&#123;</span>
    <span style="color:#ff3333; font-weight:bold;">:value</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> msg,
    <span style="color:#ff3333; font-weight:bold;">:expires</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> expiration <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#006666;">1</span>.<span style="color:#9900CC;">minutes</span>.<span style="color:#9900CC;">from_now</span>,
    <span style="color:#ff3333; font-weight:bold;">:domain</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;.cinematreasures.com&quot;</span>
   <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>And then add a function called when the DOM is ready which loads the message and injects it in the DOM. Once the cookie read, delete it so the message isn&#8217;t displayed again.</p>
<p>&nbsp;</p>
<p>So there you have it, if you follow these few steps, you should be able to handle easily 10x more traffic without increasing hardware or making any type of crazy code change. Before you start looking into memcached, redis, cdns or whatever, consider HTTP caching and async DOM manipulation. Finally, note that if you can&#8217;t use Varnish or Squid, you can very easily setup <a title="Rack Cache" href="http://rtomayko.github.com/rack-cache/" target="_blank">Rack-Cache</a> locally and share the cache via memcached. It&#8217;s also a great way to test locally.</p>
<hr />
<strong>Update:</strong> CinemaTreasures was updated to use HTTP caching as described above. The hosting cost is now half of what it used to be and the throughput is actually higher which offers a better protection against peak traffic.</p>
<hr />
<p>&nbsp;</p>
<p>External resources:</p>
<ul>
<li><a href="http://tomayko.com/writings/things-caches-do" target="_blank">http://tomayko.com/writings/things-caches-do</a></li>
<li><a title="HTTP Caching at Heroku" href="http://devcenter.heroku.com/articles/http-caching" target="_blank">HTTP Caching at Heroku</a></li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html" target="_blank">W3 caching protocol </a></li>
<li><a href="http://rtomayko.github.com/rack-cache/" target="_blank">Rack-Cache middleware</a></li>
<li><a href="http://www.nolanevans.com/2011/03/optimizing-your-rails-site-with-http.html" target="_blank">Blog post covering HTTP Caching/Varnish/Rails</a></li>
<li><a href="http://plugins.jquery.com/project/Cookie" target="_blank">jQuery cookie plugin</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2011/07/11/first-step-in-scaling-a-web-site-http-caching/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

