<?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>Hungry Machine &#187; Rails</title>
	<atom:link href="http://blog.hungrymachine.com/category/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.hungrymachine.com</link>
	<description>The guys behind LivingSocial</description>
	<lastBuildDate>Sun, 25 Oct 2009 15:08:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Merb routing in Rails &#8211; Today!</title>
		<link>http://blog.hungrymachine.com/2008/12/29/merb-routing-in-rails/</link>
		<comments>http://blog.hungrymachine.com/2008/12/29/merb-routing-in-rails/#comments</comments>
		<pubDate>Mon, 29 Dec 2008 23:01:34 +0000</pubDate>
		<dc:creator>warren</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://blog.hungrymachine.com/?p=2816</guid>
		<description><![CDATA[We&#8217;ve been hearing great things about Merb routing so a few weeks ago, we wanted to see if we could get it working in a Rails application as a proof of concept.  The goal of this project was to use the Merb routing engine along with router.rb and without touching any of our existing Rails [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve been hearing great things about Merb routing so a few weeks ago, we wanted to see if we could get it working in a Rails application as a proof of concept.  The goal of this project was to use the Merb routing engine along with router.rb and without touching any of our existing Rails application (i.e. anything in app/*).   Pre-existing URL route recognition needed to continue to work and all named routes and url_for logic needed to generate the same URLs as before.</p>
<p>With the <a href="http://weblog.rubyonrails.org/2008/12/23/merb-gets-merged-into-rails-3" target="_blank">announcement that Merb and Rails are merging</a>, we figured that it&#8217;d be a great time to share a little bit of what we learned.</p>
<h3>Background</h3>
<ul>
<li>We&#8217;re running Rails 2.2.2.</li>
<li>When we started messing with routes, we had 2500 generated routes (i.e. &#8220;rake routes | wc -l&#8221;).  After Aaron&#8217;s <a href="http://rails.lighthouseapp.com/projects/8994/tickets/1359-add-optional-format-argument-to-named-routes" target="_blank">formatted routes patch</a>, we had 1250.  We currently have over 1500.</li>
<li>Routing accounted for around 4 seconds out of 6 for ./script/console and mongrel_rails to start up.</li>
<li>Each mongrel_rails process was running at a minimum of 250mb in production.</li>
</ul>
<h3>Step 1: compiling</h3>
<p><em>Compiling is the first part of routing and involves loading an application&#8217;s routes.rb or router.rb and storing it in some way that allows for generation and recognition.</em></p>
<p>The merb_routing plugin contains a subset of merb-core&#8230; just the classes related to routes.  It shouldn&#8217;t be a surprise that these classes assume they are running in a Merb environment and not a Rails environment.  To successfully load these merb routing classes without drastically modifying the source, we wrote two small compatibility layers (mini-merb and mini-extlib) that provide some basic functionality that Merb and ExtLib provide (i.e. Merb.logger, Merb.root, etc).  This enabled us to successfully load the Merb::Router classes in our environment without any errors.</p>
<p>We then rewrote our routes.rb by hand using router.rb syntax.  We had to modify Merb routing slightly because we were getting &#8220;memory exhausted&#8221; compile errors.  It turned out that Merb routing uses a single if/elsif structure to recognize routes and due to our large number of routes, we hit a ruby quirk where you can&#8217;t have more than 2498 branches of logic in a single if-elsif statement.</p>
<blockquote><p><code>irb(main):001:0&gt; eval("if 1; #{"elsif 1;" * 2498} end")<br />
=&gt; nil<br />
irb(main):002:0&gt; eval("if 1; #{"elsif 1;" * 2499} end")<br />
SyntaxError: (eval):1:in `irb_binding': compile error<br />
(eval):1: memory exhausted</code></p></blockquote>
<p>The quick fix was using many single if statement with a return inside rather than one giant if-elsif.    After a few hooks into ActionController::Routing we had our environment using Merb/router.rb instead of Rails/routes.rb.</p>
<p>We had to make a few other minor changes to Merb routing to be compatible with rails:</p>
<ul>
<li>added support for { :method =&gt; :any } in routing conditions</li>
<li>added support for BLAH_index as a named route for singular resources (Rails creates a named route called &#8220;blog_index&#8221; instead of just &#8220;blog&#8221; for singular resources)</li>
</ul>
<p>Lastly, we wrote a rake task that overrides the default &#8220;rake routes&#8221; to pull from Merb routes instead of Rails routes.  At this point, we had the routes loaded and could see the objects in script/console.</p>
<h3>Step 2: recognizing</h3>
<p><em>Recognition is the second part of routing and happens at the beginning of every request.  It translates a URL into various parameters and figures out which controller/action to invoke for that request.</em></p>
<p>Once we had router.rb working correctly, route recognition and parameter loading was surprisingly easy to wire in.</p>
<h3>Step 3: generating</h3>
<p><em>Generation is the third part of routing and translates structured options into a URL string.  This happens every time you use url_for, a named route helper or redirect_to.</em></p>
<p>Generation was the trickiest part of this project and had the most edge cases.  Philosophically speaking, Merb and Rails route generation are very different.  Rails gives you named routes as helpers (person_path, person_url, etc) that you can use as well as a url_for() method which will search through all of the routes and find the best route given the options you provide.  Merb on the other hand provides a single method, url(), which all generation goes through.  If you don&#8217;t explicitly provide a named route, url() will use the default route (i.e. :controller/:action/:id) rather than looking for the &#8220;best route&#8221;.</p>
<p>Getting the named routes to work was pretty easy and only required a single method_missing catch-all for ActionController::Base and ActionView::Base.  Using a simple regexp, if the requested method ends in _url or _path, it uses Merb::Router#url and passes in the named route.</p>
<p>There was a bit of trickery involved in getting the path vs. url as well as the  :only_path stuff working correctly, but overall not too hard.</p>
<p>The last tricky piece was returning the best route instead of the default route when no named route was provided.  This is accomplished by looping through all of the available routes and determining which of the routes satisfies the most options passed in.  With 1500 routes, this turned out to be a bit slow, so some optimization ideas were borrowed from Rails and a cache is maintained of available routes given a controller/action.</p>
<h3>Conclusion</h3>
<p>We&#8217;ve been using this plugin successfully in production for the last month.  Our environment startup time as well as our memory overhead were both reduced drastically as soon as we put it in to production. We started this development when Rails 2.1 was the latest stable release and benchmarks against Rails 2.1 put Merb routing way ahead in just about every metric we tested.</p>
<p>The routing in Rails 2.2 was sped up substantially and is now comparable to Merb (Rails wins in some benchmarks, Merb in others).  <strong>BUT&#8230;. Merb still blows away rails in startup time, by 2-3x. </strong>We thought we could take out our merb-routing hacks and reduce code complexity, but after watching production restarts, we decided to put it back.</p>
<p>This plugin can be found on github: <a style="text-decoration: none;" href="http://github.com/hungrymachine/merb_routing/tree/master" target="_blank">merb_routing</a></p>
<p>UPDATE: after talking to Carl Lerche, it sounds like the new router refactoring he is working on will support both syntaxes on the same codebase. That&#8217;ll be very cool.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2008/12/29/merb-routing-in-rails/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Modular routing in rails and merb (acts_as_routing)</title>
		<link>http://blog.hungrymachine.com/2008/11/26/acts_as_routing-modular-routing-in-rails-and-merb/</link>
		<comments>http://blog.hungrymachine.com/2008/11/26/acts_as_routing-modular-routing-in-rails-and-merb/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 18:29:00 +0000</pubDate>
		<dc:creator>warren</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2008/11/26/acts_as_routing-modular-routing-in-rails-and-merb</guid>
		<description><![CDATA[Here&#8217;s a proof of concept plugin that will monkeypatch Rails or Merb routing to allow you to define &#8220;acts as blocks&#8221; anywhere throughout your application (i.e. a plugin) and then use them in your routes file.
Imagine the plugin acts_as_commentable defines the following in its init.rb:


ActionController::Routing.routes_for_acts_as(:commentable) do &#124;map&#124;
  map.resources :comments
  map.best_comment '/best-comment', :controller =&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a proof of concept plugin that will monkeypatch Rails or Merb routing to allow you to define &#8220;acts as blocks&#8221; anywhere throughout your application (i.e. a plugin) and then use them in your routes file.<br />
Imagine the plugin acts_as_commentable defines the following in its init.rb:</p>
<div class="CodeRay">
<div class="code">
<pre><span style="color:#036; font-weight:bold">ActionController</span>::<span style="color:#036; font-weight:bold">Routing</span>.routes_for_acts_as(<span style="color:#A60">:commentable</span>) <span style="color:#080; font-weight:bold">do</span> |map|
  map.resources <span style="color:#A60">:comments</span>
  map.best_comment <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">/best-comment</span><span style="color:#710">'</span></span>, <span style="color:#A60">:controller</span> =&gt; <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">comments</span><span style="color:#710">'</span></span>, <span style="color:#A60">:action</span> =&gt; <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">best</span><span style="color:#710">'</span></span>
<span style="color:#080; font-weight:bold">end</span></pre>
</div>
</div>
<p>If you added these :acts_as to your config/routes.rb:</p>
<div class="CodeRay">
<div class="code">
<pre><span style="color:#036; font-weight:bold">ActionController</span>::<span style="color:#036; font-weight:bold">Routing</span>::<span style="color:#036; font-weight:bold">Routes</span>.draw <span style="color:#080; font-weight:bold">do</span> |map|
  map.resources <span style="color:#A60">:people</span>, <span style="color:#A60">:acts_as</span> =&gt; [<span style="color:#A60">:commentable</span>]
  map.resources <span style="color:#A60">:posts</span>, <span style="color:#A60">:acts_as</span> =&gt; [<span style="color:#A60">:commentable</span>]
<span style="color:#080; font-weight:bold">end</span></pre>
</div>
</div>
<p>You could then use these routes throughout your application:</p>
<div class="CodeRay">
<div class="code">
<pre>  &lt;%=person_comments_path(<span style="color:#036; font-weight:bold">Person</span>.first)%&gt;
  &lt;%=post_comments_path(<span style="color:#036; font-weight:bold">Post</span>.first)%&gt;
  &lt;%=person_best_comment_path(<span style="color:#036; font-weight:bold">Person</span>.first)%&gt;</pre>
</div>
</div>
<p>This is equivalent to doing:</p>
<div class="CodeRay">
<div class="code">
<pre><span style="color:#036; font-weight:bold">ActionController</span>::<span style="color:#036; font-weight:bold">Routing</span>::<span style="color:#036; font-weight:bold">Routes</span>.draw <span style="color:#080; font-weight:bold">do</span> |map|
  map.resources <span style="color:#A60">:people</span> <span style="color:#080; font-weight:bold">do</span> |people_map|
    people_map.resources <span style="color:#A60">:comments</span>
    people_map.best_comment <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">/best-comment</span><span style="color:#710">'</span></span>, <span style="color:#A60">:controller</span> =&gt; <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">comments</span><span style="color:#710">'</span></span>, <span style="color:#A60">:action</span> =&gt; <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">best</span><span style="color:#710">'</span></span>
  <span style="color:#080; font-weight:bold">end</span>
  map.resources <span style="color:#A60">:posts</span> <span style="color:#080; font-weight:bold">do</span> |posts_map|
    posts_map.resources <span style="color:#A60">:comments</span>
    posts_map.best_comment <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">/best-comment</span><span style="color:#710">'</span></span>, <span style="color:#A60">:controller</span> =&gt; <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">comments</span><span style="color:#710">'</span></span>, <span style="color:#A60">:action</span> =&gt; <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">best</span><span style="color:#710">'</span></span>
  <span style="color:#080; font-weight:bold">end</span>
<span style="color:#080; font-weight:bold">end</span></pre>
</div>
</div>
<p>The plugin is available on github: <a href="http://github.com/hungrymachine/acts_as_routing/tree/master ">http://github.com/hungrymachine/acts_as_routing/tree/master</a></p>
<p>P.S. At some point, I&#8217;ll submit patches to Rails and Merb so this functionality is native rather than provided via a monkeypatching plugin.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2008/11/26/acts_as_routing-modular-routing-in-rails-and-merb/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>JRuby and why it might be nice to be back on the JVM &#8211; Part 2</title>
		<link>http://blog.hungrymachine.com/2008/11/21/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm-part-2/</link>
		<comments>http://blog.hungrymachine.com/2008/11/21/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm-part-2/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 07:47:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[jruby]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2008/11/21/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm-part-2</guid>
		<description><![CDATA[In the previous post, I did some JRuby testing and noticed perf improvements over time.
Mark Imbriaco, of 37Signals, asked how it compared to MRI. I was curious too.
I can&#8217;t promise a &#8220;clean&#8221; comparison, your mileage may vary, but&#8230; MRI was:

Completed in 552ms (View: 104, DB: 14) &#124; 200 OK [http://someurl.com/people/3]
Completed in 345ms (View: 60, DB: [...]]]></description>
			<content:encoded><![CDATA[<p>In the previous post, I did some <a href="http://blog.hungrymachine.com/2008/11/19/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm">JRuby testing</a> and noticed perf improvements over time.</p>
<p><a href="http://www.workingwithrails.com/person/6010-mark-imbriaco">Mark Imbriaco</a>, of 37Signals, asked how it compared to MRI. I was curious too.</p>
<p>I can&#8217;t promise a &#8220;clean&#8221; comparison, your mileage may vary, but&#8230; MRI was:</p>
<pre>
Completed in 552ms (View: 104, DB: 14) | 200 OK [http://someurl.com/people/3]
Completed in 345ms (View: 60, DB: <img src='http://blog.hungrymachine.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> | 200 OK [http://someurl.com/people/3]
Completed in 346ms (View: 60, DB: 4) | 200 OK [http://someurl.com/people/3]
Completed in 347ms (View: 56, DB: 4) | 200 OK [http://someurl.com/people/3]
Completed in 349ms (View: 58, DB: 5) | 200 OK [http://someurl.com/people/3]
</pre>
<p>Some stats on my runtime</p>
<pre>
$ java -version
java version "1.5.0_16"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_16-b06-284)
Java HotSpot(TM) Client VM (build 1.5.0_16-133, mixed mode, sharing)
$ ruby -v
ruby 1.8.6 (2008-08-11 patchlevel 287) [i686-darwin9.5.0]
</pre>
<p>Both ran on a MacBook 2.53GHz.  Likely the perf is better on Java6?</p>
<p>Installed <a href="http://support.apple.com/downloads/Java_for_Mac_OS_X_10_5_Update_1">Java6</a> and re-ran. Similar but better results.</p>
<pre>
Completed in 8815ms (View: 1632, DB: 429) | 200 OK [http://someurl.com/people/3]
Completed in 1017ms (View: 656, DB: 25) | 200 OK [http://someurl.com/people/3]
Completed in 998ms (View: 618, DB: 18) | 200 OK [http://someurl.com/people/3]
Completed in 1300ms (View: 437, DB: 35) | 200 OK [http://someurl.com/people/3]
Completed in 315ms (View: 119, DB: 21) | 200 OK [http://someurl.com/people/3]
Completed in 361ms (View: 140, DB: 20) | 200 OK [http://someurl.com/people/3]
</pre>
<p>Wow! Thats damn close to MRI&#8230;eventually&#8230; JRuby warmup time sucks though. Maybe warm it up during deploy before putting it back into the load balancer?  Not exactly sure how to warm it correctly though.  </p>
<p>If you just hit a URL on your app, you&#8217;ll only warm up THAT execution path&#8230; and you cant hit all actions, so&#8230;. thoughts?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2008/11/21/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm-part-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>JRuby and why it might be nice to be back on the JVM</title>
		<link>http://blog.hungrymachine.com/2008/11/19/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm/</link>
		<comments>http://blog.hungrymachine.com/2008/11/19/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm/#comments</comments>
		<pubDate>Wed, 19 Nov 2008 21:35:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[jruby]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2008/11/19/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm</guid>
		<description><![CDATA[We ported our Rails application to JRuby in order to do some GC comparisons yesterday.  Not a ton of changes required. Mostly replacing gems with native dependencies. YAML is a bit more strict than its MRI counterpart&#8230;. but all told, thats pretty amazing!  Nice job JRuby crew!
That said&#8230;. one interesting, entirely un-scientific, test [...]]]></description>
			<content:encoded><![CDATA[<p>We ported our Rails application to JRuby in order to do some GC comparisons yesterday.  Not a ton of changes required. Mostly replacing gems with native dependencies. YAML is a bit more strict than its MRI counterpart&#8230;. but all told, thats pretty amazing!  Nice job JRuby crew!</p>
<p>That said&#8230;. one interesting, entirely un-scientific, test case.  After requesting the same URL 6 times, the VM got a lot better. 3.4s to 480ms</p>
<pre>
Completed in 3380ms (View: 2739, DB: 65) | 200 OK [http://someurl.com/people/3]
Completed in 1299ms (View: 1211, DB: 18) | 200 OK [http://someurl.com/people/3]
Completed in 1020ms (View: 949, DB: 20) | 200 OK [http://someurl.com/people/3]
Completed in 852ms (View: 732, DB: 18) | 200 OK [http://someurl.com/people/3]
Completed in 743ms (View: 628, DB: 31) | 200 OK [http://someurl.com/people/3]
Completed in 485ms (View: 374, DB: 14) | 200 OK [http://someurl.com/people/3]
</pre>
<p>It doesnt appear to be the DB caching the data. That time stayed consistent.</p>
<p> I didnt use any crazy runtime flags.. Just jetty, a war file, and -server&#8230;. </p>
<p>If it was something we were memcaching, then after the 2nd request, it would have been consistent. </p>
<p>The amount of time spent in the view improved dramatically. </p>
<p>I didnt think JRuby leveraged JIT&#8217;ing yet.  Anyone care to guess/explain why it was significantly better per request?</p>
<p>Note: It did trail off in the 300ms range with further testing&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2008/11/19/jruby-and-why-it-might-be-nice-to-be-back-on-the-jvm/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Are your mongrels growing by 20MB/request on Rails 2.2? Blame AssetTag!</title>
		<link>http://blog.hungrymachine.com/2008/11/19/are-your-mongrels-growing-to-600mb-blame-assettag/</link>
		<comments>http://blog.hungrymachine.com/2008/11/19/are-your-mongrels-growing-to-600mb-blame-assettag/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 01:56:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[rails patches]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2008/11/19/are-your-mongrels-growing-to-600mb-blame-assettag</guid>
		<description><![CDATA[After porting our production application to Rails 2.2, we noticed a major memory leak.
Beforehand, monit would restart instances a handful of times a day.  After Rails 2.2, monit restarted instances THOUSANDS of times a day.
This is a graph of one of our haproxy instances a couple days ago.

We looked at everything, including time spent [...]]]></description>
			<content:encoded><![CDATA[<p>After porting our production application to Rails 2.2, we noticed a major memory leak.</p>
<p>Beforehand, monit would restart instances a handful of times a day.  After Rails 2.2, monit restarted instances THOUSANDS of times a day.</p>
<p>This is a graph of one of our haproxy instances a couple days ago.</p>
<p><center><img src="http://blog.hungrymachine.com/assets/2008/11/19/Picture_79.png" style="padding:10px;width:680px"></center></p>
<p>We looked at everything, including time spent <a href="http://blog.hungrymachine.com/2008/11/8/how-to-save-100m-of-ram-per-mongrel">rewriting</a> <a href="http://blog.hungrymachine.com/2008/11/11/how-to-save-100m-of-ram-per-mongrel-part-2">Routes</a>, thinking that was the culprit. </p>
<p>This morning, we all sat around and fought the issue old school style. binary debugging&#8230; and found it: AssetTagHelper. See the patch <a href="http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/1419-massive-memory-leak-in-assettag">here</a>.</p>
<p>The new thread-safe asset tag code keeps a static AssetTag::Cache = {}  of all asset_tags created (css,jss, and all images).</p>
<p>Internally, each AssetTag object keeps a reference to the controller and template objects, and in turn all instance variables you created in your request.  </p>
<p>What does that mean?  Say you have a people controller, that loads a person and their stuff, and you show images of their stuff via image_tag().</p>
<pre>
 class PeopleController < ApplicationController
   def show
     @person = Person.find(params[:id])
     @stuff = @people.stuff.find(:all, :limit => 30)
   end
 end
</pre>
<p> When image_tag() is called, it does rails magic to append file extensions, asset_ids, and the like.  To be smart, it caches those objects so it doesnt hit the file system<br />
to figure all that out on every request.  The problem is it puts it in a static cache, AssetTag::Cache.</p>
<p> So each PeopleController instance has a reference to 1 person and 30 Stuffs.  After 1000 people look at their pages, or better yet google crawls your site, you have 1k @controllers with a total of 1000 People Objects, and 1000*30 Stuff objects.  This would normally be fine.  The objects leave scope and get GC&#8217;ed. But, if you generate an image tag to an unique asset, AssetTag puts that into a cache, AssetTag::Cache, with a reference to the @controller of the request.  So All People and their Stuff are kept around forever, unable to be GC&#8217;ed&#8230;. every time a unique image is rendered via AssetTag. Eventually monit has to kill the process.</p>
<p>The <a href="http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/1419-massive-memory-leak-in-assettag">patch</a> we just submitted does 2 things.</p>
<p> 1) It now keeps a cache of just the modified path strings, caching the file access stuff.  If you have tons of local images, reference them by fully qualified host. Thats better for lots of reasons. Cookie-less asset hosts with multiple subdomains FTW!</p>
<p> 2) It stops caching absolute URL paths. You cant do anything on the filesystem to verify them, and keeping a cache of those would also grow unbounded. We have millions of items in our system, each with a reference to an image.</p>
<p>Here is a graph of that haproxy today&#8230;  Sleeping&#8230;&#8230;&#8230;</p>
<p><center><img src="http://blog.hungrymachine.com/assets/2008/11/19/Picture_80.png" style="padding:10px;width:680px"></center></p>
<p>In order to do some testing of your own, here&#8217;s a simplistic after_filter you can add to application.rb (or is it now application_controller.rb?). Make sure you run this in production mode or with cache_classes = true.  As you click around your site, you should see that the cache retains references to controller instances, just to name a few.  After you apply the patch, you&#8217;ll see the cache is just strings.</p>
<pre>
 def assettag_cache
    puts "-"*80
    puts "[AssetTag::Cache] Now #{ActionView::Helpers::AssetTagHelper::AssetTag::Cache.size} items"
    ActionView::Helpers::AssetTagHelper::AssetTag::Cache.values.each do |asset_tag|
      if asset_tag === ActionView::Helpers::AssetTagHelper::AssetTag
        puts "   [Asset] #{asset_tag.instance_variable_get("@source")}  #{asset_tag.instance_variable_get("@controller").class.to_s}"
      else
        puts "   [Asset] #{asset_tag}"
      end
    end
  end
</pre>
<p>Ohh&#8230; and we havent given up on routes&#8230; Warren is working on some very interesting enhancements to rails routing.  Looking forward to blogging about that soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2008/11/19/are-your-mongrels-growing-to-600mb-blame-assettag/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to save 100m of RAM per mongrel (Part 2)</title>
		<link>http://blog.hungrymachine.com/2008/11/11/how-to-save-100m-of-ram-per-mongrel-part-2/</link>
		<comments>http://blog.hungrymachine.com/2008/11/11/how-to-save-100m-of-ram-per-mongrel-part-2/#comments</comments>
		<pubDate>Tue, 11 Nov 2008 01:53:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2008/11/13/how-to-save-100m-of-ram-per-mongrel-part-2</guid>
		<description><![CDATA[UPDATE I&#8217;ve added a patch to Rails Edge for this fix, which is much different than the patch below.  See here
In a previous article, I called out the massive memory usage of the default rails resource behavior, and it seems others have as well.  In an attempt to decrease the number of routes, [...]]]></description>
			<content:encoded><![CDATA[<p><b>UPDATE</b> I&#8217;ve added a patch to Rails Edge for this fix, which is much different than the patch below.  See <a href="http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/1359-add-optional-format-argument-to-named-routes#ticket-1359-5">here</a></p>
<p>In a <a href="http://blog.hungrymachine.com/2008/11/8/how-to-save-100m-of-ram-per-mongrel">previous article</a>, I called out the massive memory usage of the default rails resource behavior, and it seems <a href="http://rails.lighthouseapp.com/projects/8994/tickets/1215-add-actions-and-formatted-options-to-mapresources#ticket-1215-18">others</a> have as well.  In an attempt to decrease the number of routes, I commented out the &#8220;formatted_*&#8221; routes, and manually entered them back by hand.</p>
<p>But after some internal discussion/testing with Warren, we realized that was sloppy and error prone.  Instead, I hacked Routing segments to allow for an optional format segment, so that formatted routes and normal routes are shared.  The one downside, from what I can tell so far, is you lose &#8220;formatted_*&#8221; named routes + url helpers for those routes, but passing format to a url_for still works</p>
<pre>
   person_path(:id => 1, :format => "json") =>  /people/1.json
</pre>
<p> In the below gist, you&#8217;ll see a OptionalFormatSegment, which sneakily gets around the &#8216;.&#8217; regex separator, removes the formatted_* named routes added by default, and should be the same solution as the previous post, but without the need to manually put all the routes back in.  </p>
<p><script src="http://gist.github.com/23712.js"></script></p>
<p>I&#8217;m still testing this approach, but am interested in what other folks think.</p>
<p><b>Note:</b> This monkey-patch only works on Rails 2.2</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2008/11/11/how-to-save-100m-of-ram-per-mongrel-part-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>How to save 100m of RAM per mongrel</title>
		<link>http://blog.hungrymachine.com/2008/11/08/how-to-save-100m-of-ram-per-mongrel/</link>
		<comments>http://blog.hungrymachine.com/2008/11/08/how-to-save-100m-of-ram-per-mongrel/#comments</comments>
		<pubDate>Sat, 08 Nov 2008 22:20:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[ruby rails]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2008/11/19/how-to-save-100m-of-ram-per-mongrel</guid>
		<description><![CDATA[UPDATE: See  Part 2 of this for a better solution
Note: This monkey-patch only works on Rails 2.2
We recently noticed our mongrels, upon startup, were 244M.  Eek. 

PID USER            PR  NI  VIRT  RES  SHR S %CPU %MEM   [...]]]></description>
			<content:encoded><![CDATA[<p><b>UPDATE:</b> See  <a href="http://blog.hungrymachine.com/2008/11/11/how-to-save-100m-of-ram-per-mongrel-part-2">Part 2</a> of this for a better solution</p>
<p><b>Note:</b> This monkey-patch only works on Rails 2.2</p>
<p>We recently noticed our mongrels, upon startup, were 244M.  Eek. </p>
<pre>
PID USER            PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
53749 some_user     15   0  337m 244m 2912 S    0  2.0   0:17.49 mongrel_rails
</pre>
<p>Running <a href="http://blog.evanweaver.com/files/doc/fauna/bleak_house/files/README.html">Bleakhouse</a> on our rails app, i was amazed at the number of objects created.  over 2M!</p>
<pre>
$ BLEAK_HOUSE=1 ruby-bleak-house ./script/runner 'puts 1'
** Bleakhouse: installed
1
** BleakHouse: working...
** BleakHouse: complete
** Bleakhouse: Run 'bleak /tmp/bleak.53749.0.dump' to analyze.

$ bleak /tmp/bleak.53749.0.dump
Displaying top 20 most common line/class pairs
2,047,025 total objects
2,047,025 filled heap slots
2,403,764 free heap slots
1779063 __null__:__null__:__node__
197423 __null__:__null__:String
16519 __null__:__null__:Array
12728 __null__:__null__:ActionController::Routing::DividerSegment
10495 __null__:__null__:Hash
5676 __null__:__null__:ActionController::Routing::StaticSegment
5436 __null__:__null__:Class
5132 __null__:__null__:Regexp
4525 __null__:__null__:ActionController::Routing::DynamicSegment
2524 __null__:__null__:ActionController::Routing::Route
1307 __null__:__null__:Gem::Version
</pre>
<p>Whats up with all those routing objects! So i tried a blank routes.rb file&#8230;.</p>
<pre>
519,307 total objects
519,307 filled heap slots
233,503 free heap slots
</pre>
<p>Arghh&#8230;.  1.5M objects just because of routes.rb. I know our application is large, lots of resources and nested resources, but thats crazy.  </p>
<pre>
$ rake routes | wc -l
2516
</pre>
<p>Ok, so taking a closer look, I realized something. Each resource route has a corresponding formatted_* route, lots of which we dont use. So now for some nasty monkey-patching.</p>
<pre>
ActionController::Routing::RouteSet::Mapper.class_eval do
protected

  def map_unnamed_routes(map, path_without_format, options)
    map.connect(path_without_format, options)
    #map.connect("#{path_without_format}.:format", options)
  end

  def map_named_routes(map, name, path_without_format, options)
    map.named_route(name, path_without_format, options)
    #map.named_route("formatted_#{name}", "#{path_without_format}.:format", options)
  end
end
</pre>
<p>I then manually added back the formatted routes we needed, careful to use named routes as &#8220;map.formatted_foo_bar&#8221;</p>
<pre>
$ rake routes | wc -l
1490
</pre>
<pre>
$ bleak /tmp/bleak.56554.0.dump
1,242,796 total objects
1,242,796 filled heap slots
1,224,309 free heap slots
</pre>
<p>Awesome.  I no longer create almost 800k objects. </p>
<pre>
PID USER            PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
56554 someuser     15   0  249m 156m 2912 S    0  1.3   0:09.92 mongrel_rails
</pre>
<p><b>244m</b> &#8211;> <b>156m</b></p>
<p>This is not a very elegant solution&#8230; but I saved almost 100m per mongrel. Ohh.. and it reduced startup time by 50%.</p>
<p>How big are your mongrels?</p>
<p>How does Merb&#8217;s router differ from Rails routing? Worth investigating?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2008/11/08/how-to-save-100m-of-ram-per-mongrel/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>MRI Ruby + MySQL + Threads == Stop the world&#8230; JRuby doesn&#8217;t</title>
		<link>http://blog.hungrymachine.com/2008/08/27/ruby-and-multi-threaded-mysql-mri-vs-jruby-jdbc-vs-dataobjects-mysql/</link>
		<comments>http://blog.hungrymachine.com/2008/08/27/ruby-and-multi-threaded-mysql-mri-vs-jruby-jdbc-vs-dataobjects-mysql/#comments</comments>
		<pubDate>Wed, 27 Aug 2008 15:04:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[mri]]></category>
		<category><![CDATA[threading]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2008/11/13/ruby-and-multi-threaded-mysql-mri-vs-jruby-jdbc-vs-dataobjects-mysql</guid>
		<description><![CDATA[As we have been internally discussing how to scale our databases from 10&#8217;s of millions of rows to 100&#8217;s of millions, database sharding came up.  
Depending on your data model and your application, sharding data into tables by some natural key is great if any given request uses only one shard. FiveRun&#8217;s DataFabric seems [...]]]></description>
			<content:encoded><![CDATA[<p>As we have been internally discussing how to scale our databases from 10&#8217;s of millions of rows to 100&#8217;s of millions, database sharding came up.  </p>
<p>Depending on your data model and your application, sharding data into tables by some natural key is great if any given request uses only one shard. FiveRun&#8217;s <a href="http://blog.fiveruns.com/2008/7/9/introducing-data_fabric">DataFabric</a> seems to help with that.  Its obviously best to shard the data in the most used way, but occasionally you&#8217;ll need to write broadcast queries across shards.  It&#8217;d be even better if those broadcast queries were executed concurrently. Well, apparently, its not that simple in MRI Ruby.</p>
<p>The mysql (2.7) gem stop&#8217;s the world while executing a query. A sloppy but reproducible test is <a href="http://pastie.org/248044">here</a>.  This is not a mutex lock on the re-use of a single connection object.  Eddie also reached out to the <a href="http://sequel.rubyforge.org/">Sequel</a> maintainer, who agrees it is likely due &#8220;to the fact that the C drivers don&#8217;t release the interpreter lock while they wait for a response from the server.&#8221; JRuby, or more accurately JDBC, acts as expected.  We even tested <a href="http://datamapper.org/">DataMapper</a>&#8217;s DataObjects::MySQL, as it appears they&#8217;ve re-implemented the mysql gem.   Unfortunately it suffers from the same stop-the-world issue.  </p>
<pre>
$ ruby mysql_locking_test.rb
Loading MRI MySQL
Serial: 4.00969815254211s
Multi-threaded: 4.00785183906555s

$ data_mapper=true ruby mysql_locking_test.rb
Loading DataMapper
Serial: 4.01330804824829s
Multi-threaded: 4.01132893562317s

$ jruby mysql_locking_test.rb
Loading JDBC-MySQL
Serial: 4.2802369594573975s
Multi-threaded: 1.0499329566955566s
</pre>
<p>Only in JRuby was the multi-threaded != sequential time, as expected. </p>
<p>Potentially unrelated, no one has touched the mysql gem in 3 years?!?!  </p>
<pre>
$ gem spec -v 2.7 mysql | grep date
date: 2005-10-09 00:00:00 +00:00
</pre>
<p>So even Ruby ORM frameworks (Sequel, DataMapper) that say they&#8217;re thread-safe, are not concurrent on MRI&#8230; at least for mysql.  For folks not using Rails, which already has a mutex lock higher in the stack, this must be a performance issue.  For example,  Merb + DataMapper + MySQL.  If there is a 2s SQL query, all threads in that process stop for 2s.  </p>
<p>Can others verify?   &#8220;select sleep(2) from dual;&#8221; is a great way to test for this.</p>
<p><b>UPDATE:</b> Multiple have asked, so to clarify.  The sample code  <a href="http://pastie.org/248044">here</a> creates a new connection PER thread.  The mysql <a href="http://dev.mysql.com/doc/refman/5.0/en/threaded-clients.html">docs</a> states: &#8220;Two threads can&#8217;t send a query to the MySQL server at the same time on the same connection&#8221;, but the test is creating a new connection object per thread, so that should not apply.  </p>
<p><b>UPDATE 2:</b> A couple folks have mentioned asynch drivers.  One for <a href="http://github.com/oldmoe/mysqlplus ">mysql</a> and one for postgres, but I believe they&#8217;re based on <a href="http://www.espace.com.eg/neverblock/">NeverBlock</a>, which is Ruby 1.9 only.  That sounds like awesome progress. What&#8217;s the realistic ETA for folks running 1.9 in a production environment?  At least until Christmas for a 1.9 official release?  </p>
<p><b>UPDATE 3:</b> Looks like lots is happening here.  There now is a mysql driver that supports async/threaded operations on 1.8!  See the <a href="http://www.espace.com.eg/neverblock/blog/2008/08/28/neverblock-mysql-support/">NeverBlock MySQL</a> project.  Looking forward to testing this in a production environment.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2008/08/27/ruby-and-multi-threaded-mysql-mri-vs-jruby-jdbc-vs-dataobjects-mysql/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Cleaning up old releases</title>
		<link>http://blog.hungrymachine.com/2008/06/04/cleaning-up-old-releases/</link>
		<comments>http://blog.hungrymachine.com/2008/06/04/cleaning-up-old-releases/#comments</comments>
		<pubDate>Wed, 04 Jun 2008 20:12:00 +0000</pubDate>
		<dc:creator>val</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Ops]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[cleanup]]></category>
		<category><![CDATA[releases]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2008/07/19/cleaning-up-old-releases</guid>
		<description><![CDATA[Instead of relaying on running cleanup of old releases via capistrano, we have a cron job to only keep releases for last two days (but at least three latest).


#!/usr/bin/env ruby

require 'fileutils'

KEEP_RELEASES = 3
KEEP_DAYS = 2
EXCLUDE_APPS = %W(uploadr)

cut_time = (Time.now.utc - KEEP_DAYS*24*60*60).strftime(&#34;%Y%m%d%H%M%S&#34;).to_i

Dir['/u/apps/*'].each do &#124;app&#124;
  next if EXCLUDE_APPS.include?(File.basename(app))
  dirs = Dir[&#34;#{ app }/releases/*&#34;]
  fresh [...]]]></description>
			<content:encoded><![CDATA[<p>Instead of relaying on running cleanup of old releases via capistrano, we have a cron job to only keep releases for last two days (but at least three latest).</p>
<div class="CodeRay">
<div class="code">
<pre><span style="color:#888">#!/usr/bin/env ruby</span>

require <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">fileutils</span><span style="color:#710">'</span></span>

<span style="color:#036; font-weight:bold">KEEP_RELEASES</span> = <span style="color:#00D; font-weight:bold">3</span>
<span style="color:#036; font-weight:bold">KEEP_DAYS</span> = <span style="color:#00D; font-weight:bold">2</span>
<span style="color:#036; font-weight:bold">EXCLUDE_APPS</span> = <span style="background-color:#fff0f0"><span style="color:#710">%W(</span><span style="color:#D20">uploadr</span><span style="color:#710">)</span></span>

cut_time = (<span style="color:#036; font-weight:bold">Time</span>.now.utc - <span style="color:#036; font-weight:bold">KEEP_DAYS</span>*<span style="color:#00D; font-weight:bold">24</span>*<span style="color:#00D; font-weight:bold">60</span>*<span style="color:#00D; font-weight:bold">60</span>).strftime(<span style="background-color:#fff0f0"><span style="color:#710">&quot;</span><span style="color:#D20">%Y%m%d%H%M%S</span><span style="color:#710">&quot;</span></span>).to_i

<span style="color:#036; font-weight:bold">Dir</span>[<span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">/u/apps/*</span><span style="color:#710">'</span></span>].each <span style="color:#080; font-weight:bold">do</span> |app|
  <span style="color:#080; font-weight:bold">next</span> <span style="color:#080; font-weight:bold">if</span> <span style="color:#036; font-weight:bold">EXCLUDE_APPS</span>.include?(<span style="color:#036; font-weight:bold">File</span>.basename(app))
  dirs = <span style="color:#036; font-weight:bold">Dir</span>[<span style="background-color:#fff0f0"><span style="color:#710">&quot;</span><span style="background-color:#fff0f0"><span style="color:#710">#{</span> app <span style="color:#710">}</span></span><span style="color:#D20">/releases/*</span><span style="color:#710">&quot;</span></span>]
  fresh = dirs.select { |dir| (dir.split(<span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">/</span><span style="color:#710">'</span></span>).last).to_i &gt; cut_time }
  latest = dirs.sort.last(<span style="color:#036; font-weight:bold">KEEP_RELEASES</span> )

  (dirs - fresh - latest).each <span style="color:#080; font-weight:bold">do</span> |dir|
    <span style="color:#036; font-weight:bold">FileUtils</span>.rm_rf dir
  <span style="color:#080; font-weight:bold">end</span>
<span style="color:#080; font-weight:bold">end</span></pre>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2008/06/04/cleaning-up-old-releases/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The End of Slideshows: Animoto</title>
		<link>http://blog.hungrymachine.com/2008/05/13/the-end-of-slideshows-animoto/</link>
		<comments>http://blog.hungrymachine.com/2008/05/13/the-end-of-slideshows-animoto/#comments</comments>
		<pubDate>Tue, 13 May 2008 21:29:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[animoto]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2008/11/13/the-end-of-slideshows-animoto</guid>
		<description><![CDATA[UPDATE:  Animoto just raised a round of  investment from Amazon! Congrats Guys! 
Animoto is a great idea.  They take your photos and create a production quality video to the music of your choice.  Its the end of those boring slide shows, for good.  


(From a recent Techcrunch article here)


We had [...]]]></description>
			<content:encoded><![CDATA[<p>UPDATE:  Animoto just raised a <a href="http://www.techcrunch.com/2008/05/15/amazon-funds-animoto-music-video-creator/">round of  investment</a> from Amazon! Congrats Guys! </p>
<p><a href="http://www.animoto.com">Animoto</a> is a great idea.  They take your photos and create a production quality video to the music of your choice.  Its the end of those boring slide shows, for good.  </p>
<p><div style="text-align: center;">
<object id="W47d804cf2a603f89" width="432" height="250" quality="high" data="http://widgets.clearspring.com/o/46928cc51133af17/47d804cf2a603f89" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="opaque"><param name="wmode" value="opaque" /><param name="movie" value="http://widgets.clearspring.com/o/46928cc51133af17/47d804cf2a603f89" /><param name="scaleMode" value="showAll" /><param name="allowNetworking" value="all" /><param name="allowScriptAccess" value="always" /><param name="flashvars" value="" /></object><br/><br />
<span style="font-size:10px">(From a recent Techcrunch article <a href="http://www.techcrunch.com/2008/03/12/animoto-rocks-automatically-turns-your-photos-into-a-music-video-slide-show/">here</a>)</span>
</div>
</p>
<p>We had the pleasure to work with the Animoto guys to launch their Facebook application, <a href="http://apps.facebook.com/animoto">&#8220;Animoto Videos&#8221;</a>, which leveraged all of the existing photos on Facebook. The growth was amazing.</p>
<div style="text-align:center">
<img src="http://www.allfacebook.com/images/animoto-screenshot.gif"/><br/><br />
<span style="font-size:10px">(From a recent AllFacebook article <a href="http://www.allfacebook.com/2008/03/animoto-challenges-slide-on-facebook/">here</a>)</span>
</div>
<p>Scaling an application from a few hundred users to over a million in just a few days isnt easy, but we had a great team.  Their backend rendering farm lived in Amazon&#8217;s Cloud, and the growth was so impressive, Jeff Bezos even spoke about them at Y Combinator’s <a href="http://www.startupschool.org/">Startup School</a> just a few weeks ago.  From 50 EC2 instances to over 4k in only a few days. See the video below.  </p>
<div style="text-align: center;">
<object width='520' height='276'><param name='movie' value='http://www.omnisio.com/bin/Embed.swf?embedID=b6gTwEirOr3zt0adbiFy2w&#038;autoPlay=0' /><param name='bgcolor' value='#FFFFFF' /><param name='quality' value='high' /><param name='allowscriptaccess' value='always' /><param name='allowfullscreen' value='true' /><embed type='application/x-shockwave-flash' name='omnisio_video_b6gTwEirOr3zt0adbiFy2w' src='http://www.omnisio.com/bin/Embed.swf?embedID=b6gTwEirOr3zt0adbiFy2w&#038;autoPlay=0' bgcolor='#FFFFFF' quality='high' allowfullscreen='true' allowscriptaccess='always' width='520' height='276' ><noembed>
<div><a href='http://www.omnisio.com'>Share and annotate your videos</a> with Omnisio!</div>
<p></noembed></embed></object>
</div>
<p> It was a pleasure working with the entire team from Animoto, RightScale, and Amazon.  See their blog posts about the application <a href="http://blog.animoto.com/2008/04/21/amazon-ceo-jeff-bezos-on-animoto/">here</a>,  <a href="http://blog.rightscale.com/2008/04/23/animoto-facebook-scale-up/">here</a>, and <a href="http://aws.typepad.com/aws/2008/04/animoto---scali.html">here</a>.  </p>
<p>I&#8217;m sure I&#8217;ll cross paths with many of you at RailsConf.  First round of beers is on me.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2008/05/13/the-end-of-slideshows-animoto/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
