<?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; All</title>
	<atom:link href="http://blog.hungrymachine.com/category/all/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>Sorry Mephisto.. Moving to WordPress</title>
		<link>http://blog.hungrymachine.com/2008/12/09/sorry-mephisto-moving-to-wordpress/</link>
		<comments>http://blog.hungrymachine.com/2008/12/09/sorry-mephisto-moving-to-wordpress/#comments</comments>
		<pubDate>Tue, 09 Dec 2008 18:56:21 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog2.hungrymachine.com/2008/12/09/sorry-mephisto-moving-to-wordpress/</guid>
		<description><![CDATA[Dear Mephisto, you&#8217;ve been great. We&#8217;ve been dating for a while, and I didnt have any complaints. but I&#8217;m sorta sick of writing blog posts in your web UI. I heard there are plugins for 0.8 for metaweblog api support, but after putzing around with rails 2.0 vs 2.2, etc&#8230; I decided to break up [...]]]></description>
			<content:encoded><![CDATA[<blockquote style="clear: both"><p>Dear Mephisto, you&#8217;ve been great. We&#8217;ve been dating for a while, and I didnt have any complaints. but I&#8217;m sorta sick of writing blog posts in your web UI. I heard there are plugins for 0.8 for metaweblog api support, but after putzing around with rails 2.0 vs 2.2, etc&#8230; I decided to break up with you. It&#8217;s really because I wanted to play with <a href="http://www.drinkbrainjuice.com/blogo" target="_blank">blogo</a>. No hard feelings. Lets be friends.</p></blockquote>
<blockquote style="clear: both"><p>Hi WordPress. How are you?</p></blockquote>
<p style="clear: both">We just ported our blog to WordPress. To import all our old content, I found <a href="http://schwuk.com/articles/2008/03/25/thy-will-be-done-m2wppy-is-released" target="_blank">m2wp.pl</a>, which after adding some mysql patches, does a great job of generating a wordpress export file that imports perfectly from the WP admin UI. It was missing a few features, like correct author attribution, so I make some tweaks and put it on <a href="http://github.com/hungrymachine/mephisto_to_wordpress/tree/master" target="_blank">github</a> if anyone is interested.</p>
<p style="clear: both">BTW, whats blogo?</p>
<p style="clear: both"><a class="image-link" href="http://twitter.com/lrz/status/1041024849"><img style=" text-align: center; display: block; margin: 0 auto 10px;" src="http://blog.hungrymachine.com/wp-content/uploads/2008/12/picture-32.png" alt="" width="400" height="168" /></a>Sor far I like.</p>
<p style="clear: both">One feature request for us techies, an easy TextMate &#8220;insert code here&#8221; feature.</p>
<p style="clear: both">UPDATE: don&#8217;t forget to cp your assets.</p>
<p><br class="final-break" style="clear: both" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2008/12/09/sorry-mephisto-moving-to-wordpress/feed/</wfw:commentRss>
		<slash:comments>3</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>Using helpers in a controller: with_helpers</title>
		<link>http://blog.hungrymachine.com/2008/08/07/using-helpers-in-a-controller-with_helpers/</link>
		<comments>http://blog.hungrymachine.com/2008/08/07/using-helpers-in-a-controller-with_helpers/#comments</comments>
		<pubDate>Thu, 07 Aug 2008 13:49:00 +0000</pubDate>
		<dc:creator>warren</dc:creator>
				<category><![CDATA[All]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2008/08/07/using-helpers-in-a-controller-with_helpers</guid>
		<description><![CDATA[Although there is supposed to be a clear separation between views and controllers, often when it comes to helper functions, there is a small bit of overlap and there are situations where it&#8217;d be nice to simply use a few helpers from inside an action.


ActionController::Base.class_eval do
  def with_helpers(&#38;block)
    template = ActionView::Base.new([],{},self)
 [...]]]></description>
			<content:encoded><![CDATA[<p>Although there is supposed to be a clear separation between views and controllers, often when it comes to helper functions, there is a small bit of overlap and there are situations where it&#8217;d be nice to simply use a few helpers from inside an action.</p>
<div class="CodeRay">
<div class="code">
<pre><span style="color:#036; font-weight:bold">ActionController</span>::<span style="color:#036; font-weight:bold">Base</span>.class_eval <span style="color:#080; font-weight:bold">do</span>
  <span style="color:#080; font-weight:bold">def</span> <span style="color:#06B; font-weight:bold">with_helpers</span>(&amp;block)
    template = <span style="color:#036; font-weight:bold">ActionView</span>::<span style="color:#036; font-weight:bold">Base</span>.new([],{},<span style="color:#038; font-weight:bold">self</span>)
    template.extend <span style="color:#038; font-weight:bold">self</span>.class.master_helper_module
    add_variables_to_assigns
    template.assigns = <span style="color:#33B">@assigns</span>
    template.send(<span style="color:#A60">:assign_variables_from_controller</span>)
    forget_variables_added_to_assigns
    template.instance_eval(&amp;block)
  <span style="color:#080; font-weight:bold">end</span>
<span style="color:#080; font-weight:bold">end</span></pre>
</div>
</div>
<p>Here is what it looks like in a controller.  Although this is a non-sensical example, it shows off how you can use a helper (i.e. link_to) in an action. It also shows how the instance variables (i.e. @person) set in the action are available in the with_helpers block&#8230; the same way that instance variables are available in views.</p>
<div class="CodeRay">
<div class="code">
<pre><span style="color:#080; font-weight:bold">class</span> <span style="color:#B06; font-weight:bold">MyController</span> &lt; <span style="color:#036; font-weight:bold">ApplicationController</span>
  <span style="color:#080; font-weight:bold">def</span> <span style="color:#06B; font-weight:bold">my_action</span>
    <span style="color:#33B">@person</span> = <span style="color:#036; font-weight:bold">Person</span>.find(params[<span style="color:#A60">:id</span>])
    render <span style="color:#A60">:text</span> =&gt; with_helpers { link_to(<span style="color:#33B">@person</span>.full_name, person_path(<span style="color:#33B">@person</span>)) }
  <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/08/07/using-helpers-in-a-controller-with_helpers/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Breaking the Rails static asset timestamp cache in development mode</title>
		<link>http://blog.hungrymachine.com/2008/06/21/breaking-the-rails-static-asset-timestamp-cache-in-development-mode/</link>
		<comments>http://blog.hungrymachine.com/2008/06/21/breaking-the-rails-static-asset-timestamp-cache-in-development-mode/#comments</comments>
		<pubDate>Sat, 21 Jun 2008 18:11:00 +0000</pubDate>
		<dc:creator>warren</dc:creator>
				<category><![CDATA[All]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2008/11/13/breaking-the-rails-static-asset-timestamp-cache-in-development-mode</guid>
		<description><![CDATA[Rails automatically adds the File.mtime to static assets when using stylesheet_link_tag and javascript_include_tag.  The file&#8217;s mtime is cached to prevent excessive file system access&#8230; even in development mode.  This is problematic in a Facebook canvas during development mode because often you won&#8217;t immediately see the changes you make to your stylesheets and javascripts.
Here [...]]]></description>
			<content:encoded><![CDATA[<p>Rails automatically adds the File.mtime to static assets when using stylesheet_link_tag and javascript_include_tag.  The file&#8217;s mtime is cached to prevent excessive file system access&#8230; even in development mode.  This is problematic in a Facebook canvas during development mode because often you won&#8217;t immediately see the changes you make to your stylesheets and javascripts.</p>
<p>Here is a monkey patch you can throw into a config/initializers/break_asset_cache_in_dev_mode.rb to fix this:</p>
<div class="CodeRay">
<div class="code">
<pre><span style="color:#080; font-weight:bold">if</span> <span style="color:#036; font-weight:bold">RAILS_ENV</span> == <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">development</span><span style="color:#710">'</span></span>
  require <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">action_controller/dispatcher</span><span style="color:#710">'</span></span>
  <span style="color:#036; font-weight:bold">ActionController</span>::<span style="color:#036; font-weight:bold">Dispatcher</span>.before_dispatch <span style="color:#080; font-weight:bold">do</span>
    <span style="color:#036; font-weight:bold">ActionView</span>::<span style="color:#036; font-weight:bold">Base</span>.computed_public_paths.clear
  <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/21/breaking-the-rails-static-asset-timestamp-cache-in-development-mode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
