<?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>chris moos&#039;s blog</title>
	<atom:link href="http://chrismoos.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://chrismoos.com</link>
	<description>coding my way through life</description>
	<lastBuildDate>Sun, 18 Sep 2011 19:48:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>libhashring &#8211; high performance consistent&#160;hashing</title>
		<link>http://chrismoos.com/2011/06/04/libhashring-high-performance-consistent-hashing/</link>
		<comments>http://chrismoos.com/2011/06/04/libhashring-high-performance-consistent-hashing/#comments</comments>
		<pubDate>Sat, 04 Jun 2011 23:49:11 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[hashing]]></category>
		<category><![CDATA[sharding]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=962</guid>
		<description><![CDATA[In a previous post I talked about the need to shard Redis data and how I accomplished this by adding shard/hashing support to erldis, an Erlang client for Redis. This solution proved to work well, it distributed our data very well amongst many Redis servers &#8212; but there was one problem. Performance. In the change [...]]]></description>
			<content:encoded><![CDATA[<p>In a <a href="http://chrismoos.com/2011/04/10/redis-sharding-with-erlang/">previous post</a> I talked about the need to shard Redis data and how I accomplished this by <a href="https://github.com/cstar/erldis/pull/7">adding shard/hashing support to erldis</a>, an Erlang client for Redis. This solution proved to work well, it distributed our data very well amongst many Redis servers &#8212; but there was one problem. Performance. </p>
<p>In the change I made to erldis, the hash ring was stored in ETS (an erlang memory store) and anytime a key was hashed, the ring had to be retrieved from ETS. The problem with this is that Erlang copies the entire ring when it comes out of ETS. The ring we used was very large, with thousands of items. Copying this every single time became a huge performance hit. </p>
<p>To mitigate the performance problems, I decided to implement the hash ring in C, and write an Erlang driver to use it. That is how <a href="https://github.com/chrismoos/hash-ring">libhashring</a> was born. It is very high performance and currently has bindings for Erlang and Java. It is currently deployed in our production environment and its speed is incredible. I am confident that increasing the size of the ring as we add capacity will not cause an impact to the hash ring&#8217;s performance.</p>
<p><strong>libhashring</strong> supports MD5 and SHA-1. MD5 seems to be about 25% faster than SHA-1, so if you want the extra performance, MD5 is probably the best bet. </p>
<p>Feel free to <a href="https://github.com/chrismoos/hash-ring#fork_box">fork libhashring</a> and make it even better, I&#8217;d be really happy to get some feedback and contributions.</p>
<p><strong>P.S.</strong> &#8211; After finishing the hash ring, I came across <a href="http://www.last.fm/user/RJ/journal/2007/04/10/rz_libketama_-_a_consistent_hashing_algo_for_memcache_clients">libketama</a> and realized it pretty much solves the same problem that I had. Too bad I didn&#8217;t see it sooner!</p>
<h4>C example</h4>
<div class="codecolorer-container c blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br /></div></td><td><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">hash_ring_t <span style="color: #339933;">*</span>ring <span style="color: #339933;">=</span> hash_ring_create<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">8</span><span style="color: #339933;">,</span> HASH_FUNCTION_SHA1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>slotA <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;slotA&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>slotB <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;slotB&quot;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>keyA <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;keyA&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>keyB <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;keyBBBB&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>keyC <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;keyB_&quot;</span><span style="color: #339933;">;</span><br />
<br />
hash_ring_node_t <span style="color: #339933;">*</span>node<span style="color: #339933;">;</span><br />
<br />
<a href="http://www.opengroup.org/onlinepubs/009695399/functions/assert.html"><span style="color: #000066;">assert</span></a><span style="color: #009900;">&#40;</span>hash_ring_add_node<span style="color: #009900;">&#40;</span>ring<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">uint8_t</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>slotA<span style="color: #339933;">,</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html"><span style="color: #000066;">strlen</span></a><span style="color: #009900;">&#40;</span>slotA<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> HASH_RING_OK<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<a href="http://www.opengroup.org/onlinepubs/009695399/functions/assert.html"><span style="color: #000066;">assert</span></a><span style="color: #009900;">&#40;</span>hash_ring_add_node<span style="color: #009900;">&#40;</span>ring<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">uint8_t</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>slotB<span style="color: #339933;">,</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html"><span style="color: #000066;">strlen</span></a><span style="color: #009900;">&#40;</span>slotB<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> HASH_RING_OK<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
node <span style="color: #339933;">=</span> hash_ring_find_node<span style="color: #009900;">&#40;</span>ring<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">uint8_t</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>keyA<span style="color: #339933;">,</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html"><span style="color: #000066;">strlen</span></a><span style="color: #009900;">&#40;</span>keyA<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<a href="http://www.opengroup.org/onlinepubs/009695399/functions/assert.html"><span style="color: #000066;">assert</span></a><span style="color: #009900;">&#40;</span>node <span style="color: #339933;">!=</span> NULL <span style="color: #339933;">&amp;&amp;</span> node<span style="color: #339933;">-&gt;</span>nameLen <span style="color: #339933;">==</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html"><span style="color: #000066;">strlen</span></a><span style="color: #009900;">&#40;</span>slotA<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/memcmp.html"><span style="color: #000066;">memcmp</span></a><span style="color: #009900;">&#40;</span>node<span style="color: #339933;">-&gt;</span>name<span style="color: #339933;">,</span> slotA<span style="color: #339933;">,</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html"><span style="color: #000066;">strlen</span></a><span style="color: #009900;">&#40;</span>slotA<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
node <span style="color: #339933;">=</span> hash_ring_find_node<span style="color: #009900;">&#40;</span>ring<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">uint8_t</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>keyB<span style="color: #339933;">,</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html"><span style="color: #000066;">strlen</span></a><span style="color: #009900;">&#40;</span>keyB<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<a href="http://www.opengroup.org/onlinepubs/009695399/functions/assert.html"><span style="color: #000066;">assert</span></a><span style="color: #009900;">&#40;</span>node <span style="color: #339933;">!=</span> NULL <span style="color: #339933;">&amp;&amp;</span> node<span style="color: #339933;">-&gt;</span>nameLen <span style="color: #339933;">==</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html"><span style="color: #000066;">strlen</span></a><span style="color: #009900;">&#40;</span>slotA<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/memcmp.html"><span style="color: #000066;">memcmp</span></a><span style="color: #009900;">&#40;</span>node<span style="color: #339933;">-&gt;</span>name<span style="color: #339933;">,</span> slotA<span style="color: #339933;">,</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html"><span style="color: #000066;">strlen</span></a><span style="color: #009900;">&#40;</span>slotA<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
node <span style="color: #339933;">=</span> hash_ring_find_node<span style="color: #009900;">&#40;</span>ring<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">uint8_t</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>keyC<span style="color: #339933;">,</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html"><span style="color: #000066;">strlen</span></a><span style="color: #009900;">&#40;</span>keyC<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<a href="http://www.opengroup.org/onlinepubs/009695399/functions/assert.html"><span style="color: #000066;">assert</span></a><span style="color: #009900;">&#40;</span>node <span style="color: #339933;">!=</span> NULL <span style="color: #339933;">&amp;&amp;</span> node<span style="color: #339933;">-&gt;</span>nameLen <span style="color: #339933;">==</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html"><span style="color: #000066;">strlen</span></a><span style="color: #009900;">&#40;</span>slotB<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/memcmp.html"><span style="color: #000066;">memcmp</span></a><span style="color: #009900;">&#40;</span>node<span style="color: #339933;">-&gt;</span>name<span style="color: #339933;">,</span> slotB<span style="color: #339933;">,</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html"><span style="color: #000066;">strlen</span></a><span style="color: #009900;">&#40;</span>slotB<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
hash_ring_free<span style="color: #009900;">&#40;</span>ring<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2011/06/04/libhashring-high-performance-consistent-hashing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thrift and&#160;ZooKeeper</title>
		<link>http://chrismoos.com/2011/05/25/thrift-and-zookeeper/</link>
		<comments>http://chrismoos.com/2011/05/25/thrift-and-zookeeper/#comments</comments>
		<pubDate>Wed, 25 May 2011 07:50:43 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[distributed]]></category>
		<category><![CDATA[synchronization]]></category>
		<category><![CDATA[thrift]]></category>
		<category><![CDATA[zookeeper]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=940</guid>
		<description><![CDATA[Thrift provides a great framework for developing and accessing remote services. It allows developers to create services that can be consumed by any application that is written in a language that there are Thrift bindings for (which is&#8230;just about every mainstream one, and more). This is great for systems that are heterogeneous &#8212; for example, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://thrift.apache.org/">Thrift</a> provides a great framework for developing and accessing remote services. It allows developers to create services that can be consumed by any application that is written in a language that there are Thrift bindings for (which is&#8230;just about every mainstream one, and more). </p>
<p>This is great for systems that are heterogeneous &#8212; for example, you could write a user authentication service in Java, but call it from your Ruby web application. </p>
<p>Thrift manages serialization of data to and from a service, as well as the protocol that describes a method invocation, response, etc,. This is great because instead of writing all the RPC code &#8212; you can just get straight to your service logic. Thrift uses TCP (not sure if UDP is/will be supported) and so a given service is bound to a particular port. </p>
<p>As you start to scale an infrastructure with Thrift services, you may find, as I have, that putting all of your Thrift server IP/port combinations in a configuration file that your clients read is just not&#8230;the best. If you have an environment where Thrift servers go down for maintenance (or crash), or you add more capacity on the fly, a dynamic way to manage the <strong>state</strong> of all of the services is needed.</p>
<p>Enter <a href="http://zookeeper.apache.org/">Apache ZooKeeper</a>, a distributed, fault tolerant, highly available system for managing configuration information, naming, and more (distributed synchronization, anyone?).</p>
<p>ZooKeeper appears like a filesystem to clients, it is a hierarchy of <strong>znodes</strong>, which are analogous to directories or files, both of which can contain a small amount of data.</p>
<p>ZooKeeper can be used to store Thrift service location information, allowing clients to dynamically discover Thrift services. ZooKeeper even provides a way to create <a href="http://en.wikipedia.org/wiki/Ephemeral">ephemeral</a> znodes, which means that once your Thrift service goes down, it will be removed from ZooKeeper automatically. And if that isn&#8217;t cool enough, ZooKeeper even supports <strong>watches</strong>, where clients can ask to be notified whenever a znode changes. This means that clients can begin using new Thrift service capacity instantly, and when failures happen, clients will stop attempting to contact a down Thrift service.</p>
<p>Laying out your Thrift services in ZooKeeper is important. Clients will need to know about the layout when performing service discovery. For example, you can do something such as:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">/</span>services<span style="color: #000000; font-weight: bold;">/</span>user<span style="color: #000000; font-weight: bold;">/</span>user0000000001<br />
<span style="color: #000000; font-weight: bold;">/</span>services<span style="color: #000000; font-weight: bold;">/</span>user<span style="color: #000000; font-weight: bold;">/</span>user0000000002<br />
....</div></td></tr></tbody></table></div>
<p>Clients can get a list of all znodes at <em>/services/user</em> to receive the list of servers for the <em>user</em> service. The only problem is&#8230;getting the list of znodes is only half the battle. <strong>user0000000001</strong> doesn&#8217;t really tell you how to access the user service on that node. This is why its important to store some kind of service location data with the znode. </p>
<p>ZooKeeper allows you to set the data for a znode, so when a node comes up, it just needs to also set data at the znode that describes how to locate or access the service. I&#8217;ve adopted to use a URI as the znode data &#8212; this is very flexible and easy to parse and read from most languages. For Thrift services I am using a URI that uses a <em>thrift</em> scheme:</p>
<div class="codecolorer-container html4strict blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">thrift://10.1.1.10:5656</div></td></tr></tbody></table></div>
<p>The URI can be easily adapted to your application, such as adding query string parameters with any extra custom metadata.</p>
<p>Thrift is great, and with ZooKeeper, its even better. I&#8217;m in the process of implementing this integration now and am looking forward to all of the benefits it has to offer. I would love to hear any feedback about this approach if anyone has personal experience, or just some good ideas. What is everyone else using to solve this type of problem?</p>
<p>Oh and also, if ZooKeeper isn&#8217;t your thing, you should definitely check out <a href="http://xph.us/2011/04/13/introducing-doozer.html">Doozer</a>. It has very similar features to ZooKeeper, and although new, it is definitely on my list of projects to watch. Oh, and did I mention that it is written in <a href="http://golang.org/">golang</a>?</p>
<blockquote><p>
Doozer is a highly-available, completely consistent store for small amounts of extremely important data. When the data changes, it can notify connected clients immediately (no polling), making it ideal for infrequently-updated data for which clients want real-time updates. Doozer is good for name service, database master elections, and configuration data shared between several machines.
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2011/05/25/thrift-and-zookeeper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Redis sharding with&#160;Erlang</title>
		<link>http://chrismoos.com/2011/04/10/redis-sharding-with-erlang/</link>
		<comments>http://chrismoos.com/2011/04/10/redis-sharding-with-erlang/#comments</comments>
		<pubDate>Mon, 11 Apr 2011 03:09:35 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=920</guid>
		<description><![CDATA[I&#8217;ve been using a great Erlang Redis library erldis recently and as our data set has grown much larger, we have decided we need to start sharding. Unfortunately the erldis library does not have support for sharding so I&#8217;ve forked the repository and made the changes. You can find my fork here. Pull request here. [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using a great Erlang Redis library <a href="https://github.com/cstar/erldis">erldis</a> recently and as our data set has grown much larger, we have decided we need to start <a href="http://en.wikipedia.org/wiki/Shard_(database_architecture)">sharding</a>. Unfortunately the erldis library does not have support for sharding so I&#8217;ve forked the repository and made the changes. You can find my fork <a href="https://github.com/chrismoos/erldis">here</a>. Pull request <a href="https://github.com/cstar/erldis/pull/7">here</a>.</p>
<h3>A little background</h3>
<p>Redis has been really great for us so far but as we get more data and more operations per second, we realized we need to start utilizing multiple Redis instances. Sharding basically splits up your keyspace across multiple servers in a consistent fashion. The typical example for finding out where a key belongs is by doing something like:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">hash(Key) mod N</div></td></tr></tbody></table></div>
<p>Where N is the index to a list of shards. This allows all of your clients to be consistent with knowing where a key belongs. The above algorithm is rather naive and the implementation that I&#8217;ve added to erldis is a bit different. </p>
<h3>Hash Ring</h3>
<p>In erldis when you create a ring each item or node is replicated on the ring multiple times, (128 by default in erldis), so that the hash ring is more evenly distributed. When a key is hashed, it is placed somewhere on the ring, and if you move clockwise the next node that is encountered is the one that will contain the key. If you are already at the end of the ring it just moves around the circle to the first node. Here is the Erlang representation of a ring with NumReplicas=2 with three nodes:</p>
<div class="codecolorer-container erlang blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="erlang codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #45b3e6;">Eshell</span> <span style="color: #45b3e6;">V5</span><span style="color: #ff9600;">.8</span> &nbsp;<span style="color: #109ab8;">&#40;</span>abort with ^G<span style="color: #109ab8;">&#41;</span><br />
<span style="color: #ff9600;">1</span><span style="color: #014ea4;">&gt;</span> hash_ring:<span style="color: #ff3c00;">create_ring</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span><span style="color: #ff7800;">&quot;redis01&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;redis02&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;redis03&quot;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">2</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<span style="color: #109ab8;">&#123;</span><span style="color: #ff9600;">2</span><span style="color: #6bb810;">,</span><br />
&nbsp;<span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#123;</span><span style="color: #ff7800;">&quot;redis01&quot;</span><span style="color: #6bb810;">,</span><br />
&nbsp; &nbsp;<span style="color: #ff9600;">545684121738837007922020352670259130010627269168</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span><br />
&nbsp; <span style="color: #109ab8;">&#123;</span><span style="color: #ff7800;">&quot;redis03&quot;</span><span style="color: #6bb810;">,</span><span style="color: #ff9600;">615626879509609616059735092207848107514679530568</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span><br />
&nbsp; <span style="color: #109ab8;">&#123;</span><span style="color: #ff7800;">&quot;redis02&quot;</span><span style="color: #6bb810;">,</span><span style="color: #ff9600;">831940194106586542005694020470691157762681039493</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span><br />
&nbsp; <span style="color: #109ab8;">&#123;</span><span style="color: #ff7800;">&quot;redis02&quot;</span><span style="color: #6bb810;">,</span><span style="color: #ff9600;">862200733042270842852150771881884931000854854035</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span><br />
&nbsp; <span style="color: #109ab8;">&#123;</span><span style="color: #ff7800;">&quot;redis01&quot;</span><span style="color: #6bb810;">,</span><span style="color: #ff9600;">976184092715215764651301117507107557316103934589</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span><br />
&nbsp; <span style="color: #109ab8;">&#123;</span><span style="color: #ff7800;">&quot;redis03&quot;</span><span style="color: #6bb810;">,</span><br />
&nbsp; &nbsp;<span style="color: #ff9600;">1324913878318290717698351186295127020927484244520</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#125;</span></div></td></tr></tbody></table></div>
<p>The hash algorithm used above is the name of the node concatenated with the replica number. So if you look at the ring above, the first item, <em>545684121738837007922020352670259130010627269168</em> was generated by doing:</p>
<div class="codecolorer-container erlang blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="erlang codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #45b3e6;">Eshell</span> <span style="color: #45b3e6;">V5</span><span style="color: #ff9600;">.8</span> &nbsp;<span style="color: #109ab8;">&#40;</span>abort with ^G<span style="color: #109ab8;">&#41;</span><br />
<span style="color: #ff9600;">1</span><span style="color: #014ea4;">&gt;</span> <span style="color: #ee3800;">&lt;&lt;</span><span style="color: #45b3e6;">Int</span>:<span style="color: #ff9600;">160</span><span style="color: #014ea4;">/</span><span style="color: #9d4f37;">unsigned</span><span style="color: #014ea4;">-</span><span style="color: #9d4f37;">integer</span><span style="color: #ee3800;">&gt;&gt;</span> <span style="color: #014ea4;">=</span> <a href="http://erlang.org/doc/man/crypto.html"><span style="color: #ff4e18;">crypto</span></a>:<span style="color: #ff3c00;">sha</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;redis012&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Int</span><span style="color: #6bb810;">.</span><br />
<span style="color: #ff9600;">545684121738837007922020352670259130010627269168</span></div></td></tr></tbody></table></div>
<p>The hashed string is &#8220;redis01&#8243; + 2 (which is the replica number). By knowing the algorithm for where a node lies on the ring, a client in any language can take advantage of the shards.</p>
<h3>Adding/Removing nodes</h3>
<p>The first thing I have to say about adding nodes is to not do it. Salvatore Sanfilippo wrote a <a href="http://antirez.com/post/redis-presharding.html">great post about sharding Redis</a>, and his recommendation is that re-hashing is difficult and instead you should create a large number of small Redis instances up front, that way you don&#8217;t have to add more nodes down the road. </p>
<p>For example, you might want to create 128 small Redis instances (multiple per box) and as you grow, just move those instances to their own dedicated (or larger) boxes. This lets you have a large amount of shards up front so you don&#8217;t have to worry about re-hashing for a hopefully long time.</p>
<p>And for removing nodes, failures etc,. try to use Redis&#8217;s replication and use some form of HA so that if a Redis instance dies, you have another one that is up to date to takeover (keepalived, Linux HA, etc,.).</p>
<h3>Final thoughts</h3>
<p>Redis has been fantastic and I&#8217;m really looking forward to finishing up on our Redis &#8220;cluster&#8221; and modifying our clients to support sharding. As for right now, I&#8217;m going to be looking into ways to migrate our existing Redis data into the shards in real-time and then &#8220;flipping the switch&#8221; on the clients. </p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2011/04/10/redis-sharding-with-erlang/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MoosTrax for Blackberry &#8212; Looking for&#160;testers</title>
		<link>http://chrismoos.com/2010/08/11/moostrax-for-blackberry-looking-for-testers/</link>
		<comments>http://chrismoos.com/2010/08/11/moostrax-for-blackberry-looking-for-testers/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 15:41:00 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[moostrax]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=871</guid>
		<description><![CDATA[I am finally going to work on updating MoosTrax for BlackBerry &#8212; as there are a few outstanding bugs that need to be addressed. The most important bug I will be working on is consistency of location updates in newer, post-4.2 OS BlackBerry devices. If you are interested in helping test the upcoming version, please [...]]]></description>
			<content:encoded><![CDATA[<p>I am finally going to work on updating MoosTrax for BlackBerry &#8212; as there are a few outstanding bugs that need to be addressed. The most important bug I will be working on is consistency of location updates in newer, post-4.2 OS BlackBerry devices.</p>
<p>If you are interested in helping test the upcoming version, please e-mail <a href="mailto:moostraxsupport@gmail.com">moostraxsupport@gmail.com</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2010/08/11/moostrax-for-blackberry-looking-for-testers/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MoosTrax released for&#160;iPhone</title>
		<link>http://chrismoos.com/2010/07/29/moostrax-released-for-iphone/</link>
		<comments>http://chrismoos.com/2010/07/29/moostrax-released-for-iphone/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 04:01:59 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[moostrax]]></category>
		<category><![CDATA[app store]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[released]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=859</guid>
		<description><![CDATA[I am happy to say that MoosTrax has been approved by Apple and is now available for download in the App Store. Thanks to everyone who helped with the beta testing &#8212; it was a great help. Note: MoosTrax works on devices running iOS 4+. iPhone Support/Help MoosTrax iTunes Link]]></description>
			<content:encoded><![CDATA[<p>I am happy to say that MoosTrax has been approved by Apple and is now available for download in the App Store. Thanks to everyone who helped with the beta testing &#8212; it was a great help.</p>
<p><strong>Note:</strong> MoosTrax works on devices running iOS 4+.</p>
<p><a href="http://trac.moostrax.com/trac/wiki/iPhone">iPhone Support/Help</a><br />
<a href="itms://itunes.apple.com/us/app/moostrax/id383812018?mt=8">MoosTrax iTunes Link</a></p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2010/07/29/moostrax-released-for-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MoosTrax for iPhone Beta&#160;Updates</title>
		<link>http://chrismoos.com/2010/07/12/moostrax-for-iphone-beta-updates/</link>
		<comments>http://chrismoos.com/2010/07/12/moostrax-for-iphone-beta-updates/#comments</comments>
		<pubDate>Tue, 13 Jul 2010 05:59:04 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[moostrax]]></category>
		<category><![CDATA[beta]]></category>
		<category><![CDATA[iphone]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=841</guid>
		<description><![CDATA[I&#8217;ve been working a lot on getting MoosTrax ready for the App Store and the latest beta adds a lot of great features. View a list of all of your devices View the current location of any device on your account. Enhanced battery usage through the &#8220;Conserve Battery&#8221; feature. The beta is still open, so [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working a lot on getting MoosTrax ready for the App Store and the latest beta adds a lot of great features.</p>
<ul>
<li>View a list of all of your devices</li>
<li>View the current location of any device on your account.</li>
<li>Enhanced battery usage through the &#8220;Conserve Battery&#8221; feature.</li>
</ul>
<p>The beta is still open, so send an e-mail to <a href="mailto:moostraxsupport@gmail.com">moostraxsupport@gmail.com</a> to join.</p>
<p><img src="http://cdn.chrismoos.com/wp-content/uploads/2010/07/settings.png" style="width: 300px;float:left;" /><img src="http://cdn.chrismoos.com/wp-content/uploads/2010/07/devices.png" style="padding-left: 10px; width: 300px;float:left;"/><br style="clear:both;"/></p>
<p><img src="http://cdn.chrismoos.com/wp-content/uploads/2010/07/device_info.png" style="width: 300px;"/></p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2010/07/12/moostrax-for-iphone-beta-updates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MoosTrax for iPhone&#160;iOS4</title>
		<link>http://chrismoos.com/2010/06/27/moostrax-for-iphone-ios4/</link>
		<comments>http://chrismoos.com/2010/06/27/moostrax-for-iphone-ios4/#comments</comments>
		<pubDate>Mon, 28 Jun 2010 02:47:51 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[moostrax]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[iphone]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=829</guid>
		<description><![CDATA[I just got a new iPhone 4 with iOS4&#8230;and it supports background location updates! I&#8217;ve decided to bring MoosTrax back to the iPhone. I&#8217;m looking for beta testers&#8230;and then soon I&#8217;ll be pushing it to the App Store. Applying for the beta Please e-mail moostraxsupport@gmail.com with your iPhone&#8217;s UDID. For information on finding the UDID, [...]]]></description>
			<content:encoded><![CDATA[<p>I just got a new iPhone 4 with iOS4&#8230;and it supports background location updates! I&#8217;ve decided to bring MoosTrax back to the iPhone.</p>
<p>I&#8217;m looking for beta testers&#8230;and then soon I&#8217;ll be pushing it to the App Store.</p>
<h2>Applying for the beta</h2>
<p>Please e-mail <a href="mailto:moostraxsupport@gmail.com">moostraxsupport@gmail.com</a> with your iPhone&#8217;s UDID. </p>
<p>For information on finding the UDID, go here: <a href="http://www.geekology.co.za/blog/2009/07/how-to-check-your-iphones-udid-from-itunes/">http://www.geekology.co.za/blog/2009/07/how-to-check-your-iphones-udid-from-itunes/</a></p>
<h2>Screenshots</h2>
<p><img src="http://www.moostrax.com/images/moostraxiphone2.png" style="float:left;"/><br />
<img src="http://www.moostrax.com/images/moostraxiphone.png" style="padding-left: 10px; float: left;"/><br />
<br style="clear:both;"/></p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2010/06/27/moostrax-for-iphone-ios4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AsyncRecord: Non-blocking database access for&#160;Ruby</title>
		<link>http://chrismoos.com/2010/06/21/asyncrecord-non-blocking-database-access-for-ruby/</link>
		<comments>http://chrismoos.com/2010/06/21/asyncrecord-non-blocking-database-access-for-ruby/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 04:17:18 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[eventmachine]]></category>
		<category><![CDATA[fastr]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=809</guid>
		<description><![CDATA[Two weeks ago I developed my first event-driven web framework for Ruby, Fastr. It helped me understand why running a web framework in an event loop is so natural. As I continued to tackle more features in Fastr, it was time to tackle persistence &#8212; notably, database access. AsyncRecord is/will be an ORM, similar to [...]]]></description>
			<content:encoded><![CDATA[<p>Two weeks ago I developed my first event-driven web framework for Ruby, <a href="http://chrismoos.com/2010/06/08/fastr-ruby-web-framework/">Fastr</a>. It helped me understand why running a web framework in an event loop is so <em>natural</em>. </p>
<p>As I continued to tackle more features in Fastr, it was time to tackle persistence &#8212; notably, database access. </p>
<p>AsyncRecord is/will be an ORM, similar to ActiveRecord &#8212; with one major difference &#8212; it doesn&#8217;t block. AsyncRecord currently uses <a href="http://github.com/tmm1/em-mysql">em-mysql</a> to access a MySQL database.</p>
<h2>How it usually works</h2>
<p>In most ORMs, when you attempt to access the database, everything in that thread will block until a response is received. This means that you waste time &#8212; just waiting. The CPU may be idle, but you cannot handle any more requests. (Typically you start multiple instances of your application to get past this, unfortunately each instance requires more resources on your server)</p>
<h2>How AsyncRecord works</h2>
<p>When you access something in the database with AsyncRecord, the request is sent to the database server, but control returns to the application immediately after the packet(s) are sent. When the server responds, which could be 20ms or 200ms later, a callback that you specify is invoked. </p>
<p>One important thing about accessing a database asynchronously, especially in web frameworks, is the ability to defer a response. Fastr has built-in support for deferred responses, a-la EventMachine/Thin.</p>
<p> A deferred response is when you tell the web server that you will send data to the client some time in the future, and the server is free to handle more requests until you are ready to respond.</p>
<h2>Benchmarking</h2>
<p>As I was implementing AsyncRecord, I knew it would be faster &#8212; but I wasn&#8217;t sure by how much. I setup a very simple Rails 2.3.5 application, as well as a Fastr application (from the latest source).</p>
<p>My goal was to make an application that has a single page, which shows 5 usernames from the database.</p>
<p><b>Rails controller</b>:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> MainController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> index<br />
&nbsp; &nbsp; users = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; User.<span style="color:#9900CC;">all</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:limit</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>user<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; users <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> user.<span style="color:#9900CC;">username</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; headers<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'Content-Type'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">'text/plain'</span><br />
&nbsp; &nbsp; render<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:text</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> users.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;<span style="color:#000099;">\n</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p><b>Fastr controller:</b></p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> MainController <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Fastr::Controller</span> &nbsp;<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> index<br />
&nbsp; &nbsp; defer_response<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">200</span>, <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">&quot;Content-Type&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;text/plain&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>response<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; User.<span style="color:#9900CC;">all</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:limit</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>users<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; users.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>user<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; response.<span style="color:#9900CC;">send_data</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{user.username}<span style="color:#000099;">\n</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; response.<span style="color:#9900CC;">succeed</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<h2>The Numbers</h2>
<h3>Fastr</h3>
<p>Average Latency: 123ms<br />
Requests per second: 385 r/s</p>
<p><img style="width: 600px;" src="http://cdn.chrismoos.com/wp-content/uploads/2010/06/fastr.png"/></p>
<h3>Rails</h3>
<p>Average Latency: 2040ms<br />
Requests per second: 42 r/s</p>
<p><img style="width: 600px;" src="http://cdn.chrismoos.com/wp-content/uploads/2010/06/rails.png"/></p>
<p>The tests were performed using JMeter. 100 concurrent requests (10 requests per connection).</p>
<p>I also ran some tests using apache bench, here are the results:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ab <span style="color: #660033;">-c</span> <span style="color: #000000;">100</span> <span style="color: #660033;">-n</span> <span style="color: #000000;">1000</span> http:<span style="color: #000000; font-weight: bold;">//</span>127.0.0.1:<span style="color: #000000;">5000</span><span style="color: #000000; font-weight: bold;">/</span></div></td></tr></tbody></table></div>
<h3>Fastr</h3>
<p>Average Latency: 90ms<br />
Requests per second: 1100 r/s</p>
<h3>Rails</h3>
<p>Average Latency: 2235ms<br />
Requests per second: 44 r/s</p>
<h2>Conclusion</h2>
<p>I am extremely happy with what AsyncRecord can do &#8212; and I hope to make it even better. I will be moving it out of Fastr and into its own project soon.</p>
<p>Fastr GitHub: <a href="http://github.com/chrismoos/fastr">http://github.com/chrismoos/fastr</a></p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2010/06/21/asyncrecord-non-blocking-database-access-for-ruby/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fastr &#8211; A Web Framework for&#160;Ruby</title>
		<link>http://chrismoos.com/2010/06/08/fastr-ruby-web-framework/</link>
		<comments>http://chrismoos.com/2010/06/08/fastr-ruby-web-framework/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 04:12:06 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web framework]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=787</guid>
		<description><![CDATA[Foreword Every month I go on a binge and learn something new. The most recent binge resulted in a new web framework, called fastr. I&#8217;ve always used Rails when I needed to create a web application in Ruby, but despite how great it is to code in, the performance and concurrency is not up to [...]]]></description>
			<content:encoded><![CDATA[<h2>Foreword</h2>
<p>Every month I go on a binge and learn something new. The most recent binge resulted in a new web framework, called <a href="http://github.com/chrismoos/fastr">fastr</a>.</p>
<p>I&#8217;ve always used Rails when I needed to create a web application in Ruby, but despite how great it is to code in, the performance and concurrency is not up to par. </p>
<p>Don&#8217;t get me wrong &#8212; Rails can scale, but it is not inherently very good when it comes to an individual instance&#8217;s performance.  While this is hopefully changing in Rails 3, I wanted to see what kind of concurrency and performance I could get out of a simple <a href="http://rubyeventmachine.com/">EventMachine</a> web application. Thus, fastr was born.</p>
<h2>Fastr&#8217;s Architecture</h2>
<p>Fastr is nothing special. It is an extremely simple MVC style web framework, similar in configuration to Rails.</p>
<p>What makes it different though, is how it handles requests and responses.</p>
<p>The core of fastr runs on an EventMachine reactor, which is basically just a big event loop. EventMachine is very capable of maintaining thousands of connections in one instance. This is great when you want an application that supports Comet and chunked responses. There is very minimal overhead in having thousands of connections that have occasional data flowing through.</p>
<p>EventMachine and Fastr also support the ability to defer a response until a long running task finishes executing. This is nice because it won&#8217;t block the rest of the application. The only catch is you are limited to EventMachine&#8217;s thread pool size, which I believe defaults to 20. You can always up this number though, if you want.</p>
<h2>Routing</h2>
<p>The routing is very similar to Rails, an example routes.rb file looks like this:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp;router.<span style="color:#9900CC;">draw</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>route<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; route.<span style="color:#9966CC; font-weight:bold;">for</span> <span style="color:#996600;">'/:controller/:action'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;">#route.for '/home/:action', :action =&gt; '[A-Za-z]+'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;">#route.for '/test', :to =&gt; 'home#index'</span><br />
&nbsp;<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<h2>Controllers</h2>
<p>Controllers are simple, with just a list of actions that are called based on the route. Actions should return a valid Rack response. There are convenience methods in the controller that help in creating Rack responses.</p>
<p>The nice thing about the controllers in Fastr is that you can defer responses with ease. Here is an example of a deferred response:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> long_running_task<br />
&nbsp; &nbsp; defer_response<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">200</span>, <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">&quot;Content-Type&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;text/plain&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>response<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;in our deferred response...now we can do cool stuff!&quot;</span><br />
&nbsp; &nbsp; &nbsp; response.<span style="color:#9900CC;">send_data</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;hey<span style="color:#000099;">\n</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; long_task = <span style="color:#CC0066; font-weight:bold;">proc</span> <span style="color:#006600; font-weight:bold;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; log.<span style="color:#9900CC;">debug</span> <span style="color:#996600;">&quot;Sleeping for 5 seconds...but this won't block other requests&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">sleep</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; log.<span style="color:#9900CC;">debug</span> <span style="color:#996600;">&quot;Finished sleeping, returning response to client.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#996600;">&quot;finished&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; callback = <span style="color:#CC0066; font-weight:bold;">proc</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>result<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; log.<span style="color:#9900CC;">debug</span> <span style="color:#996600;">&quot;Callback result: #{result}&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; response.<span style="color:#9900CC;">send_data</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{result}<span style="color:#000099;">\n</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; response.<span style="color:#9900CC;">succeed</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; response.<span style="color:#9900CC;">task</span><span style="color:#006600; font-weight:bold;">&#40;</span>long_task, callback<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>The alternative render methods also exist, where you can render a HAML template or just text:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">render<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:text</span>, <span style="color:#996600;">&quot;Hello, world!&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
render<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:haml</span>, <span style="color:#ff3333; font-weight:bold;">:template</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;index&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;"># this searches for index.haml in your app/views/ folder</span></div></td></tr></tbody></table></div>
<h2>Future</h2>
<p>For now, fastr is just a toy framework for me, that I hope to share with anyone interested in learning about building web frameworks.</p>
<p>I intend to start writing some tests as well as making fastr more robust. I don&#8217;t mean to displace any other Ruby web framework, but as I learn with fastr I hope to contribute what I learn back to projects like Rails and Sinatra.</p>
<p>Also, I&#8217;d like to get em-mysql or equivalent integrated so that you can really enjoy a event-driven web framework &#8212; event with database access.</p>
<p>Check out the GitHub page for more examples on getting fastr up and running.</p>
<p>GitHub: <a href="http://github.com/chrismoos/fastr">http://github.com/chrismoos/fastr</a></p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2010/06/08/fastr-ruby-web-framework/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Unlocking the full potential of the&#160;iPhone</title>
		<link>http://chrismoos.com/2010/04/17/unlocking-the-full-potential-of-the-iphone/</link>
		<comments>http://chrismoos.com/2010/04/17/unlocking-the-full-potential-of-the-iphone/#comments</comments>
		<pubDate>Sun, 18 Apr 2010 04:43:48 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[future]]></category>
		<category><![CDATA[iphone]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=753</guid>
		<description><![CDATA[Since Apple launched the iPhone in 2007 there has been an unprecedented growth in the mobile phone market. From new advances in hardware, such as touch screens, to operating systems mimicking the full power of a desktop computer. Never has a smartphone been able to penetrate the demographics of 10 year olds, to teenagers, or [...]]]></description>
			<content:encoded><![CDATA[<p>Since Apple launched the iPhone in 2007 there has been an unprecedented growth in the mobile phone market. From new advances in hardware, such as touch screens, to operating systems mimicking the full power of a desktop computer. Never has a smartphone been able to penetrate the demographics of 10 year olds, to teenagers, or mom and dad &#8212; until the iPhone. </p>
<p>There are now hundreds of thousands of applications built for mobile phones, with every use case you can imagine. But even with the growth and advances of the past few years, the industry is still in its youth. </p>
<p>Apple, with its enormous success, is still constantly on the front page because of its questionable practice &#8212; sole control of the iPhone platform. Unlike desktop operating systems, such as Windows or Mac OS X, where the user is in complete control of the operating system, the iPhone is a jail, with Apple deciding what can come in and go out.</p>
<p>The App Store, the only way for a developer to target an iPhone, or a user to install an application on the iPhone, is in constant censorship mode. Certain API&#8217;s are not allowed and questionable content is put to rest. </p>
<p>It is time that Apple realizes that it is not only the hardware in the iPhone, or the software that powers it, that makes it a powerful force in the mobile phone market. The power is in the <em>apps</em>, the platform, and in the imaginations of developers.</p>
<p>Even though there are many applications for the iPhone, there could be so much more. The iPhone is a powerful device that can be used to provide a platform for mobile applications in every industry possible. Medical, industrial, retail &#8212; the list goes on. But as long as Apple is in control of what happens on the iPhone, developers will never be able to harness the full potential of such a beautiful device.</p>
<p>Apple now has the ability to turn the iPhone, and the new iPad, into a commodity device. The PC of the mobile world. My intuition tells me that Apple won&#8217;t let this happen. They prefer to maintain complete control of their platform, and while making it a premium and luxury item, they stop it from attaining the growth that it most definitely can achieve. </p>
<p>The future is in Apple&#8217;s hands &#8212; and they have the ability to make it an awesome place.</p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2010/04/17/unlocking-the-full-potential-of-the-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

