<?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"
	>

<channel>
	<title>Misuse</title>
	<atom:link href="http://www.misuse.org/science/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.misuse.org/science</link>
	<description>It would be a good idea.</description>
	<pubDate>Sat, 26 Apr 2008 20:23:43 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>For the differently evolved</title>
		<link>http://www.misuse.org/science/2008/04/08/for-the-differently-evolved/</link>
		<comments>http://www.misuse.org/science/2008/04/08/for-the-differently-evolved/#comments</comments>
		<pubDate>Wed, 09 Apr 2008 03:46:34 +0000</pubDate>
		<dc:creator>science</dc:creator>
		
		<category><![CDATA[Misusing]]></category>

		<guid isPermaLink="false">http://www.misuse.org/science/2008/04/08/for-the-differently-evolved/</guid>
		<description><![CDATA[
(from American Scientist magazine, Mar-Apr 2008)
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.americanscientist.org/" target="_blank"><img src="http://www.misuse.org/science/wp-content/uploads/2008/04/ladybug.jpg" alt="Cartoon from New Scientist" /></a></p>
<p><em>(from <a href="http://www.americanscientist.org/" target="_blank">American Scientist magazine</a>, Mar-Apr 2008)</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.misuse.org/science/2008/04/08/for-the-differently-evolved/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Thin vs. Mongrel: A Ruby on Rails performance shootout</title>
		<link>http://www.misuse.org/science/2008/04/07/thin-vs-mongrel-a-ruby-on-rails-performance-shootout/</link>
		<comments>http://www.misuse.org/science/2008/04/07/thin-vs-mongrel-a-ruby-on-rails-performance-shootout/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 06:01:30 +0000</pubDate>
		<dc:creator>science</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.misuse.org/science/2008/04/07/thin-vs-mongrel-a-ruby-on-rails-performance-shootout/</guid>
		<description><![CDATA[
Previously Science and wayneseguin published a study looking at the performance of nginx fair proxy. To take that a little further, Science conducted an examination of how Thin and Mongrel compare head-to-head on performance. For kicks we took a look at Rails page template caching facility to see if that significantly impacts performance (it does). [...]]]></description>
			<content:encoded><![CDATA[<p><a title="Graph of nothing" href="http://www.misuse.org/science/2008/04/07/thin-vs-mongrel-a-ruby-on-rails-performance-shootout/"><img src="http://www.misuse.org/science/wp-content/uploads/2008/04/logarithm.thumbnail.gif" alt="Graph of nothing" /></a></p>
<p>Previously Science and wayneseguin published <a href="http://www.misuse.org/science/2008/04/07/thin-ruby-on-rails-nginx-fair-proxy-performance-testing/" target="_blank">a study</a> looking at the performance of <a href="http://wiki.codemongers.com/Main" target="_blank">nginx </a>fair proxy. To take that a little further, Science conducted an examination of how <a href="http://code.macournoyer.com/thin/" target="_blank">Thin </a>and <a href="http://mongrel.rubyforge.org/" target="_blank">Mongrel</a> compare head-to-head on performance. For kicks we took a look at Rails page template caching facility to see if that significantly impacts performance (it does). Full details follow..</p>
<p><span id="more-126"></span></p>
<p>For an idea of what the h/w testing setup looked like, read the previous study (cited above). For these tests, we used 3 instances of Thin or Mongrel (with lots of free ram). nginx fair proxy was turned on. Rails caching was fully enabled (including template caching). The tests all ran for 300 seconds. We pulled HEAD requests only to minimize over the wire throughput variance (since the test were initiated remote of the data center). Thins were wired up to unix sockets and Mongrels were going over IP.</p>
<p>Overall, I&#8217;d say that under these testing conditions Thin is 4% faster than Mongrel. That&#8217;s not much, and it&#8217;s within the standard deviation of each test result, but it was pretty consistent throughout the testing so I&#8217;m inclined to believe it. Your results may vary. [1]</p>
<p>Here is the summary of results:</p>
<table border="1">
<tbody>
<tr>
<th>Server type</th>
<th>Avg response (s)</th>
<th>Total pages (#)</th>
<th>90% max response (s)</th>
</tr>
<tr>
<td>Thins, 10 threads</td>
<td>1.72</td>
<td>1734</td>
<td>3.92</td>
</tr>
<tr>
<td>Mongrels, 10 threads</td>
<td>1.78</td>
<td>1677</td>
<td>3.31</td>
</tr>
<tr>
<td>Thins, 30 threads</td>
<td>5.08</td>
<td>1738</td>
<td>10.14</td>
</tr>
<tr>
<td>Mongrels, 30 threads</td>
<td>5.20</td>
<td>1709</td>
<td>10.86</td>
</tr>
<tr>
<td>Thins, 40 threads</td>
<td>6.69</td>
<td>1753</td>
<td>10.97</td>
</tr>
<tr>
<td>Mongrels, 40 threads</td>
<td>6.98</td>
<td>1685</td>
<td>13.39</td>
</tr>
</tbody>
</table>
<p>The full test results (including Standard Deviations) can be found <a href="http://www.misuse.org/downloads/thin_mongrel_test_results.html" target="_blank">here</a>. We hope the provided measurements meet your requirements. Post a comment here if you&#8217;d like more information or background.</p>
<hr />End Notes</p>
<ol>
<li>While I thought that much of the performance improvements could be <a href="http://archives.postgresql.org/pgsql-general/2001-01/msg01419.php" target="_blank">attributed to the unix sockets </a>themselves, <a href="http://archives.postgresql.org/pgsql-general/2001-01/msg01388.php" target="_blank">many knowledgeable folks</a> including Zed (author of Mongrel) and Marc (author of Thin) assert that performance of IP vs Sockets is really marginal in this day and age. Both Zed and Marc have indicated that any performance differences are probably due to code and architecture differences in the app servers themselves.</li>
<li>You may also find this study of performance of various ruby app servers interesting: <a href="http://wiki.codemongers.com/Main" target="_blank">http://wiki.codemongers.com/Main</a></li>
<li>Science also has a writeup on <a href="http://www.misuse.org/science/2008/02/22/rails-page-caching-nginx-ssi-ajax-and-form-posts/" target="_blank">optimizing Nginx and Rails page caching </a>which may be of interest to readers.</li>
</ol>
<hr /><span style="text-decoration: underline;"><em> Methodology Addendum</em></span></p>
<ul>
<li>Zed Shaw requested a methodology review. The following bullets outline how I conducted all the tests.</li>
<li>I used Jakarta JMeter 2.3.1 to run the test.</li>
<li>I pulled HEAD requests to minimize measurement errors that might be caused by over the wire variations in bandwidth</li>
<li>Rails Code path:
<ul>
<li>I ran against two fairly distinct code paths and had several hundred URL variations that hit all over the database within those two code paths (One code path searched for a set of records within a US state, the other searched for a specific record and displayed details about it).</li>
<li>Rails code used was production scale and quality. By this I mean it is code that runs a full-fledged webserver and it does a lot of work. It may not be the smartest or fastest code, but it provides a lot of user functionality that is probably pretty typical for &#8220;read mostly&#8221; Rails sites.</li>
<li>All activity was read-only - no insert/updates were performed. Simulated traffic was typical for this website.</li>
</ul>
</li>
<li>I had a warmup period before each test, to make sure that all core code was cached before running the actual test. Warmup was generally around 100 seconds. I was not precise on this though.</li>
<li>Tests all ran for 300 seconds. There was a ramp-up period (to go from 0 threads running to all threads running) on each test that was equal in seconds to half the number of threads - so a 10 thread test had a 5 second ramp-up. A 30 thread test had a 15 sec ramp-up.</li>
<li>Testing was run from a single dev workstation located on a 6mbs ADSL line (uplink is usually around 600kbs effective).</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.misuse.org/science/2008/04/07/thin-vs-mongrel-a-ruby-on-rails-performance-shootout/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Thin, Ruby on Rails &#038; Nginx fair proxy: Performance testing</title>
		<link>http://www.misuse.org/science/2008/04/07/thin-ruby-on-rails-nginx-fair-proxy-performance-testing/</link>
		<comments>http://www.misuse.org/science/2008/04/07/thin-ruby-on-rails-nginx-fair-proxy-performance-testing/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 04:50:40 +0000</pubDate>
		<dc:creator>science</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.misuse.org/science/2008/04/07/thin-ruby-on-rails-nginx-fair-proxy-performance-testing/</guid>
		<description><![CDATA[
By science &#38; wayneeseguin
Thin a new-ish application server, primarily designed for serving the same community as Zed Shaw&#8217;s (and now community managed) masterwork Mongrel. Its job is to dispatch web requests, primarily Rails and other Ruby frameworks. There&#8217;s plenty already written about Thin, to get you up and running.
I&#8217;ve been eying Thin and thanks to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.misuse.org/science/2008/04/07/thin-ruby-on-rails-nginx-fair-proxy-performance-testing/meaurement-scale/" rel="attachment wp-att-123" title="Meaurement scale"><img src="http://www.misuse.org/science/wp-content/uploads/2008/03/thin_scale.thumbnail.gif" alt="Meaurement scale" /></a></p>
<p>By science &amp; wayneeseguin</p>
<p><a href="http://code.macournoyer.com/thin/" title="Thin project website" target="_blank">Thin</a> a new-ish application server, primarily designed for serving the same community as Zed Shaw&#8217;s (and now community managed) masterwork <a href="http://mongrel.rubyforge.org/" target="_blank">Mongrel</a>. Its job is to dispatch web requests, primarily Rails and other Ruby frameworks. <a href="http://blog.kineticweb.com/articles/2008/02/12/starting-to-get-thin-v0-6-3" title="Blog on using Thin" target="_blank">There&#8217;s plenty already written</a> about Thin, to get you up and running.</p>
<p>I&#8217;ve been eying Thin and thanks to Wayne, I got motivated to test it out. He and I spent the better part of a day doing configuration analysis and performance testing on Thin in the context of <a href="http://www.engineyard.com" title="EngineYard home page" target="_blank">EngineYard&#8217;s</a> hosting environment. We had access to a brand new, unloaded &#8220;slice&#8221; (aka web server) on their server farm. The stack we used looks like:</p>
<p>Load balancers  =&gt; Nginx =&gt; unix sockets =&gt; Thin =&gt; Rails</p>
<p>We ran a quite a few performance tests against Thin using the above setup and overall liked what we saw.</p>
<p><span id="more-121"></span>Summary:</p>
<ul>
<li>It&#8217;s stable - no crashing even with high concurrency</li>
<li>It&#8217;s fast - performance was impressive (we will get some comparisons to Mongrel for you soon)</li>
<li>It doesn&#8217;t use much memory - We think this is at least partly because it lets you <a href="http://archives.postgresql.org/pgsql-general/2001-01/msg01420.php" title="Why unix sockets are faster than ip socks" target="_blank">use unix sockets instead of ip ports</a>.</li>
</ul>
<p>We went a little deeper too. In particular, because Thin is using epoll/event_machine to pull from the unix sockets, we were worried that while network performance would be improved, user-interface latency would rise because fast requests would get stuck behind slow requests inside the unix socket queuing mechanism. [2]</p>
<p><a href="http://nginx.net/" target="_blank">Nginx</a> offers a way out of this problem in the form of its <a href="http://brainspl.at/articles/2007/11/09/a-fair-proxy-balancer-for-nginx-and-mongrel" target="_blank">&#8220;fair proxy&#8221; module</a> - it ensures that each request is sent to a socket only if that socket is not currently handling any work. So sockets are not allowed to queue - nginx does that. Wayne and I both have experience with nginx + fair with mongrels. So how would nginx + fair do with Thin? About as expected which is pretty darn well.</p>
<p>Wayne and I hypothesized that the fair proxy module would result in higher latency but lower &#8220;worst case&#8221; performance. In fact &#8220;max time to return&#8221; was faster in all cases for the fair proxy. But &#8220;90% of requests&#8221; were returned slower for fair. (Both were within one standard deviation but appear significant to my eye b/c we got the same pattern for each set of tests). Average performance was statistically identical in all cases as were the total number of requests made in 300 seconds.</p>
<hr /> <strong>30 threads, running for 300 seconds (30 second warm-up) against 3 Thins</strong></p>
<table border="1">
<tr>
<td>Test setup</td>
<td># of Requests</td>
<td>Avg time</td>
<td>90% returned</td>
<td>Max time to return</td>
</tr>
<tr>
<td>Fair Proxy</td>
<td>1738</td>
<td>5.08s</td>
<td>10.1s</td>
<td>14.3s</td>
</tr>
<tr>
<td>Socket queue</td>
<td>1730</td>
<td>5.10s</td>
<td>9.26s</td>
<td>16.7s</td>
</tr>
</table>
<hr />But this doesn&#8217;t tell the whole story. Web servers are often a little spooky - with some requests stalling for weird reasons (bad programming being a big one). To simulate the putative bad programmer, I installed a sleep function into our test Rails application (which is a full-sized commercial web app). It was designed to sleep for 4 seconds for 5% of the requests. This test was designed to determine if the fair proxy was doing its job. And it was.</p>
<hr style="visibility: hidden" /> Here&#8217;s what we found. For cases where 5% of your dynamic calls are &#8220;slow&#8221; using the &#8220;fair proxy&#8221; could boost your page throughput by 25%. What&#8217;s crucial about this finding is that if you are looking at your <em>average</em>  “time to return” or even your “max time to return” you won’t see much difference between “fair proxy” and queuing in the unix sockets. But your users will see a difference in that your server will return more pages per minute because fewer pages will get caught in “slow lanes.”</p>
<hr /> <strong>10 Threads running for 300 seconds against 3 Thins, with 5% of requests “stuck” for 4s</strong></p>
<table border="1">
<tr>
<th>Test setup</th>
<th># of Requests</th>
<th>Avg time</th>
<th>90% returned</th>
<th>Max time to return</th>
</tr>
<tr>
<td>Fair Proxy</td>
<td>1341</td>
<td>2.24s</td>
<td>6.09s</td>
<td>11.53s</td>
</tr>
<tr>
<td>Socket queue</td>
<td>1071</td>
<td>2.79s</td>
<td>6.93s</td>
<td>11.84s</td>
</tr>
</table>
<hr /> We were quite happily surprised by these results and hope that others find them helpful in planning their server architecture in Ruby/Rails or <a href="http://www.merbivore.com/" target="_blank">whatever</a> <a href="http://camping.rubyforge.org/files/README.html" target="_blank">your</a> <a href="http://www.nitroproject.org/" target="_blank">platform</a> of <a href="http://rubyforge.org/projects/iowa" target="_blank">choice</a> <a href="http://rbazinet.wordpress.com/2008/01/14/10-alternative-ruby-web-frameworks/" target="_blank">might be</a>. <a href="http://www.misuse.org/science/2008/04/07/thin-vs-mongrel-a-ruby-on-rails-performance-shootout/" title="Thin v Mongrel shootout">Read on </a>for more performance testing fun, in a comparison between Mongrel and Thin&#8217;s performance. Final Note: One thing I did notice was that under heavy load nginx fair proxy caused some weird &#8220;clustering&#8221; of requests - the graphs (unpublished) show it pretty clearly while the statistics (published above) do not. So while fair proxy looks pretty good overall, if you are heavily loaded, I might recommend from the study that you do not use fair proxy, at least the version I tested (current stable release). Post a comment if you have any questions about this.<br />
<hr /> End Notes:</p>
<ol>
<li>You can see our <a href="http://www.misuse.org/downloads/nginx_thin_testing_results.htm" target="_blank">raw performance data </a>here.</li>
<li>To understand why this might occur, think of a rental car return area at an airport. They have long parking lanes, where you queue up behind cars in front of you waiting to return. Now if there&#8217;s a guy at the start of the lanes and he directs into a lane based on a round-robin strategy, if you get stuck behind a slow customer, two or three cars will pass you by in other lanes. That will make you annoyed. On the web you can&#8217;t see the other customers passing you, but queuing into sockets using round-robin can lead someone who has a lightweight request to wait behind a somewhat slower request. Unless your peak latency is under 1s, then this will cause noticeable problems for your customers.</li>
<li>Science also has a writeup on <a href="http://www.misuse.org/science/2008/02/22/rails-page-caching-nginx-ssi-ajax-and-form-posts/" target="_blank">optimizing Nginx and Rails page caching </a>which may be of interest to readers.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.misuse.org/science/2008/04/07/thin-ruby-on-rails-nginx-fair-proxy-performance-testing/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Converting numbers or currency to comma delimited format with Ruby regex</title>
		<link>http://www.misuse.org/science/2008/03/27/converting-numbers-or-currency-to-comma-delimited-format-with-ruby-regex/</link>
		<comments>http://www.misuse.org/science/2008/03/27/converting-numbers-or-currency-to-comma-delimited-format-with-ruby-regex/#comments</comments>
		<pubDate>Thu, 27 Mar 2008 19:20:14 +0000</pubDate>
		<dc:creator>science</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.misuse.org/science/2008/03/27/converting-numbers-or-currency-to-comma-delimited-format-with-ruby-regex/</guid>
		<description><![CDATA[
There may be much easier ways to do this but Science wrote a nice little regular expression which will convert your numbers to comma delimited strings in pure Ruby. It demonstrates some cool features of Ruby from which maybe you will learn!

def comma_numbers(number, delimiter = ',')
  number.to_s.reverse.gsub(%r{([0-9]{3}(?=([0-9])))}, &#8220;\\1#{delimiter}&#8221;).reverse
end
# here are some examples:
puts comma_numbers(1000)
# &#8220;1,000&#8243;
puts [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.misuse.org/science/2008/03/27/converting-numbers-or-currency-to-comma-delimited-format-with-ruby-regex/bring-back-the-five-thousand-dollar-bill/" rel="attachment wp-att-125" title="Bring back the five thousand dollar bill"><img src="http://www.misuse.org/science/wp-content/uploads/2008/03/5000front.thumbnail.gif" alt="Bring back the five thousand dollar bill!" /></a></p>
<p>There may be much easier ways to do this but Science wrote a nice little regular expression which will convert your numbers to comma delimited strings in pure Ruby. It demonstrates some cool features of Ruby from which maybe you will learn!<br />
<span id="more-124"></span></p>
<pre><code>def comma_numbers(number, delimiter = ',')
  number.to_s.reverse.gsub(%r{([0-9]{3}(?=([0-9])))}, &#8220;\\1#{delimiter}&#8221;).reverse
end
# here are some examples:
puts comma_numbers(1000)
# &#8220;1,000&#8243;
puts comma_numbers(123456.78)
# &#8220;123,456.78&#8243;
puts comma_numbers(&#8221;$12345&#8243;)
# &#8220;$12,345&#8243;
puts comma_numbers(&#8221;123456&#8243;, &#8220;.&#8221;)
# &#8220;123.456&#8243; # Euro-friendly!</code></pre>
<p>Let&#8217;s take a look at how this thing works. There are a couple of items that are worth examining in a little detail..</p>
<p>Firstly, since Regex operates left to right but we want to sub out numbers from right to left, we first reverse the string, which is super easy with a Ruby string.</p>
<p>Secondly, we create a regex pattern that does something interesting. We want to match and replace any three numbers which have a number in front of them with those same three numbers plus a comma. The interesting bit is that if we aren&#8217;t careful when we match the number in front of our three numbers, we will &#8220;advance the search pointer&#8221; inside regex past that value. This will result in our search being &#8220;off by one&#8221; - creating conversions such as &#8220;1,1234,000&#8243;</p>
<p>To understand why, first remember that the string is reversed when we regex it: &#8220;0004321&#8243; Next, consider that the &#8220;4&#8243; in the above example - it will be matched by a regex of %{([0-9]{3})[0-9]} We need to reference it to ensure that commas are only placed when there is a number in front of our block of three numbers..</p>
<p>But we want to search that 4 &#8220;again&#8221; after a match is made by gsub, so it can be counted as the group of three digits&#8221;234&#8243; to be comma&#8217;ed. So we use a nice little Ruby extension to regex (?=[x]) which lets you match something in a repeated regex but keep the search from considering it matched for future matches. This yields the regex of %r{([0-9]{3}(?=([0-9])))} - some of those parens are extraneous but it&#8217;s easier for Science to read it that way (and future legibility of regex is one of its crucial failings). Happy commas!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.misuse.org/science/2008/03/27/converting-numbers-or-currency-to-comma-delimited-format-with-ruby-regex/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Rails page caching, nginx, SSI, Ajax and form POSTS</title>
		<link>http://www.misuse.org/science/2008/02/22/rails-page-caching-nginx-ssi-ajax-and-form-posts/</link>
		<comments>http://www.misuse.org/science/2008/02/22/rails-page-caching-nginx-ssi-ajax-and-form-posts/#comments</comments>
		<pubDate>Fri, 22 Feb 2008 08:38:37 +0000</pubDate>
		<dc:creator>science</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.misuse.org/science/2008/02/22/rails-page-caching-nginx-ssi-ajax-and-form-posts/</guid>
		<description><![CDATA[
A couple of great blog posts have come out in the last year, dealing with how to squeeze more performance out of Ruby on Rails. These techniques are actually massively improving the performance of Ruby on Rails, so much so that I&#8217;m starting to think of Rails less as an Application Framework and more as [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.misuse.org/science/2008/02/22/rails-page-caching-nginx-ssi-ajax-and-form-posts/fence-post/" rel="attachment wp-att-119" title="Fence post"><img src="http://www.misuse.org/science/wp-content/uploads/2008/02/fence-post.thumbnail.jpg" alt="Fence post" /></a></p>
<p>A couple of great blog posts have come out in the last year, dealing with how to squeeze more performance out of Ruby on Rails. These techniques are actually massively improving the performance of Ruby on Rails, so much so that I&#8217;m starting to think of Rails less as an Application Framework and more as an Web Page Template Generator.</p>
<p><span id="more-118"></span>For background here are two of the best articles on using page caching, nginx and SSI to radically improve performance on Rails while sacrificing nothing:</p>
<p><a href="http://theexciter.com/articles/dynamic-page-caching-with-nginx-ssi" target="_blank">http://theexciter.com/articles/dynamic-page-caching-with-nginx-ssi </a></p>
<p><a href="http://blog.kovyrin.net/2007/08/05/using-nginx-ssi-and-memcache-to-make-your-web-applications-faster/" target="_blank">http://blog.kovyrin.net/2007/08/05/using-nginx-ssi&#8230;</a></p>
<p>These techniques are great. They apply to you if your application:</p>
<p>1) Generates lots of pages with unique URL&#8217;s and each such page is accessed over and over.</p>
<p>1.a) For example, your site might have a single action which displays information about various regions around the  country. It&#8217;s a single action which pulls from a database to generate info about Hawaii or the Gulf Coast, FL. Your URL&#8217;s look like:</p>
<p>/region/info/Gulf-Coast-Florida</p>
<p>/region/info/Hawaii</p>
<p>2) Each page is relatively slow (&gt; 2s?) and resource consuming to build but doesn&#8217;t change all that often. You might assemble this region info from ActiveResources and XML feeds and what not, but once you&#8217;ve assembled the content on the page it might be valid for weeks or months.</p>
<p>3) Each page has some amount of dynamic content that prevents you from using page caching.</p>
<p>3.a) Each page might have a &#8220;login&#8221; link, or if the user is logged in it might be a link to their account saying &#8220;Welcome back Science! (account)&#8221;</p>
<p>In the traditional Rails model, you might just live with a 4s load time and move on with other projects. But with nginx SSI and page caching you don&#8217;t have to. You can build the dynamic content as a partial (like an Ajax request which returns an HTML partial). The rest of the page you build as fully page cached to disk or memcache.  Nginx reads your SSI tag and calls back to Rails for only the very lightweight frequently changing dynamic content to assemble the entire page.</p>
<p>That&#8217;s pretty cool and the other articles cover this much in greater detail and clarify. Read up!</p>
<p>Science has been working on extending this work ever so slightly. What if your actions are CRUD and not only do they generate the above slowly changing dynamic content for GET requests but they also generate variable search results for form POST&#8217;s or AJAX requests (or WSDL or whatever): they behave differently, yielding alternative content depending on the CRUD or request method.</p>
<p>In the caching model above, you&#8217;re out of luck. Your nginx server is going to happily serve out your static page to all requests no matter what. A form or ajax post will simply yield the full page content just like before.</p>
<p>One way to solve this is to change your URL&#8217;s so that the request method is parsable on the command line:</p>
<p>/ajax/region/info/Hawaii</p>
<p>/post/region/info/Hawaii</p>
<p>But that kind of blows huh?</p>
<p>Another way to handle this is much more in the spirit of CRUD: Configure Nginx to by-pass POST requests and only serve the static page caches on GET requests.  This makes perfect sense from an HTTP perspective: GET&#8217;s are cachable and POST&#8217;s reflect dynamic data. Perfect distinction. Since Ajax sends (generally speaking) its requests as POST&#8217;s everything fits together.</p>
<p>So get out there and add code to nginx to force it to skip page caching for POST&#8217;s. Here&#8217;s some snippets from my nginx.conf to give an idea of one way to solve this problem:</p>
<pre><code># rewrite any trailing "/" without the trailing "/"
# this is a work around - we must force nginx to treat pages with trailing slashes
# exactly like pages without them, so the page cache detection works correctly below
rewrite ^/(.*)/$ /$1 last;

location / {
  # turn ssi capability on
  ssi on;
  proxy_set_header  X-Real-IP  $remote_addr;
  proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_redirect false;
  proxy_max_temp_file_size 0;

  location ~ ^/(images|javascripts|stylesheets)/ {
    expires 10y;
  }

  # don't page cache any POST requests
  if ($request_method = POST) {
    proxy_pass http://mongrel;
    break;
  }

  # if we find the cached file on disk now (i.e. it's a GET request) serve it
  if (-f $request_filename.html) {
    rewrite (.*) $1.html break;
  }

  # if we find index.html version of request in root of website, it's also a cached file so serve it
  set $index 'index.html';
  if (-f $request_filename$index) {
    rewrite (.*) $1$index break;
  }
  # if we find index.html files anywhere else, serve as cached
  if (-f $request_filename/$index) {
    rewrite (.*) $1/$index break;
  }
  # otherwise if we don't find the file on disk, hand it off to mongrel/Rails to process
  if (!-f $request_filename) {
    proxy_pass http://mongrel;
    break;
  }
}
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.misuse.org/science/2008/02/22/rails-page-caching-nginx-ssi-ajax-and-form-posts/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MojoMagick: Ruby Image Library (for ImageMagick)</title>
		<link>http://www.misuse.org/science/2008/01/30/mojomagick-ruby-image-library-for-imagemagick/</link>
		<comments>http://www.misuse.org/science/2008/01/30/mojomagick-ruby-image-library-for-imagemagick/#comments</comments>
		<pubDate>Thu, 31 Jan 2008 06:40:23 +0000</pubDate>
		<dc:creator>science</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.misuse.org/science/2008/01/30/mojomagick-ruby-image-library-for-imagemagick/</guid>
		<description><![CDATA[
Science releases MojoMagick, an Ruby language image library &#8220;that does very little&#8221; &#8482;. There are several useful image tools that &#8220;do a lot&#8221; - MojoMagick is designed to just a few things:

Be fast
Don&#8217;t leak memory
Make simple ImageMagick tasks, simple as Ruby tasks
Permit direct access to ImageMagick for complex tasks (i.e. get out of your way)
Provide [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.misuse.org/science/2008/01/30/mojomagick-ruby-image-library-for-imagemagick/" title="Magick!"><img src="http://www.misuse.org/science/wp-content/uploads/2008/01/fairy.thumbnail.jpg" alt="Magick!" /></a></p>
<p>Science releases MojoMagick, an Ruby language image library &#8220;that does very little&#8221; &#8482;. There are several useful image tools that &#8220;do a lot&#8221; - MojoMagick is designed to just a few things:<span id="more-117"></span></p>
<ul>
<li>Be fast</li>
<li>Don&#8217;t leak memory</li>
<li>Make simple ImageMagick tasks, simple as Ruby tasks</li>
<li>Permit direct access to ImageMagick for complex tasks (i.e. get out of your way)</li>
<li>Provide a central access to ImageMagick for good code architecture</li>
<li>Easy to extend</li>
<li>Limit memory accessible to ImageMagick (where desired)</li>
</ul>
<p>That&#8217;s what it does. It&#8217;s packaged as a Rails plugin, but does not require Rails to run. If there&#8217;s any interest, I&#8217;ll make it a gem (just ask).</p>
<p>You can download a copy <a href="http://trac.misuse.org/science/wiki/MojoMagick" target="_blank">by following the instructions here.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.misuse.org/science/2008/01/30/mojomagick-ruby-image-library-for-imagemagick/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Passing Multiple Arguments in Ruby: &#8220;*&#8221; is your friend</title>
		<link>http://www.misuse.org/science/2008/01/30/passing-multiple-arguments-in-ruby-is-your-friend/</link>
		<comments>http://www.misuse.org/science/2008/01/30/passing-multiple-arguments-in-ruby-is-your-friend/#comments</comments>
		<pubDate>Wed, 30 Jan 2008 20:50:26 +0000</pubDate>
		<dc:creator>science</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.misuse.org/science/2008/01/30/passing-multiple-arguments-in-ruby-is-your-friend/</guid>
		<description><![CDATA[
Passing multiple arguments in Ruby is easy. You can pass any number of arguments, and even vary the class/types according to context. You can even vary the number of arguments passed. The receiver has to deal with this somehow, but even that&#8217;s pretty easy to manage. It&#8217;s a little trickier if the receiver has to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.misuse.org/science/2008/01/30/passing-multiple-arguments-in-ruby-is-your-friend/" title="Arguments"><img src="http://www.misuse.org/science/wp-content/uploads/2008/01/argument1.thumbnail.jpg" alt="Arguments" /></a></p>
<p>Passing multiple arguments in Ruby is easy. You can pass any number of arguments, and even vary the class/types according to context. You can even vary the number of arguments passed. The receiver has to deal with this somehow, but even that&#8217;s pretty easy to manage. It&#8217;s a little trickier if the receiver has to delegate an unknown number of arguments to another receiver, but the * does the job for you - a great example of Ruby syntax that works for you. What follows is some simple example code to illustrate the idea.<span id="more-105"></span></p>
<pre><code>def my_method(*args)
  # this line unrolls all the arguments out of the array
  # otherwise you'd be passing in an array to sub_method (see below)
  sub_method(*args)
  # here we don't unroll the arguments so you can see the receiver
  # just gets an array instead of a series of arguments
  sub_method(args)
end

def sub_method(*args)
  puts "Arguments received by sub_method as an array:"
  args.each do |arg_item|
    puts arg_item.inspect
    puts arg_item.class.inspect
  end
end

my_method('1','2',3,[4,5,6])
</code></pre>
<p>Output is:</p>
<pre><code>
Arguments received by sub_method as an array:
"1"
String
"2"
String
3
Fixnum
[4, 5, 6]
Array
Arguments received by sub_method as an array:
["1", "2", 3, [4, 5, 6]]
Array
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.misuse.org/science/2008/01/30/passing-multiple-arguments-in-ruby-is-your-friend/feed/</wfw:commentRss>
		</item>
		<item>
		<title>On magnifying glasses, microscopes and the act of looking.</title>
		<link>http://www.misuse.org/science/2008/01/27/on-magnifying-glasses-microscopes-and-the-act-of-looking/</link>
		<comments>http://www.misuse.org/science/2008/01/27/on-magnifying-glasses-microscopes-and-the-act-of-looking/#comments</comments>
		<pubDate>Sun, 27 Jan 2008 21:51:13 +0000</pubDate>
		<dc:creator>science</dc:creator>
		
		<category><![CDATA[Quotations]]></category>

		<guid isPermaLink="false">http://www.misuse.org/science/2008/01/27/on-magnifying-glasses-microscopes-and-the-act-of-looking/</guid>
		<description><![CDATA[
A larger world exists, but we have never looked at it. We are too concerned with our microscopes or our magnifying glasses. We try to make things large by using magnifying glasses—but we have never looked at outer space with our naked eyes. If we looked into it, we could find it—but we don’t have [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.misuse.org/science/2008/01/27/on-magnifying-glasses-microscopes-and-the-act-of-looking/" title="Map of the Universe"><img src="http://www.misuse.org/science/wp-content/uploads/2008/01/map-of-universe-spaceshots-posters.thumbnail.jpg" alt="map-of-universe-spaceshots-posters.jpg" /></a></p>
<p>A larger world exists, but we have never looked at it. We are too concerned with our microscopes or our magnifying glasses. We try to make things large by using magnifying glasses—but we have never looked at outer space with our naked eyes. If we looked into it, we could find it—but we don’t have to use our binoculars and telescopes. We don’t need them, they are false pretenses. We don’t need any means to do this; we could just simply <em>look at it</em>, whatever it is, and enjoy it. An immensely larger version of thinking and of celebration is taking place. That seems to be the very important point.</p>
<p>- Chögyam Trungpa Rinpoche</p>
]]></content:encoded>
			<wfw:commentRss>http://www.misuse.org/science/2008/01/27/on-magnifying-glasses-microscopes-and-the-act-of-looking/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Synchronizing Files</title>
		<link>http://www.misuse.org/science/2007/12/23/synchronizing-files/</link>
		<comments>http://www.misuse.org/science/2007/12/23/synchronizing-files/#comments</comments>
		<pubDate>Mon, 24 Dec 2007 02:30:05 +0000</pubDate>
		<dc:creator>science</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.misuse.org/science/2007/12/23/synchronizing-files/</guid>
		<description><![CDATA[
Science regularly has to synchronize files across file systems. Normally, this would involve a Ruby script or something heinous in a shell language. But that&#8217;s just business. When the synchronization is complex, the problem is much more difficult. Answering questions like these becomes a major painola: was the file deleted from one side, or added [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.misuse.org/science/2007/12/23/synchronizing-files/syncronized-photons/" rel="attachment wp-att-110" title="Syncronized Photons"><img src="http://www.misuse.org/science/wp-content/uploads/2007/12/syncphotons.thumbnail.gif" alt="Syncronized Photons" /></a></p>
<p>Science regularly has to synchronize files across file systems. Normally, this would involve a Ruby script or something heinous in a shell language. But that&#8217;s just business. When the synchronization is complex, the problem is much more difficult. Answering questions like these becomes a major painola: was the file deleted from one side, or added to the other? Was the folder renamed or removed?</p>
<p>It&#8217;s possible to try to be clever and check all your things into SVN to manage the changes, but with gigabytes of music files, for example, this could be another kind of pain (if I delete &#8220;Wham Rap&#8221; from my collection - not that I would - I don&#8217;t want it kicking around in the SVN repo taking up space).</p>
<p>There&#8217;s a better way. <span id="more-109"></span>Science has found a tool called <a href="http://www.superflexible.com/" title="Super Flexible File Sync" target="_blank">Super Flexible File Synchronizer</a>. You have to pay for it. I mean you should pay for it because it does a lot and it&#8217;s very smart. The Scientific Method over the years has required sync tools - they all make mistakes. Except this one: it hasn&#8217;t made one bad guess about what to do yet. And when it&#8217;s about to delete a bunch of files, it notices and asks &#8220;boy that&#8217;s a lot of deletions, are you sure?&#8221; Exactly what I would do if someone asked me to delete a bunch of files. &#8220;Sure that&#8217;s what you told me to do, but geez, that&#8217;s an awful lot.&#8221;</p>
<p>Open source is great when you can get it - but this tool costs money and the people making it, earn it. If you have to sync files, consider shelling out and making your life a whole lot easier with Super Flexible File Synchronizer. And no one associated with Misuse or Science gains anything by recommending this software.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.misuse.org/science/2007/12/23/synchronizing-files/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Using ActiveMerchant to process credit cards in Ruby/Rails</title>
		<link>http://www.misuse.org/science/2007/12/13/using-activemerchant-to-process-credit-cards-in-rubyrails/</link>
		<comments>http://www.misuse.org/science/2007/12/13/using-activemerchant-to-process-credit-cards-in-rubyrails/#comments</comments>
		<pubDate>Thu, 13 Dec 2007 22:29:01 +0000</pubDate>
		<dc:creator>science</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.misuse.org/science/2007/12/13/using-activemerchant-to-process-credit-cards-in-rubyrails/</guid>
		<description><![CDATA[
ActiveMerchant is a very nice little Ruby library that permits connecting to payment processing gateways to charge money against credit cards. To understand how this works, you need to know that there are two separate entities, a &#8220;payment gateway&#8221; and a &#8220;merchant account&#8221; (aka a bank). The Payment Gateway receives your request over the Internet [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.misuse.org/science/2007/12/13/using-activemerchant-to-process-credit-cards-in-rubyrails/" title="Ionic pillar"><img src="http://www.misuse.org/science/wp-content/uploads/2007/12/ionic-column.thumbnail.jpg" alt="Ionic pillar" /></a></p>
<p><a href="http://activemerchant.rubyforge.org/" target="_blank">ActiveMerchant</a> is a very nice little Ruby library that permits connecting to payment processing gateways to charge money against credit cards. To understand how this works, you need to know that there are two separate entities, a &#8220;payment gateway&#8221; and a &#8220;merchant account&#8221; (aka a bank). The Payment Gateway receives your request over the Internet for a charge, and authorizes that charge in real-time. The Gateway then hands the authorization/transaction over to the Merchant Account, which converts that credit card transaction into money in your account.</p>
<p><span id="more-107"></span>Many Internet credit card companies will act as both Payment Gateway and Merchant Account, but you should be aware that it&#8217;s easy to de-couple these, and request that your Payment Gateway process the charge with your preferred Merchant Account. You can save money if you shop around for these services. <a href="http://authorize.net" target="_blank">Authorize.net</a> is one example that seems to be popular with the Ruby/Rails community. Paypal&#8217;s Payflow Pro system is an example of a Gateway but not a Merchant Account - you can connect any participating bank to their backend for conversion to cash.</p>
<p>Onto some code. I noticed that many popular examples of ActiveMerchant are out of date, have typo&#8217;s or just don&#8217;t work. So Science wrote some very simple, put-it-in-a-text-file-and-run-it code that gives a couple of examples on how to process cards with ActiveMerchant and Authorize.net</p>
<p>First, apply for a &#8220;test account&#8221; with Authorize.net&#8217;s <a href="http://developer.authorize.net/" target="_blank">developer center</a>. After you&#8217;re approved for an account, you&#8217;ll get a login_id and a transaction_key. You&#8217;ll want to enter those values into the appropriate constants at the top of the code below. Then install ActiveMerchant:</p>
<pre><code>gem install ActiveMerchant -y
</code></pre>
<p>That&#8217;s it - run the code and you&#8217;ll see two successful transactions. Where you go from there is up to you, but hopefully this will help you get off the ground!</p>
<pre><code>require 'active_merchant'

# MOST BASIC EXAMPLE 

# random amount from $10 to $35 - this prevents duplicate transaction errors
charge_amount = rand(1000)+2500 

LOGIN_ID = 'your_login_id_here'
TRANSACTION_KEY = 'your_trans_key_here'
ActiveMerchant::Billing::Base.mode = :test 

#number = '4222222222222' #Authorize.net test card, error-producing
number = '4007000000027' #Authorize.net test card, non-error-producing

credit_card = ActiveMerchant::Billing::CreditCard.new(
:number =&gt; number,
:month =&gt; 8,
:year =&gt; 2009,
:first_name =&gt; 'Tobias',
:last_name =&gt; 'Luetke',
:type =&gt; 'visa'
)

if credit_card.valid?
gateway = ActiveMerchant::Billing::AuthorizeNetGateway.new(
 :login  =&gt; LOGIN_ID,
 :password =&gt; TRANSACTION_KEY
)
response = gateway.purchase(charge_amount, credit_card)

if response.success?
 puts "success!"
else
 raise StandardError.new( response.message )
end
end

# EXAMPLE USING BILLING ADDRESS

# random amount from $10 to $35 - this prevents duplicate transaction errors
charge_amount = rand(1000)+2500
number = '4222222222222' #Authorize.net test card, error-producing
#number = '4007000000027' #Authorize.net test card, non-error-producing
billing_address = { :name =&gt; 'Mark McBride', :address1 =&gt; '1 Show Me The Money Lane',
:city =&gt; 'San Francisco', :state =&gt; 'CA',
:country =&gt; 'US', :zip =&gt; '23456', :phone =&gt; '(555)555-5555' }

creditcard = ActiveMerchant::Billing::CreditCard.new(
 :number =&gt; number,
 :month =&gt; 3,        #for test cards, use any date in the future
 :year =&gt; 2010,
 :first_name =&gt; 'Mark',
 :last_name =&gt; 'McBride',
 :type =&gt; 'visa'       #note that MasterCard is 'master'
)

if creditcard.valid?
  gateway = ActiveMerchant::Billing::AuthorizeNetGateway.new(
   :login  =&gt; LOGIN_ID,
   :password =&gt; TRANSACTION_KEY)

  options = {:address =&gt; {}, :billing_address =&gt; billing_address}

  response = gateway.authorize(charge_amount, creditcard, options)

  if response.success?
    gateway.capture(charge_amount, response.authorization)
    puts "Success: " + response.message.to_s
  else
    puts "Fail: " + response.message.to_s
  end
else
  puts "Credit card not valid: " + creditcard.validate.to_s
end
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.misuse.org/science/2007/12/13/using-activemerchant-to-process-credit-cards-in-rubyrails/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
