<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>Managed Open Source blog - Blog</title>
  <id>tag:blog.managedopensource.com,2008:mephisto/</id>
  <generator version="0.7.3" uri="http://mephistoblog.com">Mephisto Noh-Varr</generator>
  <link href="http://blog.managedopensource.com/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://blog.managedopensource.com/" rel="alternate" type="text/html"/>
  <updated>2008-02-03T00:07:44Z</updated>
  <entry xml:base="http://blog.managedopensource.com/">
    <author>
      <name>supo</name>
    </author>
    <id>tag:blog.managedopensource.com,2008-02-02:4</id>
    <published>2008-02-02T23:39:00Z</published>
    <updated>2008-02-03T00:07:44Z</updated>
    <link href="http://blog.managedopensource.com/2008/2/2/ruby-benchmark-options-passing-1.8-to-1.9" rel="alternate" type="text/html"/>
    <title>Re: Sun's benchmarking ways to pass options to a method in Ruby</title>
<content type="html">
            &lt;p&gt;This is a response to Bryan Donovan&#8217;s blog post called &lt;a href=&quot;http://blogs.sun.com/bdonovan/entry/ruby_benchmarking_ways_to_pass&quot;&gt;ways to pass options&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Bryan&#8217;s original benchmark was run on Ruby 1.8.4.  I will be running the benchmarks on Ruby 1.8.6 and Ruby 1.9 to demonstrate performance reversal of code level optimizations between Ruby versions (as I did in &lt;a href=&quot;http://blog.managedopensource.com/2007/10/31/reversal-of-code-performance-optimizations-from-ruby-1-8-to-1-9&quot;&gt;Ruby performance reversal benchmark 1.8 to 1.9&lt;/a&gt;).&lt;/p&gt;


	&lt;p&gt;I will use Bryan&#8217;s &lt;a href=&quot;http://pastie.caboo.se/146761&quot;&gt;Ruby benchmark code&lt;/a&gt; to run for both Ruby 1.8.6 and Ruby 1.9.0 (official).&lt;/p&gt;


&lt;h4&gt;Ruby 1.8.6 Results&lt;/h4&gt;
Below are the results of running the options passing benchmark in Ruby 1.8.6:
&lt;pre&gt;&lt;code&gt;
With no option values passed
Rehearsal -------------------------------------------
delete:   0.290000   0.050000   0.340000 (  0.428564)
merge:    0.700000   0.190000   0.890000 (  1.017415)
or_nil:   0.370000   0.050000   0.420000 (  0.509209)
---------------------------------- total: 1.650000sec

              user     system      total        real
delete:   0.300000   0.050000   0.350000 (  0.428401)
merge:    0.760000   0.130000   0.890000 (  1.010474)
or_nil:   0.360000   0.050000   0.410000 (  0.490170)

With some option values passed
Rehearsal -------------------------------------------
delete:   0.360000   0.060000   0.420000 (  0.505094)
merge:    0.890000   0.130000   1.020000 (  1.150165)
or_nil:   0.390000   0.070000   0.460000 (  0.563713)
---------------------------------- total: 1.900000sec

              user     system      total        real
delete:   0.340000   0.060000   0.400000 (  0.489191)
merge:    0.920000   0.110000   1.030000 (  1.149708)
or_nil:   0.350000   0.090000   0.440000 (  0.528287)

With all option values passed
Rehearsal -------------------------------------------
delete:   0.420000   0.050000   0.470000 (  0.547446)
merge:    0.970000   0.130000   1.100000 (  1.228093)
or_nil:   0.420000   0.050000   0.470000 (  0.574593)
---------------------------------- total: 2.040000sec

              user     system      total        real
delete:   0.400000   0.050000   0.450000 (  0.485888)
merge:    0.960000   0.140000   1.100000 (  1.237509)
or_nil:   0.400000   0.060000   0.460000 (  0.536063)
&lt;/code&gt;&lt;/pre&gt;
&lt;a href=&quot;http://pastie.caboo.se/146767&quot;&gt;Results of benchmark for Ruby 1.8.6&lt;/a&gt;.

&lt;h4&gt;Ruby 1.9.0 Results&lt;/h4&gt;
Below are the results of running the options passing benchmark in Ruby 1.9.0:
&lt;pre&gt;&lt;code&gt;
With no option values passed
Rehearsal -------------------------------------------
delete:   0.150000   0.000000   0.150000 (  0.230391)
merge:    0.540000   0.010000   0.550000 (  0.645735)
or_nil:   0.120000   0.000000   0.120000 (  0.188468)
---------------------------------- total: 0.820000sec

              user     system      total        real
delete:   0.160000   0.000000   0.160000 (  0.238828)
merge:    0.520000   0.000000   0.520000 (  0.610940)
or_nil:   0.120000   0.000000   0.120000 (  0.180744)

With some option values passed
Rehearsal -------------------------------------------
delete:   0.220000   0.000000   0.220000 (  0.294110)
merge:    0.690000   0.010000   0.700000 (  0.803382)
or_nil:   0.220000   0.000000   0.220000 (  0.297869)
---------------------------------- total: 1.140000sec

              user     system      total        real
delete:   0.210000   0.000000   0.210000 (  0.283983)
merge:    0.700000   0.000000   0.700000 (  0.802766)
or_nil:   0.230000   0.000000   0.230000 (  0.295433)

With all option values passed
Rehearsal -------------------------------------------
delete:   0.270000   0.010000   0.280000 (  0.348052)
merge:    0.770000   0.040000   0.810000 (  0.947252)
or_nil:   0.240000   0.010000   0.250000 (  0.336790)
---------------------------------- total: 1.340000sec

              user     system      total        real
delete:   0.280000   0.000000   0.280000 (  0.660810)
merge:    0.750000   0.000000   0.750000 (  1.618925)
or_nil:   0.240000   0.000000   0.240000 (  0.478159)
&lt;/code&gt;&lt;/pre&gt;
&lt;a href=&quot;http://pastie.caboo.se/146772&quot;&gt;Results of benchmark for Ruby 1.9.0&lt;/a&gt;.

	&lt;p&gt;In Ruby 1.8.6 the &lt;code&gt;delete&lt;/code&gt; code is consistently more efficient, whereas in Ruby 1.9.0 the &lt;code&gt;or_nil&lt;/code&gt; code is mostly more efficient, except for the &lt;em&gt;With some option values passed&lt;/em&gt; scenario.&lt;/p&gt;


	&lt;p&gt;This once again shows that when optimizing performance on the code level, you need to be careful that you justify your micro-optimizations before you create code spaghetti just &#8220;because&#8230;.&#8221;.  Readability and maintainability is most important and when needed, only then should you optimize.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.managedopensource.com/">
    <author>
      <name>supo</name>
    </author>
    <id>tag:blog.managedopensource.com,2007-10-31:3</id>
    <published>2007-10-31T05:19:53Z</published>
    <updated>2008-02-02T23:38:21Z</updated>
    <link href="http://blog.managedopensource.com/2007/10/31/reversal-of-code-performance-optimizations-from-ruby-1-8-to-1-9" rel="alternate" type="text/html"/>
    <title>Reversal of code performance optimizations from Ruby 1.8 to 1.9</title>
<summary type="html">&lt;p&gt;This article shows how code-level optimizations may not be valid when migrating from 1.8.x to 1.9.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;This article shows how code-level optimizations may not be valid when migrating from 1.8.x to 1.9.&lt;/p&gt;
&lt;p&gt;As some of you already know I am keenly playing with custom Ruby configurations from disabling pthreads in 1.8.6 Linux builds to numerous build variations of Ruby 1.9 (trunk).&lt;/p&gt;


Last night I noticed something quite interesting, but before we get to that point, let me tell you a story.
&lt;blockquote&gt;There was once a fastidious Ruby developer who payed the closest attention to detail.  Code optimization of all kinds were his obsession.  So much so that he took great pains to &#8220;optimize code&#8221;.  The results, in my opinion were not very Rubyish and often much less readable than the original code.  One day last year, while running on Ruby 1.8.x, he found after running a script that using the &lt;code&gt;for item in list...end&lt;/code&gt; construct performed &lt;b&gt;slightly&lt;/b&gt; better than the very Rubyish (and &lt;span class=&quot;caps&quot;&gt;IMHO&lt;/span&gt; more pleasant) &lt;code&gt;list.each { |item| ... }&lt;/code&gt;.  On that day he made my life a misery by insisting that I replace all my &lt;code&gt;.each&lt;/code&gt; code blocks to &lt;code&gt;for ...&lt;/code&gt;.  After an age of whinging (yes, that is a word &#8211; from Middle English, which means to excessively whine), I completed this useless task.  The next day he somehow determined that &lt;code&gt;.collect&lt;/code&gt; blocks were also inefficient and then insisted on another round of micro optimization that produce very little real world performance benefit if any.&lt;/blockquote&gt;

	&lt;p&gt;Now fast forward a year.  While playing with my recent Ruby 1.9 build on a CentOS server, I noticed the &lt;code&gt;.each&lt;/code&gt; enumerable iteration construct performs faster than the &lt;code&gt;for item in list...end&lt;/code&gt; construct.&lt;/p&gt;


&lt;h4&gt;Executive Summary&lt;/h4&gt;
For those that don&#8217;t have data analysis stamina here are the basic results for Ruby 1.8.6 (with pthreads on CentOS) to two decimal places:
&lt;ul&gt;&lt;li&gt;The &lt;code&gt;for i in list...end&lt;/code&gt; case took 96.65% of the time to run as did the &lt;code&gt;each&lt;/code&gt; case.  &lt;b&gt;Not usually worth the code optimization for 99.99% of the time.&lt;/b&gt;&lt;/li&gt;&lt;li&gt;The &lt;code&gt;collect&lt;/code&gt; case took 92.97% of the time to run as did the &lt;code&gt;list (aka &amp;amp;lt;&amp;amp;lt;)&lt;/code&gt; case. &lt;b&gt;So use the more Ruby-ish constructs to improve readability and reduce chance of human error in coding style.&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;
For those that don&#8217;t have the data analysis stamina here are the basic results for Ruby 1.9.0 (trunk) (with pthreads on CentOS):
&lt;ul&gt;&lt;li&gt;The &lt;code&gt;for i in list...end&lt;/code&gt; case took 125.76% of the time to run as did the &lt;code&gt;each&lt;/code&gt; case.  Or &lt;code&gt;each&lt;/code&gt; case took 79.51% of the time to run as did the &lt;code&gt;for i in list...end&lt;/code&gt; case.  &lt;b&gt;Well, well.  Who sucks now!?&lt;/b&gt;&lt;/li&gt;&lt;li&gt;The &lt;code&gt;collect&lt;/code&gt; case took 84.08% of the time to run as did the &lt;code&gt;list (aka &amp;amp;lt;&amp;amp;lt;)&lt;/code&gt; case.&lt;/li&gt;&lt;/ul&gt;
&lt;h4&gt;Benchmark Script&lt;/h4&gt;
Now let&#8217;s have a look at my benchmark script for completeness (also just in case any coding errors got in to make the benchmark unfair):
&lt;pre&gt;&lt;code&gt;
require 'benchmark'

hash = {}
1_000_000.times {|i| hash[&quot;name#{i}&quot;] = &quot;value#{i}&quot; }

def concat(value)
  &quot;value is #{value}&quot; 
end

Benchmark.bm do |b|
  b.report(&quot;for &quot;) { for key in hash.keys; concat(hash[key]); end; }
  b.report(&quot;each&quot;) { hash.keys.each {|key| concat(hash[key]) } }
end

Benchmark.bm do |b|
  b.report(&quot;&amp;lt;&amp;lt;     &quot;) do
    list = []
    for key in hash.keys
      list &amp;lt;&amp;lt; concat(hash[key])
    end
    list
  end

  b.report(&quot;collect&quot;) do
    hash.keys.collect { |key| concat(hash[key]) }
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;a href=&quot;http://pastie.caboo.se/146748&quot;&gt;See Array#&amp;lt;&amp;lt; vs. Array#collect benchmark in Ruby 1.8.6 here&lt;/a&gt;.
Definitely not the most interesting benchmark script in the world, but it should demonstrate base performance (without too many other variables factoring into performance).  

&lt;h4&gt;Ruby 1.8.6 Results&lt;/h4&gt;
First I ran this benchmark script using a Ruby 1.8.6 build I had in /usr.  This build used the default &lt;code&gt;./configure&lt;/code&gt; options which in Ruby 1.8.x means &lt;code&gt;pthreads&lt;/code&gt; is enabled:
&lt;pre&gt;&lt;code&gt;First run...
      user     system      total        real
for   4.560000   1.400000   5.960000 (  5.962244)
each  4.800000   1.360000   6.160000 (  6.158466)
      user     system      total        real
&amp;lt;&amp;lt;       5.410000   1.450000   6.860000 (  6.855109)
collect  4.980000   1.430000   6.410000 (  6.423387)

Second run...
      user     system      total        real
for   4.570000   1.350000   5.920000 (  5.916540)
each  4.800000   1.370000   6.170000 (  6.165264)
      user     system      total        real
&amp;lt;&amp;lt;       5.550000   1.360000   6.910000 (  6.918924)
collect  4.970000   1.440000   6.410000 (  6.398015)

Third run...
      user     system      total        real
for   4.500000   1.480000   5.980000 (  5.986721)
each  4.810000   1.320000   6.130000 (  6.135532)
      user     system      total        real
&amp;lt;&amp;lt;       5.460000   1.420000   6.880000 (  6.871511)
collect  4.980000   1.420000   6.400000 (  6.392726)

Fourth run...
      user     system      total        real
for   4.490000   1.410000   5.900000 (  5.900563)
each  4.730000   1.400000   6.130000 (  6.131811)
      user     system      total        real
&amp;lt;&amp;lt;       5.560000   1.360000   6.920000 (  6.912522)
collect  4.970000   1.440000   6.410000 (  6.407939)&lt;/code&gt;&lt;/pre&gt;
&lt;a href=&quot;http://pastie.caboo.se/146751&quot;&gt;Results of Array#&amp;lt;&amp;lt; vs. Array#collect benchmark for Ruby 1.8.6&lt;/a&gt;.
Well where to I start?  First of all the differences in the results above running on Ruby v1.8.6 (with pthreads enabled) are quite small anyway.  Let us simply analyze the small amount of data I collected to put things in perspective:
&lt;pre&gt;&lt;code&gt;
In the R shell I did something like...
&amp;gt; for_real_totals &amp;lt;- c(5.962244, 5.916540, 5.986721, 5.900563)
&amp;gt; each_real_totals &amp;lt;- c(6.158466, 6.165264, 6.135532, 6.131811)
&amp;gt; list_real_totals &amp;lt;- c(6.855109, 6.918924, 6.871511, 6.912522)
&amp;gt; collect_real_totals &amp;lt;- c(6.423387, 6.398015, 6.392726, 6.407939)

On to ratios...
&amp;gt; c1_to_c2_ratio &amp;lt;- for_real_totals / each_real_totals
&amp;gt; c1_to_c2_ratio
[1] 0.9681378 0.9596572 0.9757460 0.9622872

&amp;gt; c3_to_c4_ratio &amp;lt;- list_real_totals / collect_real_totals
&amp;gt; c3_to_c4_ratio
[1] 1.067211 1.081417 1.074895 1.078743

Since c4 (aka &quot;collect&quot;) is faster take the inverse ratio...
&amp;gt; c4_to_c3_ratio &amp;lt;- collect_real_totals / list_real_totals
&amp;gt; c4_to_c3_ratio
[1] 0.9370219 0.9247124 0.9303232 0.9270045

On to standard deviations....
&amp;gt; stdev.for &amp;lt;- sd(for_real_totals)
&amp;gt; stdev.for
[1] 0.0398919

&amp;gt; stdev.each &amp;lt;- sd(each_real_totals)
&amp;gt; stdev.each
[1] 0.01658215

&amp;gt; stdev.list &amp;lt;- sd(list_real_totals)
&amp;gt; stdev.list
[1] 0.03110267

&amp;gt; stdev.collect &amp;lt;- sd(collect_real_totals)
&amp;gt; stdev.collect
[1] 0.01347952

&amp;gt; avg.for &amp;lt;- mean(for_real_totals)
&amp;gt; avg.for
[1] 5.941517

&amp;gt; avg.each &amp;lt;- mean(each_real_totals)
&amp;gt; avg.each
[1] 6.147768

&amp;gt; avg.list &amp;lt;- mean(list_real_totals)
&amp;gt; avg.list
[1] 6.889517

&amp;gt; avg.collect &amp;lt;- mean(collect_real_totals)
&amp;gt; avg.collect
[1] 6.405517

&amp;gt; avg.c1_to_c2_ratio &amp;lt;- avg.for / avg.each
&amp;gt; avg.c1_to_c2_ratio
[1] 0.966451

&amp;gt; avg.c3_to_c4_ratio &amp;lt;- avg.list / avg.collect
&amp;gt; avg.c3_to_c4_ratio
[1] 1.075560

&amp;gt; avg.c4_to_c3_ratio &amp;lt;- avg.collect / avg.list
&amp;gt; avg.c4_to_c3_ratio
[1] 0.9297484
&lt;/code&gt;&lt;/pre&gt;
&lt;a href=&quot;http://pastie.caboo.se/146754&quot;&gt;See R analysis code here&lt;/a&gt;.
Interestingly the standard deviations for the &lt;code&gt;for&lt;/code&gt; and &lt;code&gt;list (&amp;lt;&amp;lt;)&lt;/code&gt; cases were more than double the standard deviation of their Rubish counterparts (&lt;code&gt;each&lt;/code&gt; and &lt;code&gt;collect&lt;/code&gt; respectively).  Though I am not 100% sure what this means if anything yet.
&lt;h4&gt;Ruby 1.9 (trunk) Results&lt;/h4&gt;
Ok, now here are the results for running the benchmark script against Ruby 1.9 (trunk) on the same machine, again four times:
&lt;pre&gt;&lt;code&gt;      user     system      total        real
for   4.130000   0.070000   4.200000 (  4.227468)
each  3.310000   0.000000   3.310000 (  3.314974)
      user     system      total        real
&amp;lt;&amp;lt;       4.350000   0.030000   4.380000 (  4.384898)
collect  3.570000   0.100000   3.670000 (  3.701988)

      user     system      total        real
for   4.150000   0.060000   4.210000 (  4.210407)
each  3.350000   0.010000   3.360000 (  3.363656)
      user     system      total        real
&amp;lt;&amp;lt;       4.340000   0.020000   4.360000 (  4.361846)
collect  3.560000   0.110000   3.670000 (  3.668885)

      user     system      total        real
for   4.110000   0.060000   4.170000 (  4.163847)
each  3.320000   0.000000   3.320000 (  3.321745)
      user     system      total        real
&amp;lt;&amp;lt;       4.340000   0.020000   4.360000 (  4.355446)
collect  3.550000   0.110000   3.660000 (  3.668928)

      user     system      total        real
for   4.160000   0.070000   4.230000 (  4.224626)
each  3.370000   0.000000   3.370000 (  3.379422)
      user     system      total        real
&amp;lt;&amp;lt;       4.390000   0.020000   4.410000 (  4.401145)
collect  3.570000   0.110000   3.680000 (  3.676394)&lt;/code&gt;&lt;/pre&gt;
&lt;a href=&quot;http://pastie.caboo.se/146755&quot;&gt;Results of Array#&amp;lt;&amp;lt; vs. Array#collect benchmark for Ruby 1.9&lt;/a&gt;.
Below is my simple data analysis in R shell session:
&lt;pre&gt;&lt;code&gt;
&amp;gt; real_totals.for &amp;lt;- c(4.227468, 4.210407, 4.163847, 4.224626)
&amp;gt; real_totals.each &amp;lt;- c(3.314974, 3.363656, 3.321745, 3.379422)
&amp;gt; real_totals.list &amp;lt;- c(4.384898, 4.361846, 4.355446, 4.401145)
&amp;gt; real_totals.collect &amp;lt;- c(3.701988, 3.668885, 3.668928, 3.676394)
&amp;gt; ratios.for_to_each &amp;lt;- real_totals.for / real_totals.each
&amp;gt; ratios.each_to_for &amp;lt;- real_totals.each / real_totals.for
&amp;gt; ratios.list_to_collect &amp;lt;- real_totals.list / real_totals.collect
&amp;gt; ratios.collect_to_list &amp;lt;- real_totals.collect / real_totals.list
&amp;gt; ratios.for_to_each
[1] 1.275264 1.251735 1.253512 1.250103

&amp;gt; ratios.each_to_for
[1] 0.7841512 0.7988909 0.7977587 0.7999340

&amp;gt; ratios.list_to_collect
[1] 1.184471 1.188875 1.187117 1.197136

&amp;gt; ratios.collect_to_list
[1] 0.8442586 0.8411313 0.8423771 0.8353267

&amp;gt; stdev.for &amp;lt;- sd(real_totals.for)
&amp;gt; stdev.each &amp;lt;- sd(real_totals.each)
&amp;gt; stdev.list &amp;lt;- sd(real_totals.list)
&amp;gt; stdev.collect &amp;lt;- sd(real_totals.collect)
&amp;gt; stdev.for
[1] 0.02945461

&amp;gt; stdev.each
[1] 0.03149215

&amp;gt; stdev.list
[1] 0.02108821

&amp;gt; stdev.collect
[1] 0.01569489

&amp;gt; avg.for &amp;lt;- mean(real_totals.for)
&amp;gt; avg.each &amp;lt;- mean(real_totals.each)
&amp;gt; avg.list &amp;lt;- mean(real_totals.list)
&amp;gt; avg.collect &amp;lt;- mean(real_totals.collect)
&amp;gt; avg.for
[1] 4.206587

&amp;gt; avg.each
[1] 3.344949

&amp;gt; avg.list
[1] 4.375834

&amp;gt; avg.collect
[1] 3.679049

&amp;gt; avg.for / avg.each
[1] 1.257594

&amp;gt; avg.each / avg.for
[1] 0.7951694

&amp;gt; avg.list / avg.collect
[1] 1.189393

&amp;gt; avg.collect / avg.list
[1] 0.8407652
&lt;/code&gt;&lt;/pre&gt;
&lt;a href=&quot;http://pastie.caboo.se/146756&quot;&gt;See R analysis code here&lt;/a&gt;.
Of course, we might also be able to say something about the relative speed of Ruby 1.9 to Ruby 1.8.6 as well (since they were run on the same host, with same script and no noticeable external run-time load differences).  However, I will leave that as an exercise to the reader.

	&lt;p&gt;In the meantime, let me emphasize this point.
&lt;b&gt;&lt;span class=&quot;caps&quot;&gt;DO NOT MAKE MICRO CODE OPTIMIZATIONS WITHOUT JUSTIFICATION&lt;/span&gt;!&lt;/b&gt;  It is usually fruitless and you may well be making more work down the line for yourself and creating a less maintainable system at the same time.&lt;/p&gt;


	&lt;p&gt;I am not advocating changing to the &lt;code&gt;each&lt;/code&gt; coding style if you honestly find it less readable than &lt;code&gt;for item in list&lt;/code&gt;, but there should be no excuse for not using &lt;code&gt;collect&lt;/code&gt; since (a) it is the Ruby way; (b) less error prone; and&#169; more readable!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.managedopensource.com/">
    <author>
      <name>supo</name>
    </author>
    <id>tag:blog.managedopensource.com,2007-10-27:1</id>
    <published>2007-10-27T20:39:00Z</published>
    <updated>2007-10-29T04:19:54Z</updated>
    <link href="http://blog.managedopensource.com/2007/10/27/how-to-scale" rel="alternate" type="text/html"/>
    <title>How do we scale?</title>
<content type="html">
            &lt;p&gt;This is perhaps the most frequently asked question we get at &lt;strong&gt;Managed Open Source&lt;/strong&gt; (MOS).  To answer this we always find it necessary to push back on our clients and ask, &#8220;how to scale what?&#8221;.  This is when most of our clients go silent and realize they haven&#8217;t put much thought into what questions they really should be asking about their current environment.&lt;/p&gt;


	&lt;p&gt;The problem with most organizations is that they do not consider exactly &lt;strong&gt;what&lt;/strong&gt; it is they want or need to scale.  For example, we recently had a startup client that used the Ruby on Rails framework to build their application and wanted us to &#8220;scale Rails&#8221;.  Scaling open source application stacks is what we do best, but in reality we do not actually &#8220;scale Rails&#8221;.  We scale the application, which has specific needs and intricacies.  Ruby and Rails are only two parts of the whole stack.  Not to mention there is more to scaling than simply software stack.  If you are trying to reach an Asian audience, but have data centers in Europe, that wouldn&#8217;t be the optimal way to scale from a data delivery perspective.&lt;/p&gt;


	&lt;p&gt;Sometimes application optimizations only need to deliver more consistent response times or more correct responses, rather than delivering higher throughput or lightning speed.  For example, if your current application configuration can fulfill up to 5,000 requests per second, but only 93% of them get fulfilled without errors, that may not be an acceptable level of response quality.  Instead the application may be better off providing throughput of up to 4,000 requests per second but 99.8% responses are successful.&lt;/p&gt;


	&lt;p&gt;The moral of these examples is when asking &#8220;how should we scale?&#8221; take a few steps back and ask yourself what is unique to your specific application.  What we often find is that there are a few options to tweak at each level of the application stack (including hardware and data center levels) to get to the point where your application can scale better yet not restrict the configuration too much you end up painting your way into a corner.&lt;/p&gt;


	&lt;p&gt;Think about what &#8220;scaling&#8221; means for your application and your business needs rather than just in terms of performance and/or throughput.&lt;/p&gt;


	&lt;p&gt;&lt;b&gt;Managed Open Source&#8217;s&lt;/b&gt; next set of posts will be on scalability vs. performance in more detail since so many people in IT equate the two.&lt;/p&gt;
          </content>  </entry>
</feed>
