<?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>Ramblings &#187; General</title>
	<atom:link href="http://ramblings.gibberishcode.net/archives/category/general/feed" rel="self" type="application/rss+xml" />
	<link>http://ramblings.gibberishcode.net</link>
	<description>about fetching, interpreting, and executing.</description>
	<lastBuildDate>Sat, 01 May 2010 19:19:27 +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>Ramaze vs. Padrino Benchmarks</title>
		<link>http://ramblings.gibberishcode.net/archives/ramaze-vs-padrino-benchmarks/82</link>
		<comments>http://ramblings.gibberishcode.net/archives/ramaze-vs-padrino-benchmarks/82#comments</comments>
		<pubDate>Sat, 01 May 2010 19:19:27 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://ramblings.gibberishcode.net/?p=82</guid>
		<description><![CDATA[I have been developing all of my web-based projects in Ramaze since January 2009 when I switched from Rails to Ramaze.  At that time, I did some benchmark comparisons.  The other day, I heard about Padrino, the micro-framework for Sinatra, which is comparable to the Ramaze micro-framework for Innate.  What caught my [...]]]></description>
			<content:encoded><![CDATA[<p>I have been developing all of my web-based projects in Ramaze since January 2009 when I switched from Rails to Ramaze.  At that time, I did some <a href="http://ramblings.gibberishcode.net/archives/rails-vs-ramaze-performance-comparison/31">benchmark comparisons</a>.  The other day, I heard about <a href="http://www.padrinorb.com">Padrino</a>, the micro-framework for <a href="http://www.sinatrarb.com">Sinatra</a>, which is comparable to the <a href="http://www.ramaze.net">Ramaze</a> micro-framework for <a href="http://github.com/manveru/innate">Innate</a>.  What caught my eye was the benchmark tests the Padrino folks had run that put Ramaze at the bottom of the stack.  I thought to myself, &#8220;no way!&#8221; and set out to run my own benchmarks comparing Padrino to Ramaze as I know at the very least, Ramaze quite outshines Rails&#8217; performance.  Something ain&#8217;t quite right.
</p>
<h2>What was tested?</h2>
<p>There are two things I have grown to love since switching from Rails to Ramaze and that&#8217;s Sequel as the object relational mapper (ORM) and Erubis as the templating engine.  So these are exactly the two components you will find in both of these tests.  Fortunately, both frameworks make it exceedingly easy to utilize these components whereas I had to jump through a few loops to successfully test ActiveRecord in Ramaze against Rails then-only choice as an ORM.
</p>
<p>The main goal in this benchmarking effort is to compare apples to apples and I tried to control for that at every level in the stack from deployment method and worker threads to as close as possible code and computations in rendering each page.  Although the applications remain ridiculously simple, they do test a variety of things most developers would do in a typical app in terms of configuring a sane rendering engine and layout that pulls content from an action&#8217;s template.  Some miscellaneous computations were done for each page such as globally set titles and searching for &#8220;posts&#8221; to render.
</p>
<p>All project sources and the data collected and reported herein is available in the <a href="http://github.com/mwlang/benchmarks/tree/master/2010/">2010 folder on github.com</a>.  I am not entirely sure what the Padrino folks did to control for variables in their benchmarking tests, but here&#8217;s what I did:
</p>
<ol>
<li>Same hardware: Macbook Pro 2.33 GHz Intel Core 2 Duo with 4GB RAM, OS X 10.5.8.</li>
<li>Deployed via Phusion Passenger 2.2.11 on Apache 2.2.14 with six workers running both in live/production mode (using each framework&#8217;s default for these environments).</li>
<li>Same Ruby MRI: ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin9] for both.</li>
<li>Sequel as the ORM, Erubis as the rendering engine.</li>
<li>Nearly identical page and layout templates (varying only by the name &#8220;Ramaze&#8221; and &#8220;Padrino&#8221; in the title tags).</li>
<li>A representive set of identical computations in each project (current time, globally set title, helpers that generate links, etc.</li>
<li>Identical sqlite3 data file with identical model declaration and querying through Sequel.</li>
</ol>
<table style="width: 70%;" border="1">
<thead>
<tr>
<td style="text-align: center;" colspan="2">Apache 2.2.14</td>
</tr>
<tr>
<td style="text-align: center;" colspan="2">Passenger 2.2.11<br/>(gem)</td>
</tr>
<tr>
<td style="text-align: center;" colspan="2">MRI Ruby 1.8.7<br/>(macports)</td>
</tr>
<tr>
<td style="text-align: center;" colspan="1">Ramaze 2010.03 / Innate 2010.03</td>
<td style="text-align: center;" colspan="1">Padrino 0.9.10 / Sinatra 1.0</td>
</tr>
</thead>
</table>
<p>I utilized this simple call to Apache Bench to run through the two test scenarios:<br />
All data collected was based on 10,000 requests at 100 concurrent users after an initial &#8220;warmup&#8221; of the passenger threads with start of 100 requests at 10 concurrent users.  The following command shows the basic set of parameters issued to Apache Bench:
</p>
<pre class="twilight">
ab -n 10000 -c 100 http://padrino.macdoze.local/
</pre>
<p><br/></p>
<h2>The Results</h2>
<p>The following table tabulates the results gathered from Apache Bench as well as passenger-memory-stat.  I ran a short run to warm things up (100 requests, 10 concurrently).  And then ran the big bench at 10,000 requests, 100 concurrently, and then ran again and recorded the results.  At around 5,000 requests, I ran passenger-memory-stat to collect the data during mid-processing.  Swap space was never triggered (0k utilization) during these tests, and CPU utilization was roughly 75% during the test runs.
</p>
<table border="0" cellspacing="0" frame="void" rules="none">
<tbody>
<tr>
<td width="138" height="17" align="left"><strong></strong></td>
<td width="86" align="right"><strong>Padrino</strong></td>
<td width="86" align="right"><strong>Ramaze</strong></td>
<td width="86" align="left"><strong>units</strong></td>
</tr>
<tr>
<td height="16" align="right"><strong>Time taken for tests</strong></td>
<td align="right">38.184</td>
<td align="right">51.072</td>
<td align="left"><em>seconds</em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Complete requests</strong></td>
<td align="right">10000</td>
<td align="right">10000</td>
<td align="left"><em></em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Failed requests</strong></td>
<td align="right">0</td>
<td align="right">0</td>
<td align="left"><em></em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Write errors</strong></td>
<td align="right">0</td>
<td align="right">0</td>
<td align="left"><em></em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Total transferred</strong></td>
<td align="right">16430000</td>
<td align="right">17440000</td>
<td align="left"><em>bytes</em></td>
</tr>
<tr>
<td height="16" align="right"><strong>HTML transferred</strong></td>
<td align="right">13320000</td>
<td align="right">14050000</td>
<td align="left"><em>bytes</em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Requests per second</strong></td>
<td align="right">261.89</td>
<td align="right">195.80</td>
<td align="left"><em>[#/sec] (mean)</em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Time per request</strong></td>
<td align="right">381.837</td>
<td align="right">510.717</td>
<td align="left"><em>[ms] (mean)</em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Time per request</strong></td>
<td align="right">3.818</td>
<td align="right">5.107</td>
<td align="left"><em>[ms] (mean, across all concurrent requests)</em></td>
</tr>
<tr>
<td height="17" align="right"><strong>Transfer rate</strong></td>
<td align="right">420.20</td>
<td align="right">333.48</td>
<td align="left"><em>[Kbytes/sec] received</em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Resident Memory per Worker</strong></td>
<td align="right">41.9</td>
<td align="right">26.3</td>
<td align="left"><em>MB</em></td>
</tr>
</tbody>
</table>
<h2>Throughput</h2>
<p>Everybody likes to <a href="http://www.therailsway.com/2009/1/6/requests-per-second">talk about throughput</a>, so lets start there.  As you can see, Padrino processed the requests 1.34 times faster than Ramaze.  In other words, Padrino is pushing bytes at about 25% faster than Ramaze is.  Be forewarned that throughput doesn&#8217;t necessarily equate to user response times.  This metric simply tells you the load at which your system is capable of delivering content at.
</p>
<p><img src='http://ramblings.gibberishcode.net/wp-content/uploads/2010/05/throughput.png' alt='throughput' class='alignnone' /></p>
<h2>Time per Request</h2>
<p>Time per request helps you see about how long an average user request takes for a given load.  As you can see here, with times in the milliseconds, we&#8217;re talking about numbers that will easily be swallowed in the noise of network latency.  Even so, we are looking at a similar performance ratio as with the throughputs above.
</p>
<p><img src='http://ramblings.gibberishcode.net/wp-content/uploads/2010/05/time_per_request.png' alt='Time per Request' class='alignnone' /></p>
<h2>Memory Consumption</h2>
<p>This final graph shows a surprising difference in memory consumption between the two micro-frameworks.  Here, Ramaze trumps Padrino&#8217;s memory footprint, utilizing only 63% of the memory that Padrino requires.  This means that you can run more workers per server using Ramaze than you can with Padrino before you consume all the RAM on the server.
</p>
<p><img src='http://ramblings.gibberishcode.net/wp-content/uploads/2010/05/memory.png' alt='Memory Usage' class='alignnone' /></p>
<h2>Conclusion</h2>
<p>Padrino has certainly set the new standard for raw throughput performance in Ruby-based web frameworks, but don&#8217;t be deceived into thinking its blowing its competition away by leaps and bounds.  If you&#8217;re one of those shops that is fortunate to have an infinite supply of hardware to throw at the problem, then Padrino makes a good choice for maximizing throughput per server.  I know I will certainly strongly consider utilizing Padrino in a couple of up-coming projects.
</p>
<p>I have found that one area Padrino is shining where Ramaze is not quite there yet, is an excellent website with just the right information to get started developing new projects.  I was really impressed with Sinatra&#8217;s approach to named routes with the RESTful inspired get/post/put/delete DSL that is further enhanced by Padrino&#8217;s helpers. The recent Padrino enhancements to their router helpers for &#8220;mounting&#8221; more than one application is a bit more intuitive to me, especially with the ample documentation on just how to configure for all the most common routing scenarios than Ramaze&#8217;s.  I still have not quite implemented mulitiple mini-apps under Ramaze despite multiple attempts.
</p>
<p>Ramaze has been around long enough that it has a sizable body of legacy/obsolete documentation floating around the &#8216;net that you need to wade through before finding the right documentation that&#8217;s relevant to the post Ramaze/Innate split/re-architecture.  The documentation&#8217;s certainly there for Ramaze, but if you don&#8217;t know exactly where to look, or your Google-fu is suffering during your time of need, the only place to find it is by resorting to reading the source or hoping someone on the #Ramaze IRC readily finds it on your behalf (which they&#8217;re pretty darn good at doing).
</p>
<p>Padrino also differs itself from Ramaze and following the Rails camp a little more by introducing an opinionated project structure and set of helpers that is well-documented and easy to find.  Ramaze, on the other hand, strives hard not to push opinions onto the developers on how they choose to structure their projects.  Because of Padrino&#8217;s choices, they&#8217;re also able to provide a nice set of well-rounded generators and rake tasks to give you a much nicer &#8220;out of box experience&#8221; especially suitable for the Rubyist that is still learning his way around the Ruby language.  I would love to see the Ramaze community come together to generate an equally strong set of documentation and best-practices rolled into a few good generators to help the aspiring developer get off the ground with Ramaze a lot faster from the get-go.
</p>
<p>Both Ramaze and Padrino have strong technical merits, and as you can see from the benchmarks above, both are quite performant platforms in their own right with Padrino having the edge in speed and Ramaze having the edge in memory consumption.  For developers like me churning out many different small websites for various customers and running all of those websites off one physical box, Ramaze continues fill my needs in that corner with its smaller memory consumption footprint.  1.3 microseconds for a collection of customers registering 25 to 100 page views a day each isn&#8217;t enough to of a difference to concern myself with a wholesale switch in platforms.  However, I definitely see a bright future for Padrino in my toolbox as I endeavor to build collections of reusable mini-apps that can be mounted in many easily configurable combinations for each deployment.</p>
]]></content:encoded>
			<wfw:commentRss>http://ramblings.gibberishcode.net/archives/ramaze-vs-padrino-benchmarks/82/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>A comparison JRuby vs. Ruby MRI with Sequel</title>
		<link>http://ramblings.gibberishcode.net/archives/a-comparison-jruby-vs-ruby-mri-with-sequel/74</link>
		<comments>http://ramblings.gibberishcode.net/archives/a-comparison-jruby-vs-ruby-mri-with-sequel/74#comments</comments>
		<pubDate>Sun, 25 Apr 2010 21:10:55 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://ramblings.gibberishcode.net/?p=74</guid>
		<description><![CDATA[For the most part, I stick with Apache 2, Phusion Passenger, and Ruby MRI as my deployment stack.  Even so, I regularly foray into other territories to see what&#8217;s going on in the wide world of Ruby.  This weekend, I turned my eyes to JRuby again for the first time in almost 18 [...]]]></description>
			<content:encoded><![CDATA[<p>For the most part, I stick with Apache 2, Phusion Passenger, and Ruby MRI as my deployment stack.  Even so, I regularly foray into other territories to see what&#8217;s going on in the wide world of Ruby.  This weekend, I turned my eyes to JRuby again for the first time in almost 18 months.  I wanted to explore how what JRuby would do performance-wise with a database intensive application.
</p>
<p>I have been doing some data loading from one database into another using <a href="http://kettle.pentaho.org/">Pentaho&#8217;s Kettle</a> and that got me curious about JRuby since Pentaho&#8217;s toolset is built upon Java.  Quite simply, my work with Kettle got me wondering, &#8220;why not JRuby?&#8221;  I&#8217;ve been hearing some great things about JRuby and how it greatly leverages the Java stack to bring you all manner of improvements over Ruby MRI, notably scalability on any one of the many Java deployment container servers and native-system threading capabilities.
</p>
<p>I didn&#8217;t pull down the latest and greatest JRuby libraries to my mac.  I simply got what I could get via macports:
</p>
<pre class="twilight">
sudo port install apache-ant
sudo port install jruby
</pre>
<p>I don&#8217;t know if the apache-ant port was actually needed or not, but I&#8217;d read that JRuby depended on ant to compile its components, so, fast as I could type the two port commands, and watch the terminal session actually install both, I was done. The above got me jruby 1.4.0 (ruby 1.8.7 patchlevel 174) (2010-04-22 6586) (Java HotSpot(TM) Client VM 1.5.0_22) [i386-java] and I was ready to play.
</p>
<h2>The JDBC Drivers</h2>
<p>What I was really curious to find out is whether JRuby and sequel was all that hard to get set up and working with Sql Server 2000 MSDE and MySQL.  Both proved fairly simple to get working, although I had to patch Sequel 3.10.0 to get MySQL working with JDBC.
</p>
<h3>Microsoft SQL Server JDBC Driver</h3>
<p>I was impressed with the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=a737000d-68d0-4531-b65d-da0f2a735707&#038;displaylang=en">Microsoft SQL Server JDBC Driver 3.0</a>.  It worked as advertised and was pretty straightforward to install, although I had to Google a bit to find out *how* since wading through the help docs didn&#8217;t help me.  I found out that simply putting the jar file in JRuby&#8217;s lib folder was all that was needed.  If you use port to install JRuby as I did above, then that folder on your mac is:
</p>
<pre class="twilight">
/opt/local/share/java/jruby/lib
</pre>
<p>The latest GA version of the SQL Server JDBC 3.0 driver at the time of this writing was version 3.0.1301.101.
</p>
<h3>MySQL JDBC Driver</h3>
<p><a href="http://dev.mysql.com/downloads/connector/j/">MySQL&#8217;s JDBC driver</a> was equally easy to download and copy the jar to the above referenced JRuby lib folder.  The latest GA driver version at the time of this writing was 5.1.12.  One small change I had to make to Sequel 3.10.0 was to add the Statement.RETURN_GENERATED_KEYS option to the executeUpdate call in Sequel&#8217;s adaptors/jdbc.rb.  The <a href="http://groups.google.com/group/sequel-talk/browse_thread/thread/207242e65bfcedce">following thread on sequel-talk</a> covers this.
</p>
<h2>The Script</h2>
<p>To find out how JRuby and Ruby MRI stacked up, I wrote a script, <a href="http://gist.github.com/378689">available on github.com</a>, that generates 20,000 rows of fake data that might be typical of what you&#8217;d find on an invoice/order table in an e-commerce site.  I then clone this data to another table.  Both of these actions are fairly heavy I/O operations and the <a href="http://kenai.com/projects/jruby/pages/Benchmarks">JRuby page on benchmarking</a> warns this will be a bit slower than MRI.  The test results tend to bear this out.  The real-world scenario where I am doing this sort of cloning is copy and consolidate data from various databases into a data-warehouse setting from production transactional systems.
</p>
<h2>The Results</h2>
<p>Running the script in Ruby MRI and in JRuby, I found JRuby to be generally slower than Ruby MRI but still roughly on par when subjected to the usual single threaded approach to writing Ruby code that most developers use.  However, JRuby definitely showed some marked improvements when you took the time to craft a threaded approach to the problem while Ruby MRI took a performance hit with a threaded approach.  Unfortunately, boosting the thread count from 4 to 8 did almost nothing, so there&#8217;s some practical level to how many threads can be utilized in a scenario like this.  I did notice during the test runs that my CPU and disk and network I/O never quite maxed out although the JRuby in server mode seemed to to push things the hardest with CPU hovering at about 146% (200% max given core 2 duo Intel).
</p>
<p>None of these numbers inspire me to use Ruby or JRuby for any heavy lifting any time soon.  Pentaho&#8217;s Kettle may sway me to use a Java solution as it can scale a bit further with appropriate resources than my current solution of Delphi compiled executable running on Windows XP.  The Delphi-based solution can churn through about 2 million rows of data in 15 minutes.  These solutions in Ruby, by comparison would take roughly 8 to 14 hours to churn through the same 2 million rows of data.
</p>
<table>
<tr>
<th>Test Name</th>
<th>JRuby Client</th>
<th>JRuby Server</th>
<th>Ruby MRI</th>
</tr>
<tr>
<td>Create 20k Records</td>
<td>111.085</td>
<td>86.989</td>
<td>105.050</td>
</tr>
<tr>
<td>Clone with 1 Thread</td>
<td>63.268</td>
<td>55.652</td>
<td>47.930</td>
</tr>
<tr>
<td>Clone with 4 Threads</td>
<td>38.000</td>
<td>31.070</td>
<td>57.220</td>
</tr>
</table>
<pre class="twilight">
>> jruby -S test.rb
      user     system      total        real
populate sample_data table: creating the sample_data table...
populating sample_data with 20000 rows
sample data:   100% |oooooooooooooooooooooooooooooooooooooooooo| Time: 00:01:50
111.085000   0.000000 111.085000 (111.085000)

clone sample_data to cloned_data: creating the cloned_data table...
cloning 20000 records for sample_data
sample_data:   100% |oooooooooooooooooooooooooooooooooooooooooo| Time: 00:01:03
 63.268000   0.000000  63.268000 ( 63.267000)

threaded clone: cloning 20000 records for sample_data
sample_data:   100% |oooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:37
 38.000000   0.000000  38.000000 ( 38.000000)
</pre>
<p><br/></p>
<pre class="twilight">
>> jruby -S test.rb --server
      user     system      total        real
populate sample_data table: creating the sample_data table...
populating sample_data with 20000 rows
sample data:   100% |oooooooooooooooooooooooooooooooooooooooooo| Time: 00:01:26
 86.989000   0.000000  86.989000 ( 86.989000)

clone sample_data to cloned_data: creating the cloned_data table...
cloning 20000 records for sample_data
sample_data:   100% |oooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:55
 55.652000   0.000000  55.652000 ( 55.652000)

threaded clone: cloning 20000 records for sample_data
sample_data:   100% |oooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:30
 31.070000   0.000000  31.070000 ( 31.070000)
</pre>
<p><br/></p>
<pre class="twilight">
>> ruby test.rb
      user     system      total        real
populate sample_data table: creating the sample_data table...
populating sample_data with 20000 rows
sample data:   100% |oooooooooooooooooooooooooooooooooooooooo| Time: 00:01:45
 85.370000   4.460000  89.830000 (105.049892)

clone sample_data to cloned_data: creating the cloned_data table...
cloning 20000 records for sample_data
sample_data:   100% |oooooooooooooooooooooooooooooooooooooooo| Time: 00:00:47
 31.700000   3.500000  35.200000 ( 47.930685)

threaded clone: cloning 20000 records for sample_data
sample_data:   100% |oooooooooooooooooooooooooooooooooooooooo| Time: 00:00:56
 39.450000   3.760000  43.210000 ( 57.226705)
</pre>
<p><br/></p>
]]></content:encoded>
			<wfw:commentRss>http://ramblings.gibberishcode.net/archives/a-comparison-jruby-vs-ruby-mri-with-sequel/74/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting Ruby to talk to MSDE</title>
		<link>http://ramblings.gibberishcode.net/archives/getting-ruby-to-talk-to-msde/22</link>
		<comments>http://ramblings.gibberishcode.net/archives/getting-ruby-to-talk-to-msde/22#comments</comments>
		<pubDate>Fri, 09 Apr 2010 01:07:45 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Configuration]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Ruby Language]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Setups]]></category>

		<guid isPermaLink="false">http://ramblings.gibberishcode.net/?p=22</guid>
		<description><![CDATA[Getting Ruby to talk to Microsoft SQL Server 2005 is one thing.  Getting Ruby to talk to Microsoft SQL Server Developer Edition 2000, has one twist that threw me off for hours.  Here, I&#8217;ll show you how to do and hopefully save you lots of frustration and brain damage from banging your head [...]]]></description>
			<content:encoded><![CDATA[<p>Getting Ruby to talk to Microsoft SQL Server 2005 is one thing.  Getting Ruby to talk to Microsoft SQL Server Developer Edition 2000, has one twist that threw me off for hours.  Here, I&#8217;ll show you how to do and hopefully save you lots of frustration and brain damage from banging your head against the wall.
</p>
<p>I won&#8217;t cover a complete Ruby and Rails/Ramaze/Sinatra installation.  This post assumes you have that much down pat, so we&#8217;ll pick up the ball with installing FreeTDS, unixODBC, Ruby ODBC
</p>
<p>If you&#8217;re using Ubuntu 8.10, you can get away with installing everything from packages with the following:
</p>
<pre class="twilight">
apt-get install  unixodbc freetds-common tdsodbc \
             libodbc-ruby1.8 \
             libdbi-ruby1.8 libdbd-odbc-ruby \
             autoconf make
</pre>
<p><b>NOTE:  I wrote this article and right before publishing, attempted to replicate these results on both mac OS X and CentOS 5.  Both failed to work with the technique I thought I had all nice and worked out.  I spent several hours over many months trying to find out exactly what&#8217;s different between the packages, but never got very far with my investigations.  For a long time, it looked to me like both the ODBC packages and the FreeTDS packages need to be tweaked to properly handle [SERVER]\[DB_INSTANCE] construct that MSDE uses vs. just [SERVER] that the full-fledged SQL Server uses.</b>  This, after all, is the convention of the Windows ODBC driver and DSN definitions.  However, there&#8217;s a really simple solution that I hit upon on Actual Technologies&#8217; website that led me to a true universal solution and that&#8217;s to learn the port the INSTANCE runs on and set up the DSN specifically to that port!
</p>
<p>But beware, the above doesn&#8217;t get you all of the freetds tools, most importantly the tsql command which can help you with debugging issues before getting into the ODBC game (that is, direct TDS connections to your SQL Server).  So, to cover the most distros possible, I&#8217;ll document the &#8220;from source&#8221; approach for *nix systems and macports for Macs so you&#8217;ll find two sets of installation instructions for every step.</p>
<h2>Preparing your Environment</h2>
<p>I prefer to pull down all source packages into my local user directory under a &#8220;~/src&#8221; folder.  The instructions that follow assume you&#8217;re in this folder.  If you&#8217;re not, then please make the appropriate substitutions as you follow along.  Additionally, I configure and compile most things as a regular user then use sudo to install system-wide as a &#8220;super user.&#8221;
</p>
<h2>Install unixODBC</h2>
<p>unixODBC provides the ODBC connectivity for the TDS driver.</p>
<pre class="twilight">
wget http://www.unixodbc.org/unixODBC-2.2.14.tar.gz
tar zxfv unixODBC-2.2.14.tar.gz
cd unixODBC-2.2.14
./configure  --enable-gui=no
make
sudo make install
</pre>
<h3>On Macs</h3>
<pre class="twilight">
sudo port install unixODBC
</pre>
<h3>On CentOS</h3>
<pre class="twilight">
sudo yum install unixODBC unixODBC-devel
</pre>
<h2>Install FreeTDS</h2>
<p>FreeTDS provides the open source implementation of the protocol implemented by both Sybase and Microsoft SQL Server.
</p>
<pre class="twilight">
wget ftp://ftp.ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-stable.tgz
tar zvxf freetds-stable.tgz
cd freetds-0.82/
sudo ./configure  --with-unixodbc=/usr/local
sudo make
sudo make install
</pre>
<h3>On Macs</h3>
<pre class="twilight">
sudo port install freetds
</pre>
<h3>On CentOS</h3>
<pre class="twilight">
sudo yum install freetds
</pre>
<h2>Install ruby-odbc</h2>
<p>The ruby-odbc package provides the ruby bindings for ODBC connectivity.
</p>
<pre class="twilight">
wget http://www.ch-werner.de/rubyodbc/ruby-odbc-0.9995.tar.gz
tar zvxf ruby-odbc-0.9995.tar.gz
cd ruby-odbc-0.9995/
ruby extconf.rb
make
sudo make install
</pre>
<h3>On Macs</h3>
<pre class="twilight">
sudo port install rb-odbc
</pre>
<h2>Install ruby DBI</h2>
<pre class="twilight">
wget http://rubyforge.org/frs/download.php/655/ruby-dbi-all-0.0.23.tar.gz
tar zvxf ruby-dbi-all-0.0.23.tar.gz
cd ruby-dbi-all
ruby setup.rb config --with=dbi,dbd_odbc
ruby setup.rb setup
sudo ruby setup.rb install
</pre>
<h2>Configure FreeTDS and ODBC</h2>
<p>If you&#8217;re connecting to either SQL Server 2000 or SQL Server 2005 Standard, Enterprise, etc., then the typical approach is to add an entry for the server to /etc/freetds/freetds.conf and then reference that entry in the /etc/odbc.ini.  Sometimes, these files get installed in /usr/local/etc.  If so, then I will usually symlink the files into /etc for convenience, so that&#8217;s what&#8217;s referenced below.
</p>
<p>My server is called &#8220;apvdbs01&#8243; (the WINS name) with an IP Address of 10.0.2.2 and the database I&#8217;m connecting to is called &#8220;test_development&#8221; while &#8220;username&#8221; and &#8220;passwd&#8221; should be substituted with an valid user account and credentials for successfully connection to the database server.
</p>
<p>
Add a server entry for your server (which I typically give same name as Windows Server) to /etc/freetds.conf, so that host points to the SQL Server address:
</p>
<pre class="twilight">
[apvdbs01]
host = 10.0.2.2
port = 1433
tds version = 7.0
</pre>
<p>TDS version 7.0 is for SQL Server 2000.  If you have SQL Server 2005, then tds version is 8.0.</p>
<pre class="twilight">
tsql –S apvdbs01 –U username –P passwd
</pre>
<p>Once you can connect directly with the TDS drivers, move on to adding the ODBC driver entries.</p>
<p>Add the FreeTDS ODBC driver by editing “/etc/odbcinst.ini” (make sure “/usr/local/lib/libtdsodbc.so” exists first):
</p>
<pre class="twilight">
[FreeTDS]
Description     = TDS driver (Sybase/MS SQL)
Driver          = /usr/lib/odbc/libtdsodbc.so
Setup           = /usr/lib/odbc/libtdsS.so
</pre>
<p>Add a new DSN to “/etc/odbc.ini”:</p>
<pre class="twilight">
[test_development]
Driver          = FreeTDS
Description     = ODBC connection via FreeTDS
Trace           = No
ServerName      = apvdbs01
Database        = test_development
</pre>
<p>So, &#8220;FreeTDS&#8221; is the driver that we gave for the lib TDS ODBC connector in the odbcinst.ini file (this allows you to install and maintain multiple versions of the libtdsodbc.so file).  We reference this driver in the odbc.ini file with the &#8220;Driver&#8221; entry and we reference the actual server data in the freetds.conf file via the &#8220;ServerName&#8221; entry.
</p>
<p>Now that you have ODBC configured for FreeTDS, test it with:</p>
<pre class="twilight">
	isql test_development username passwd
</pre>
<h2>But that doesn&#8217;t work for MSDE!</h2>
<p>The above will get you connected to a standard or enterprise SQL Server 2000/2005 installation, but does not work for an Embedded SQL Server 2000/2005 installation.  After trying many permutations, I finally came up with a configuration that actually works.  One of the key things to know about MSDE is that the MSDE server instance is in the form of &#8220;servername\instance&#8221; rather than straight up &#8220;servername&#8221; as with standard/enterprise installations.  This is known as a &#8220;named instance.&#8221;  The trick to connecting?  Find out the port the named instance is listening on and connect to that port rather than the 1433 port!</p>
<p>You can determine the port used by the instance by using the Server Network Utility in the Microsoft SQL Server program group on the Windows server where your database resides. Select the instance name from the drop down list and select TCP/IP from the list of enabled protocols. This will show you the port number for that instance.</p>
<pre class="twilight">
[test_msde2000]
Driver         = FreeTDS
Description    = ODBC connection via FreeTDS
Server         = 10.0.2.2
Database       = my_test_db
Port           = 1348
TDS_Version    = 7.0
</pre>
<p>I could then connect to the MSDE instance like so:</p>
<pre class="twilight">
isql test_msde2000 username passwd
</pre>
<h2>Test ODBC connectivity from Ruby</h2>
<p>If both tsql and isql commands work, then you&#8217;re well on your way to connecting to SQL Server via Ruby.  To test Ruby with the above ODBC configurations:</p>
<pre class="twilight">
irb
require "dbi"
dbh = DBI.connect("dbi:ODBC:test_development", "username", "passwd")
</pre>
<h2>Connecting with Sequel</h2>
<p>One of my favorite tools for connecting to SQL DBMS&#8217; is Sequel, which is maintained by Jeremy Evans.  To connect using Sequel, install the gem:
</p>
<pre class="twilight">
sudo gem install sequel
</pre>
<p>And then give this a shot:</p>
<pre class="twilight">
irb
require 'rubygems'
require 'sequel'

DB = Sequel.odbc('test_development', :db_type => 'mssql', :user => 'username', :password => 'passwd')
</pre>
<h2>References</h2>
<p>http://www.freetds.org/userguide/confirminstall.htm</p>
<p>http://www.unixodbc.org/odbcinst.html</p>
<p>http://www.actualtech.com</p>
]]></content:encoded>
			<wfw:commentRss>http://ramblings.gibberishcode.net/archives/getting-ruby-to-talk-to-msde/22/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>What makes a top award candidate, anyhow?</title>
		<link>http://ramblings.gibberishcode.net/archives/what-makes-a-top-award-candidate-anyhow/37</link>
		<comments>http://ramblings.gibberishcode.net/archives/what-makes-a-top-award-candidate-anyhow/37#comments</comments>
		<pubDate>Sat, 01 Aug 2009 16:30:04 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Ruby Language]]></category>
		<category><![CDATA[imagemagick]]></category>
		<category><![CDATA[inkscape]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[sequel]]></category>

		<guid isPermaLink="false">http://ramblings.gibberishcode.net/?p=37</guid>
		<description><![CDATA[In our local Linux user group mailing list, one of the participant asked the group for recommendations for open source software projects that should be considered for a prominent publication&#8217;s top 100 awards.  The ensuing discussion got me to wondering:  What is the purpose behind doing the awards?  Most of what I [...]]]></description>
			<content:encoded><![CDATA[<p>In our local Linux user group mailing list, one of the participant asked the group for recommendations for open source software projects that should be considered for a prominent publication&#8217;s top 100 awards.  The ensuing discussion got me to wondering:  What is the purpose behind doing the awards?  Most of what I see talked about are all well-known and well-used, such as git, mercurial, word press, joomla, django, and so on.  Usually, when I look at a list like this, I&#8217;m looking to uncover new and undiscovered projects that have real potential to make a real impact in my daily life and thus was somewhat surprised that such mature projects are being so heavily promoted in the discussions.
</p>
<p>Its not that I don&#8217;t think these tools are worthy contenders.  Most of them, I have used fairly extensively myself over the years.  The suggested contenders are solid and mature projects, but they feel decidedly &#8220;old hat&#8221; to me much as apache, postfix, vim, bind, and the linux kernel probably feels to the system administrator.  In other words, they&#8217;re ubiquitous, so why signal them out with some sort of top 100 reward?
</p>
<p>These days, I have adopted Ruby as my language of choice, so I have moved away from Python and PHP.  While this has largely meant I develop Ruby on Rails applications.  However, as my Ruby skills grow, this also means going far and wide in many other ruby-based tools (such as rake, sake, and rack for system-level or middleware tools).  I am now using ruby for quick and dirty systems administration tasks (such as the short script I wrote to find all currently assigned IP addresses on our office network), automating deployments (capistrano, puppet, chef), marshaling data from one database system to another, and even with extensive image-processing (resizing, conversion of formats, compressing, etc.).
</p>
<p>So what, in my view, warrants a top 100 award recognition?  I like to see new and exciting projects on these lists.  If a project&#8217;s on the list, I like to know that they are extremely active and rapidly gaining mind-share and penetration into the community.  I want to know a little bit about how they put a new spin on an old problem and the impact they have been able to make, not only in the project&#8217;s direct vertical niche, but across the board.  A few years ago, Ruby on Rails arrived on the scene as a game-changer, not only for putting Ruby on the map as a viable language, but as a bona fide development framework for delivering web-based services.  Ruby on Rails turned the Java world on its head and forced Java developers to drastically improve their productivity tools then in common practice; they evangelized convention over configuration and brought many fantastic ideals such as Agile development and RESTful APIs to the forefront of many, many developers&#8217; minds.
</p>
<p>To my way of thinking, though, Ruby on Rails is now old news.  Newcomers will stumble upon Ruby and Rails through word of mouth or simply googling for a solution to some problem they&#8217;re trying to solve.  That&#8217;s the problem I see with top-100 lists paying tribute year after year to the same old mature projects.  Whether its Ruby on Rails or Word Press or Joomla or Django, all of these are easily discovered and well-written about by anybody with decent querying skills.  So what&#8217;s out there today that&#8217;s refreshing and hard to find? Yet, is making a huge impact on the community?  Here are a few that I think are worthy contenders (and yes, they are a little heavy on the Ruby side)&#8230;
</p>
<h2>Rack</h2>
<p><a href="http://rack.rubyforge.org/">Rack: a Ruby Webserver Interface</a>.  What I find phenomenal about Rack is its adoption by so many frameworks that are delivering web-based services.  Micro-frameworks like Ramaze and Camping and Sinatra were early adopters of Rack and such adoption led to far smaller code-bases in each as well as significant performance boosts and, as if that wasn&#8217;t enough, enabled much easier transition from Ruby 1.8 to 1.9.
</p>
<h2>Inkscape and ImageMagick</h2>
<p>Speaking of image processing, I am not sure if many have encountered <a href="http://www.imagemagick.org/script/index.php">ImageMagick</a> and the Ruby bindings offered via <a href="http://rmagick.rubyforge.org/">RMagick</a>, but definitely worth a look-see.  As of this year, I do almost all of my creative graphics work in <a href="http://www.inkscape.org">Inkscape</a> and <a href="http://www.gimp.org/">The Gimp</a> and use ImageMagick to automate some pretty impressive transformations of those images outside the GUI.  Before Inkscape became mature enough to use on daily basis (which, by my reckoning is only in the last 18 months or so), I was heavily reliant on Adobe&#8217;s Illustrator and companion Photoshop apps.  I never would&#8217;ve imagined two years ago that I could completely do away with these packages, let alone begin to automate much of the repetitive tasks that I put those resulting images through (resizing, cropping, web-optimizing, etc.) with a collection of well-written OSS tools.
</p>
<h2>Ramaze and Sequel</h2>
<p>One last pair of tools I think is worthy of consideration, especially for web-based ruby developers is <a href="http://sequel.rubyforge.org/">Sequel</a> and <a href="http://ramaze.net/">Ramaze</a>. Sequel is an object-relational-mapping library that makes working with SQL databases a real pleasure for Ruby developers.  The maintainers seem to have taken the best of the best and rolled those ideas into one coherent and extremely fast library for accessing just about any database out there.  I have fooled around with DataMapper and have worked extensively with ActiveRecord and I must say Sequel really is rung or two above these libraries and I look forward to continuing to adopt Sequel.
</p>
<p>I ran into Sequel by way of the Ramaze project, which is a micro-framework for building web-based applications.  Unlike Ruby on Rails, which tends to generate tons of scaffold/skeletal code for you to begin hacking away on to build your projects, Ramaze takes the opposite tack in that it provides little to no scaffolding or auto-generated code.  Instead, the mindset is squeezing the maximum amount of functionality out of every line of code you do write.  For a Ruby on Rails developer coming to Ramaze, the feeling is very much like the first time I took off on a bicycle without the training wheels attached.  You feel wildly uncontrolled and like you may fall at any moment, but a little encouragement from the warm friendly community gets you going straight and true and the amount of code you&#8217;re NOT writing, reading, reviewing, nor specking tests for really begins to jump out at you!</p>
]]></content:encoded>
			<wfw:commentRss>http://ramblings.gibberishcode.net/archives/what-makes-a-top-award-candidate-anyhow/37/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rails vs. Ramaze Performance Comparison</title>
		<link>http://ramblings.gibberishcode.net/archives/rails-vs-ramaze-performance-comparison/31</link>
		<comments>http://ramblings.gibberishcode.net/archives/rails-vs-ramaze-performance-comparison/31#comments</comments>
		<pubDate>Thu, 19 Feb 2009 21:07:24 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Servers]]></category>
		<category><![CDATA[Systems]]></category>
		<category><![CDATA[mri ruby]]></category>
		<category><![CDATA[passenger]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[ree ruby]]></category>

		<guid isPermaLink="false">http://ramblings.gibberishcode.net/?p=31</guid>
		<description><![CDATA[One of my biggest concerns of late is that my &#8220;more than just a little trivial&#8221; Rails projects seem to find their way straight into the heavyweight category in no time at all.  While I am quite hopeful that Merb being the 3.0 version of Rails will resolve many of the issues I face [...]]]></description>
			<content:encoded><![CDATA[<p>One of my biggest concerns of late is that my &#8220;more than just a little trivial&#8221; Rails projects seem to find their way straight into the heavyweight category in no time at all.  While I am quite hopeful that Merb being the 3.0 version of Rails will resolve many of the issues I face today, I have no idea when I can truly count on Rails 3.0&#8217;s arrival at the party.  Thus, I have begun looking at other frameworks that are available today.</p>
<h2>Introducing Ramaze</h2>
<p>One I found is <a href="http://www.ramaze.net">Ramaze</a>.  I have to say that Ramaze is a very minimalist approach to a framework that is actually rather enlightening.  For one coming from a Rails&#8217; world, it can feel a bit sparse at first.  But lately, I&#8217;m attributing my lack of comfort to being put on my toes to do some actual real Ruby coding.  Its both a little scary and liberating at the same time.  I have found that I am enjoying Ruby a lot more as a result of my exposure to Ramaze and my thought process is actually radically changing, almost like a Visual Basic programmer going to Borland Delphi might feel.</p>
<p>So I decided to take a hard look at performance metrics between Rails and Ramaze&#8217;s.  At the same time, I wanted to see how MRI 1.8.7 stacked up against Ruby Enterprise Ed. 1.8.6, so I&#8217;m satisfying a dual curiosity herein.  Being quite happy with <a href="http://www.mod_rails.com">Phusion Passenger</a>, I decided to set things up with Apache 2.2.9 + Passenger + Rails/Ramaze.  Since I&#8217;m quite comfortable with ERB and ActiveRecord, I tweaked Ramaze to be a bit more like the familiar Rails world I am familiar with.</p>
<h2>Un-DRYing the Results</h2>
<p>There&#8217;s no point in generating a lot of data and reporting on it if others cannot repeat yourself (CRY!) in replicating the results, so with that in mind, I attempt to refrain from further bad turn of words by busying myself in pushing everything I utilized to <a href="http://github.com/mwlang/benchmarks/tree/master">github.com</a> and documenting the basic <a href="http://ramblings.gibberishcode.net/archives/bootstrap-ubuntu-server-810-intrepid-64-bit/29">bootstrapping of Ubuntu Intrepid</a>.  For these tests in particular, I used two scripts, <a href="http://github.com/mwlang/bootstrap-scripts/blob/af44b371a24a79820c98fcf9cfe014b7a523a24a/ubuntu/intrepid/bootstrap-passenger-std.sh">bootstrap-passenger-std.sh</a> and <a href="http://github.com/mwlang/bootstrap-scripts/blob/af44b371a24a79820c98fcf9cfe014b7a523a24a/ubuntu/intrepid/bootstrap-passenger-ent.sh">bootstrap-passenter-ent.sh</a> to set up four distinct configurations under the Ruby1.8 interpreter.  Ruby 1.9.1. was a bit difficult to set up and there is a <a href="http://github.com/mwlang/bootstrap-scripts/blob/af44b371a24a79820c98fcf9cfe014b7a523a24a/ubuntu/intrepid/bootstrap-passenger-191.sh">bootstrap-passenger-191.sh</a> script that I assembled as I installed things, but I haven&#8217;t run it to ensure it works end-to-end.   </p>
<table style="width: 70%;" border="1">
<thead>
<tr>
<td style="text-align: center;" colspan="5">Apache 2.2.2</td>
</tr>
<tr>
<td style="text-align: center;" colspan="4">Passenger 2.0.6<br/>(gem)</td>
<td style="text-align: center;">Passenger 2.1.0<br/>(source)</td>
</tr>
<tr>
<td style="text-align: center;" colspan="2">Rails 2.2.2</td>
<td style="text-align: center;" colspan="2">Ramaze 2009.01</td>
<td style="text-align: center;" colspan="1">Ramaze 2009.01</td>
</tr>
<tr>
<td style="text-align: center;">MRI Ruby 1.8.7<br/>package</td>
<td style="text-align: center;">Ent. Ruby 1.8.6<br/>source</td>
<td style="text-align: center;">MRI Ruby 1.8.7<br/>package</td>
<td style="text-align: center;">Ent. Ruby 1.8.6<br/>source</td>
<td style="text-align: center;">MRI Ruby 1.9.1<br/>source</td>
</tr>
</thead>
</table>
<p>I utilized this simple call to Apache Bench to run through the four test scenarios:<br />
All data collected was based on 10,000 requests at 100 concurrent users after an initial &#8220;warmup&#8221; of the passenger threads with start of 100 requests at 10 concurrent users.  The following command shows the basic set of parameters issued to Apache Bench:</p>
<pre class="twilight">
ab -n 10000 -c 100 http://demo.u64rails01.local/posts
</pre>
<p><br/></p>
<h2>What was tested?</h2>
<p>In order to compare, as close as possible, apples to apples, I opted to use Active Record and ERubis in Ramaze to set up the same MVC classes in both the Rails and Ramaze project.  ActiveRecord is probably the heaviest weighted ORM that can be utilized with Ramaze.  I tried briefly to get Erubis working with Rails so that the two frameworks&#8217; projects would be more closely aligned than the out-of-box ERB rendering Rails ships with would have afforded.  I did attempt Erubis with Rails, however, I was either doing something very wrong or Erubis under Rails takes a sizable performance hit and I stuck with out-of-box ERB for these tests given its better performance.  As such, Rails uses out of box ERB rendering in these tests.</p>
<p>The <a href="http://github.com/mwlang/benchmarks/tree/0baffeb9cf3eb514912c6de34b64dc2ce25c2e31/2009/02">application itself</a> is ridiculously simple, offering only one model and performing only a read against the database, but hopefully, an effective start towards building this benchmark framework towards more substantive benchmark tests to come.  For now, lets take a look at how Rails and Ramaze stack up to each other and what affect the underlying interpreter can have on performance.  Standard packaged Main Ruby Interpreter (MRI) 1.8.7 consisted of simple package install provided by the Ubuntu Intrepid repositories whle <a href="http://www.rubyenterpriseedition.com/">Ruby Enterprise Edition</a> (REE) 1.8.6, which hails from the same folks bringing you Phusion Passenger, is compiled from source.</p>
<p>As a bonus, I also compiled and clocked metrics for Ramaze on 1.9.1.  This was a tricky environment to get set up and working.  And my initial results made me think I did something horribly wrong with compiling and configuring Ruby 1.9.1.  However, I fully replicated Antonio Cangiano&#8217;s benchmarks in my test environment (see <a href="http://antoniocangiano.com/2008/12/09/the-great-ruby-shootout-december-2008/">The Great Ruby Shootout (December 2008)</a>) and MRI 1.9.1. did indeed crush the other Ruby interpreters in Fibonacci number crunching (amongst others).  The theory tossed around in the Ramaze IRC channel was that 1.9.1. change in implementation of the String class (and it being unicode native now) slows things down a good bit with string processing.</p>
<h2>The Results</h2>
<p>The following table tabulates the results gathered from Apache Bench as well as passenger-memory-stat.  I ran a short run to warm things up (100 requests, 10 concurrently).  And then ran the big bench at 10,000 requests, 100 concurrently, and then ran again and recorded the results.  At around 5,000 requests, I ran passenger-memory-stat to collect the data during mid-processing and then again at the end.  These tests were run on a Ubuntu 64-bit Intrepid 8.10 virtual server that was allocated 1 CPU core and 512MB of RAM.  Swap space was never triggered (0k utilization), and CPU utilization was roughly 85% within the Virtual Machine during the test runs.  The host machine, which is four core CPU, showed one core busy at near 100% with the other three cores pretty much idle.</p>
<table border="0" cellspacing="0" frame="void" rules="none">
<tbody>
<tr>
<td width="138" height="17" align="left"><strong></strong></td>
<td width="86" align="right"><strong>mri_rails</strong></td>
<td width="86" align="right"><strong>ree_rails</strong></td>
<td width="86" align="right"><strong>mri_ramaze</strong></td>
<td width="86" align="right"><strong>ree_ramaze</strong></td>
<td width="86" align="right"><strong>191_ramaze</strong></td>
<td width="86" align="left"><strong>units</strong></td>
</tr>
<tr>
<td height="16" align="right"><strong>Time taken for tests</strong></td>
<td align="right">489.24</td>
<td align="right">379.76</td>
<td align="right">397.43</td>
<td align="right">287.5</td>
<td align="right">351.95</td>
<td align="left"><em>seconds</em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Complete requests</strong></td>
<td align="right">10000</td>
<td align="right">10000</td>
<td align="right">10000</td>
<td align="right">10000</td>
<td align="right">10000</td>
<td align="left"><em></em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Failed requests</strong></td>
<td align="right">0</td>
<td align="right">0</td>
<td align="right">0</td>
<td align="right">0</td>
<td align="right">0</td>
<td align="left"><em></em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Write errors</strong></td>
<td align="right">0</td>
<td align="right">0</td>
<td align="right">0</td>
<td align="right">0</td>
<td align="right">0</td>
<td align="left"><em></em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Total transferred</strong></td>
<td align="right">36670146</td>
<td align="right">36668229</td>
<td align="right">18130000</td>
<td align="right">18130000</td>
<td align="right">18460000</td>
<td align="left"><em>bytes</em></td>
</tr>
<tr>
<td height="16" align="right"><strong>HTML transferred</strong></td>
<td align="right">30500000</td>
<td align="right">30500000</td>
<td align="right">14480000</td>
<td align="right">14480000</td>
<td align="right">14680000</td>
<td align="left"><em>bytes</em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Requests per second</strong></td>
<td align="right">20.44</td>
<td align="right">26.33</td>
<td align="right">25.19</td>
<td align="right">34.78</td>
<td align="right">28.41</td>
<td align="left"><em>[#/sec] (mean)</em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Time per request</strong></td>
<td align="right">4892.42</td>
<td align="right">3797.56</td>
<td align="right">3970.43</td>
<td align="right">2875.03</td>
<td align="right">3519.49</td>
<td align="left"><em>[ms] (mean)</em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Time per request</strong></td>
<td align="right">48.92</td>
<td align="right">37.98</td>
<td align="right">39.7</td>
<td align="right">28.75</td>
<td align="right">35.2</td>
<td align="left"><em>[ms] (mean, across all concurrent requests)</em></td>
</tr>
<tr>
<td height="17" align="right"><strong>Transfer rate</strong></td>
<td align="right">73.19</td>
<td align="right">94.29</td>
<td align="right">44.59</td>
<td align="right">61.58</td>
<td align="right">51.22</td>
<td align="left"><em>[Kbytes/sec] received</em></td>
</tr>
<tr>
<td height="16" align="right"><strong>Total private dirty RSS</strong></td>
<td align="right">323.73</td>
<td align="right">180.89</td>
<td align="right">221.11</td>
<td align="right">221.51</td>
<td align="right">210.73</td>
<td align="left"><em>MB</em></td>
</tr>
</tbody>
</table>
<h2>Throughput</h2>
<p>Everybody likes to <a href="http://www.therailsway.com/2009/1/6/requests-per-second">talk about throughput</a>, so lets start there.  As you can see, MRI and Rails was the worst performer while REE and Ramaze clocked in with the highest throughput in terms of requests per second.  Be forewarned that throughput doesn&#8217;t necessarily equate to user response times.  This metric simply tells you the load at which your system is capable of delivering content at.</p>
<p><img src='http://github.com/mwlang/benchmarks/raw/0baffeb9cf3eb514912c6de34b64dc2ce25c2e31/2009/02/throughput.png' alt='throughput' class='alignnone' /></p>
<h2>Time per Request</h2>
<p>Time per request helps you see about how long an average user request takes for a given load.  As you can see here, with times in the milliseconds, we&#8217;re talking about numbers that will easily be swallowed in the noise of network latency.  Even so, its not hard to be impressed by what the REE folks managed to pull out of their hat with regards to performance on the main ruby interpreter.</p>
<p><img src='http://github.com/mwlang/benchmarks/raw/0baffeb9cf3eb514912c6de34b64dc2ce25c2e31/2009/02/time_per_request.png' alt='Time per Request' class='alignnone' /></p>
<h2>Memory Consumption</h2>
<p>This final graph shows the sizeable dent REE makes in memory consumption for running a Rails application.  Ramaze is already pretty efficient and lean and REE made practically no dent in memory consumption here.  However, REE&#8217;s use of the faster memory allocation routines does have a good effect on boosting Ramaze&#8217;s performance (as seen in above graphs), so there&#8217;s still lots to be gained by running Ramaze with REE.</p>
<p><img src='http://github.com/mwlang/benchmarks/raw/0baffeb9cf3eb514912c6de34b64dc2ce25c2e31/2009/02/memory_usage.png' alt='Memory Usage' class='alignnone' /></p>
<h2>Conclusion</h2>
<p>For me, I have two very, very viable solutions before me.  Rails on Enterprise Ruby or Ramaze on Ruby 1.8.7.  The final choice comes down to how much I can bet on my own Ruby prowess.   Ramaze is a very lean framework that gets you going, but doesn&#8217;t get you a nine inch pillowed mattress topping for your bed like Rails does.  Because Ramaze is so lean, I realize I will have to really take my Ruby skills to the next level and truly understand the ruby code that other developers produce.  Unlike Rails, where there&#8217;s gobs and gobs of plugins and blogs on the topic that make pretty much any need simple to satisfy and get working, I have to know my Ruby to get a solution implemented on Ramaze.  Not a bad thing, but certainly a more challenging and potentially rewarding path to take.</p>
<p>Aside from my personal concerns about making the jump, looking at these results, it is good to see that I have options and how easy it is to get a good deployment up and working compared to 3 or 4 years ago when I was banging my head against the wall for days on end to keep lighttpd + fcgi processes up and running around the clock.  In these tests, it was very, very satisfying that not one single crash or dropped request was recorded in all the benchmarking I performed.  Mongrel came along and made a big impact, but you still needed something like monit to watch Mongrel and restart it on ocvasion.  Now Passenger has come along and made yet another big impact in the ease of deploying Rails, Ramaze, or any of the other ruby-based frameworks.  We&#8217;ve come a long ways, indeed.  I, for one, certainly look forward to what the Ruby sphere will bring us over the next couple of years.</p>
]]></content:encoded>
			<wfw:commentRss>http://ramblings.gibberishcode.net/archives/rails-vs-ramaze-performance-comparison/31/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Ultraviolet gives new life to Syntax highlighting</title>
		<link>http://ramblings.gibberishcode.net/archives/ultraviolet-gives-new-life-to-syntax-highlighting/27</link>
		<comments>http://ramblings.gibberishcode.net/archives/ultraviolet-gives-new-life-to-syntax-highlighting/27#comments</comments>
		<pubDate>Thu, 05 Feb 2009 08:30:44 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[mama]]></category>
		<category><![CDATA[oniguruma]]></category>
		<category><![CDATA[textmate]]></category>
		<category><![CDATA[textpow]]></category>
		<category><![CDATA[ultraviolet]]></category>

		<guid isPermaLink="false">http://ramblings.gibberishcode.net/?p=27</guid>
		<description><![CDATA[I am tired of Google&#8217;s Syntax highlighter.  If I accidentally switch to Visual mode in the editor and do some edits and switch back to HTML mode, then I lose the class=&#8221;code&#8221; moniker and I have to go through the entire post and fix.
Another drawback I have with Google Syntax highlighter is that the page [...]]]></description>
			<content:encoded><![CDATA[<p>I am tired of Google&#8217;s Syntax highlighter.  If I accidentally switch to Visual mode in the editor and do some edits and switch back to HTML mode, then I lose the class=&#8221;code&#8221; moniker and I have to go through the entire post and fix.</p>
<p>Another drawback I have with Google Syntax highlighter is that the page renders without highlighting and then all the code listings change to syntax highlighted text a few moments later.</p>
<p>Introducing <a href="http://ultraviolet.rubyforge.org/index.xhtml" target="_blank">Ultraviolet</a>, a syntax highlighter supporting over 50 syntaxes and any <a href="http://macromates.com/" target="_blank">TextMate</a> theme.  Ultraviolet is based on <a href="http://www.geocities.jp/kosako3/oniguruma/" target="_blank">Oniguruma</a>, a regular expression library that comes standard with Ruby 1.9.  Ultraviolet requires a little more effort for me to cut and paste, but I am definitely much happier with the end results and Wordpress no longer mungs my posts.  Only real complaint I have is that I can&#8217;t read the posted code inline in HTML format (but I can read it in Visual mode!).</p>
<h2>Ruby Script</h2>
<pre class="twilight"><span class="line-numbers">   1 </span> <span class="Keyword">require</span> <span class="String"><span class="String">'</span>rubygems<span class="String">'</span></span>
<span class="line-numbers">   2 </span> <span class="Keyword">require</span> <span class="String"><span class="String">'</span>ramaze<span class="String">'</span></span>
<span class="line-numbers">   3 </span> <span class="Keyword">require</span> <span class="String"><span class="String">'</span>maruku<span class="String">'</span></span>
<span class="line-numbers">   4 </span> <span class="Keyword">require</span> <span class="String"><span class="String">'</span>sequel<span class="String">'</span></span>
<span class="line-numbers">   5 </span>
<span class="line-numbers">   6 </span> <span class="Variable"><span class="Variable">$</span>LOAD_PATH</span>.<span class="Entity">unshift</span>(__DIR__)
<span class="line-numbers">   7 </span>
<span class="line-numbers">   8 </span> <span class="Keyword">require</span> <span class="String"><span class="String">'</span>env<span class="String">'</span></span>
<span class="line-numbers">   9 </span>
<span class="line-numbers">  10 </span> <span class="Keyword">require</span> <span class="String"><span class="String">'</span>vendor/flickr<span class="String">'</span></span>
<span class="line-numbers">  11 </span> <span class="Keyword">require</span> <span class="String"><span class="String">'</span>vendor/haml_maruku_filter<span class="String">'</span></span>
<span class="line-numbers">  12 </span> <span class="Keyword">require</span> <span class="String"><span class="String">'</span>vendor/image_science_cropped_resize<span class="String">'</span></span>
<span class="line-numbers">  13 </span>
<span class="line-numbers">  14 </span> <span class="Keyword">require</span> <span class="String"><span class="String">'</span>model/init<span class="String">'</span></span>
<span class="line-numbers">  15 </span> <span class="Keyword">require</span> <span class="String"><span class="String">'</span>controller/init<span class="String">'</span></span>
<span class="line-numbers">  16 </span>
<span class="line-numbers">  17 </span> <span class="Keyword">require</span> <span class="String"><span class="String">'</span>db/init<span class="String">'</span></span> <span class="Keyword">if</span> <span class="Variable">SOCIAR</span>.<span class="Entity">mode</span> <span class="Keyword">==</span> <span class="Constant"><span class="Constant">:</span>dev</span>
<span class="line-numbers">  18 </span>
<span class="line-numbers">  19 </span> r <span class="Keyword">=</span> <span class="Variable">SOCIAR</span>.<span class="Entity">ramaze</span>
<span class="line-numbers">  20 </span>
<span class="line-numbers">  21 </span> <span class="Comment"><span class="Comment">=begin</span></span>
<span class="line-numbers">  22 </span> <span class="Comment">if r.gzip</span>
<span class="line-numbers">  23 </span> <span class="Comment">  require 'ramaze/contrib/gzip_filter'</span>
<span class="line-numbers">  24 </span> <span class="Comment">  gzip = Ramaze::Filter::Gzip</span>
<span class="line-numbers">  25 </span> <span class="Comment">  gzip.trait :threshold =&gt; 1</span>
<span class="line-numbers">  26 </span> <span class="Comment">  Ramaze::Dispatcher::Action::FILTER &lt;&lt; gzip</span>
<span class="line-numbers">  27 </span> <span class="Comment"><span class="Comment">=end</span></span>
<span class="line-numbers">  28 </span>
<span class="line-numbers">  29 </span> <span class="Support">Ramaze</span>.<span class="Entity">start</span> <span class="Constant"><span class="Constant">:</span>adapter</span> =&gt; r.<span class="Entity">adapter</span>,
<span class="line-numbers">  30 </span>              <span class="Constant"><span class="Constant">:</span>host</span> =&gt; r.<span class="Entity">host</span>,
<span class="line-numbers">  31 </span>              <span class="Constant"><span class="Constant">:</span>port</span> =&gt; r.<span class="Entity">port</span>,
<span class="line-numbers">  32 </span>              <span class="Constant"><span class="Constant">:</span>boring</span> =&gt; r.<span class="Entity">boring</span></pre>
<h2>Shell Script</h2>
<pre class="twilight"><span class="line-numbers">   1 </span> <span class="Comment"><span class="Comment">#</span>!/bin/sh</span>
<span class="line-numbers">   2 </span>
<span class="line-numbers">   3 </span> <span class="Comment"><span class="Comment">#</span>## BEGIN INIT INFO</span>
<span class="line-numbers">   4 </span> <span class="Comment"><span class="Comment">#</span> Provides:          lm-sensors</span>
<span class="line-numbers">   5 </span> <span class="Comment"><span class="Comment">#</span> Required-Start:    $local_fs</span>
<span class="line-numbers">   6 </span> <span class="Comment"><span class="Comment">#</span> Required-Stop:</span>
<span class="line-numbers">   7 </span> <span class="Comment"><span class="Comment">#</span> Default-Start:     S</span>
<span class="line-numbers">   8 </span> <span class="Comment"><span class="Comment">#</span> Default-Stop:</span>
<span class="line-numbers">   9 </span> <span class="Comment"><span class="Comment">#</span> Short-Description: lm-sensors</span>
<span class="line-numbers">  10 </span> <span class="Comment"><span class="Comment">#</span> Description:       hardware health monitoring</span>
<span class="line-numbers">  11 </span> <span class="Comment"><span class="Comment">#</span>## END INIT INFO</span>
<span class="line-numbers">  12 </span>
<span class="line-numbers">  13 </span> . /lib/lsb/init-functions
<span class="line-numbers">  14 </span>
<span class="line-numbers">  15 </span> [ -f /etc/default/rcS ] <span class="Keyword">&amp;&amp;</span> . /etc/default/rcS
<span class="line-numbers">  16 </span> PATH=/bin:/usr/bin:/sbin:/usr/sbin
<span class="line-numbers">  17 </span> PROGRAM=/usr/bin/sensors
<span class="line-numbers">  18 </span>
<span class="line-numbers">  19 </span> test -x <span class="Variable"><span class="Variable">$</span>PROGRAM</span> <span class="Keyword">||</span> exit 0
<span class="line-numbers">  20 </span>
<span class="line-numbers">  21 </span> <span class="Keyword">case</span> <span class="String"><span class="String">&quot;</span><span class="Variable"><span class="Variable">$</span>1</span><span class="String">&quot;</span></span> <span class="Keyword">in</span>
<span class="line-numbers">  22 </span>   start)
<span class="line-numbers">  23 </span> 	log_begin_msg <span class="String"><span class="String">&quot;</span>Setting sensors limits<span class="String">&quot;</span></span>
<span class="line-numbers">  24 </span> 	<span class="Keyword">if</span> [ <span class="String"><span class="String">&quot;</span><span class="Variable"><span class="Variable">$</span>VERBOSE</span><span class="String">&quot;</span></span> = <span class="String"><span class="String">&quot;</span>no<span class="String">&quot;</span></span> ]<span class="Keyword">;</span> <span class="Keyword">then</span>
<span class="line-numbers">  25 </span> 		/usr/bin/sensors -s <span class="Keyword">1&gt;</span> /dev/null <span class="Keyword">2&gt;</span> /dev/null
<span class="line-numbers">  26 </span> 		/usr/bin/sensors <span class="Keyword">1&gt;</span> /dev/null <span class="Keyword">2&gt;</span> /dev/null
<span class="line-numbers">  27 </span> 	<span class="Keyword">else</span>
<span class="line-numbers">  28 </span> 		/usr/bin/sensors -s
<span class="line-numbers">  29 </span> 		/usr/bin/sensors <span class="Keyword">&gt;</span> /dev/null
<span class="line-numbers">  30 </span> 	<span class="Keyword">fi</span>
<span class="line-numbers">  31 </span> 	log_end_msg <span class="Variable"><span class="Variable">$</span>?</span>
<span class="line-numbers">  32 </span> 	<span class="Keyword">;</span><span class="Keyword">;</span>
<span class="line-numbers">  33 </span>   stop)
<span class="line-numbers">  34 </span> 	<span class="Keyword">;</span><span class="Keyword">;</span>
<span class="line-numbers">  35 </span>   force-reload<span class="Keyword">|</span>restart)
<span class="line-numbers">  36 </span> 	<span class="Variable"><span class="Variable">$</span>0</span> start
<span class="line-numbers">  37 </span> 	<span class="Keyword">;</span><span class="Keyword">;</span>
<span class="line-numbers">  38 </span>   *)
<span class="line-numbers">  39 </span> 	log_success_msg <span class="String"><span class="String">&quot;</span>Usage: /etc/init.d/sensors {start|stop|restart|force-reload}<span class="String">&quot;</span></span>
<span class="line-numbers">  40 </span> 	exit 1
<span class="line-numbers">  41 </span> <span class="Keyword">esac</span>
<span class="line-numbers">  42 </span>
<span class="line-numbers">  43 </span> exit 0
</pre>
<h2>Apache Config</h2>
<pre class="twilight"><span class="line-numbers">   1 </span> <span class="MarkupTag"><span class="MarkupTag">&lt;</span><span class="MarkupNameOfTag">VirtualHost</span> <span class="MarkupTag">*:80</span><span class="MarkupTag">&gt;</span></span>
<span class="line-numbers">   2 </span> 	<span class="LibraryConstant">ServerName</span> www.stinger.local
<span class="line-numbers">   3 </span> 	<span class="LibraryConstant">ServerAdmin</span> webmaster@localhost
<span class="line-numbers">   4 </span>
<span class="line-numbers">   5 </span> 	<span class="LibraryConstant">DocumentRoot</span> /var/www/
<span class="line-numbers">   6 </span> 	<span class="MarkupTag"><span class="MarkupTag">&lt;</span><span class="MarkupNameOfTag">Directory</span> <span class="MarkupTag">/&gt;</span></span>
<span class="line-numbers">   7 </span> 		<span class="LibraryConstant">Options</span> FollowSymLinks
<span class="line-numbers">   8 </span> 		<span class="LibraryConstant">AllowOverride</span> None
<span class="line-numbers">   9 </span> 	<span class="MarkupTag"><span class="MarkupTag">&lt;/</span><span class="MarkupNameOfTag">Directory</span><span class="MarkupTag">&gt;</span></span>
<span class="line-numbers">  10 </span> 	<span class="MarkupTag"><span class="MarkupTag">&lt;</span><span class="MarkupNameOfTag">Directory</span> /var/www<span class="MarkupTag">/&gt;</span></span>
<span class="line-numbers">  11 </span> 		<span class="LibraryConstant">Options</span> Indexes FollowSymLinks MultiViews
<span class="line-numbers">  12 </span> 		<span class="LibraryConstant">AllowOverride</span> None
<span class="line-numbers">  13 </span> 		<span class="LibraryConstant">Order</span> allow,deny
<span class="line-numbers">  14 </span> 		allow from all
<span class="line-numbers">  15 </span> 	<span class="MarkupTag"><span class="MarkupTag">&lt;/</span><span class="MarkupNameOfTag">Directory</span><span class="MarkupTag">&gt;</span></span>
<span class="line-numbers">  16 </span>
<span class="line-numbers">  17 </span> 	<span class="LibraryConstant">ScriptAlias</span> /cgi-bin/ /usr/lib/cgi-bin/
<span class="line-numbers">  18 </span> 	<span class="MarkupTag"><span class="MarkupTag">&lt;</span><span class="MarkupNameOfTag">Directory</span> &quot;/usr/lib/cgi-bin&quot;<span class="MarkupTag">&gt;</span></span>
<span class="line-numbers">  19 </span> 		<span class="LibraryConstant">AllowOverride</span> None
<span class="line-numbers">  20 </span> 		<span class="LibraryConstant">Options</span> +ExecCGI -MultiViews +SymLinksIfOwnerMatch
<span class="line-numbers">  21 </span> 		<span class="LibraryConstant">Order</span> allow,deny
<span class="line-numbers">  22 </span> 		<span class="LibraryConstant">Allow</span> from all
<span class="line-numbers">  23 </span> 	<span class="MarkupTag"><span class="MarkupTag">&lt;/</span><span class="MarkupNameOfTag">Directory</span><span class="MarkupTag">&gt;</span></span>
<span class="line-numbers">  24 </span>
<span class="line-numbers">  25 </span> 	<span class="LibraryConstant">ErrorLog</span> /var/log/apache2/error.log
<span class="line-numbers">  26 </span>
<span class="line-numbers">  27 </span> 	<span class="Comment"><span class="Comment">#</span> Possible values include: debug, info, notice, warn, error, crit,</span>
<span class="line-numbers">  28 </span> 	<span class="Comment"><span class="Comment">#</span> alert, emerg.</span>
<span class="line-numbers">  29 </span> 	<span class="LibraryConstant">LogLevel</span> warn
<span class="line-numbers">  30 </span>
<span class="line-numbers">  31 </span> 	<span class="LibraryConstant">CustomLog</span> /var/log/apache2/access.log combined
<span class="line-numbers">  32 </span>
<span class="line-numbers">  33 </span>     <span class="LibraryConstant">Alias</span> /doc/ <span class="String"><span class="String">&quot;</span>/usr/share/doc/<span class="String">&quot;</span></span>
<span class="line-numbers">  34 </span>     <span class="MarkupTag"><span class="MarkupTag">&lt;</span><span class="MarkupNameOfTag">Directory</span> <span class="MarkupTag">&quot;/usr/share/doc/&quot;</span><span class="MarkupTag">&gt;</span></span>
<span class="line-numbers">  35 </span>         <span class="LibraryConstant">Options</span> Indexes MultiViews FollowSymLinks
<span class="line-numbers">  36 </span>         <span class="LibraryConstant">AllowOverride</span> None
<span class="line-numbers">  37 </span>         <span class="LibraryConstant">Order</span> deny,allow
<span class="line-numbers">  38 </span>         <span class="LibraryConstant">Deny</span> from all
<span class="line-numbers">  39 </span>         <span class="LibraryConstant">Allow</span> from 127.0.0.0/255.0.0.0 ::1/128
<span class="line-numbers">  40 </span>     <span class="MarkupTag"><span class="MarkupTag">&lt;/</span><span class="MarkupNameOfTag">Directory</span><span class="MarkupTag">&gt;</span></span>
<span class="line-numbers">  41 </span>
<span class="line-numbers">  42 </span> <span class="MarkupTag"><span class="MarkupTag">&lt;/</span><span class="MarkupNameOfTag">VirtualHost</span><span class="MarkupTag">&gt;</span></span>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://ramblings.gibberishcode.net/archives/ultraviolet-gives-new-life-to-syntax-highlighting/27/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ramaze and ActiveRecord</title>
		<link>http://ramblings.gibberishcode.net/archives/ramaze-and-activerecord/26</link>
		<comments>http://ramblings.gibberishcode.net/archives/ramaze-and-activerecord/26#comments</comments>
		<pubDate>Wed, 04 Feb 2009 07:49:01 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby Language]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[benchmarks]]></category>
		<category><![CDATA[erubis]]></category>
		<category><![CDATA[monkey patch]]></category>
		<category><![CDATA[ramaze]]></category>

		<guid isPermaLink="false">http://ramblings.gibberishcode.net/?p=26</guid>
		<description><![CDATA[Thanks to the great folks on IRC over at Freenode#ramaze, I was able to not only get Ramaze working with Erubis and Activerecord for a pseudo apples to apples comparison of Rails vs. Ramaze performance benching, but I was also able to get Apache 2.2.9 talking to Passenger to Ramaze.  This quick post will [...]]]></description>
			<content:encoded><![CDATA[<p>Thanks to the great folks on IRC over at Freenode#ramaze, I was able to not only get Ramaze working with Erubis and Activerecord for a pseudo apples to apples comparison of Rails vs. Ramaze performance benching, but I was also able to get Apache 2.2.9 talking to Passenger to Ramaze.  This quick post will take you through the basics.</p>
<h2>Environment</h2>
<p>This post will guide you through setting up the following environment on Ubuntu Intrepid (8.10):</p>
<ul>
<li><a href="http://httpd.apache.org/docs/2.2/">Apache 2.2.9</a></li>
<li><a href="http://www.modrails.com/">Passenger 2.0.6</a></li>
<li><a href="http://api.rubyonrails.org/classes/ActiveRecord/Base.html">ActiveRecord 2.2.2</a></li>
<li><a href="http://ramaze.net/">Ramaze 2009.01</a></li>
<li><a href="http://www.kuwata-lab.com/erubis/">Erubis 2.6.2</a></li>
<li><a href="http://www.mysql.com/">MySql 5.0.67 (assumed installed)</a></li>
</ul>
<p>To get started:</p>
<pre  name="code" class="ruby:nocontrols">
sudo apt-get install apache2 passenger
sudo passenger-install-apache2-module
</pre>
<p>Install the Rack, Ramaze, Activerecord, and Erubis gems</p>
<pre  name="code" class="ruby:nocontrols">
sudo gem install rack, ramaze, activerecord, erubis
</pre>
<h2>Establishing Project</h2>
<p>Now create your first ramaze project with:</p>
<pre  name="code" class="ruby:nocontrols">
ramaze --create demo
</pre>
<p>Then change to the demo directory.  If you see a start.ru file, rename it to config.ru or Passenger won&#8217;t find it.  Create a file called passenger.rb with the following:</p>
<pre  name="code" class="ruby:nocontrols">
require 'rubygems'
require 'ramaze'

# Add directory start.rb is in to the load path, so you can run the app from
# any other working path
$LOAD_PATH.unshift(__DIR__)

# Initialize controllers and models
require 'controller/init'
require 'model/init'

Ramaze::Global.sourcereload = false
Ramaze::Global.sessions = true
Ramaze::Log.ignored_tags = [:debug, :info]
</pre>
<p>Important:  Do not include &#8220;Ramaze.start &#8230;&#8221; in this file or this will surely mess things up for Passenger.</p>
<p>Now edit the config.ru file (formerly start.ru):</p>
<pre  name="code" class="ruby:nocontrols">
/usr/bin/env rackup
# start.ru for ramaze apps
# use thin>=0.6.3
# thin start -r start.ru
#
# rackup is a useful tool for running Rack applications, which uses the
# Rack::Builder DSL to configure middleware and build up applications easily.
#
# rackup automatically figures out the environment it is run in, and runs your
# application as FastCGI, CGI, or standalone with Mongrel or WEBrick�..all from
# the same configuration.

require 'app'
Ramaze.trait[:essentials].delete Ramaze::Adapter
Ramaze.start
run Ramaze::Adapter::Base
</pre>
<p>Add the following virtual host file to /etc/apache2/sites-enabled/001-ramaze-demo</p>
<pre  name="code" class="ruby:nocontrols">
&lt;VirtualHost *:80&gt;
    ServerName ramaze.demo.local
    RackBaseURI /
    RailsAutoDetect off
    RackAutoDetect on
    DocumentRoot /var/www/ramaze/demo/public
&lt;/VirtualHost&gt;
</pre>
<p>And edit your /etc/hosts file to include &#8220;ramaze.demo.local&#8221; so it resolves to localhost.</p>
<h2>Database</h2>
<p>Next, create a database called ramaze_demo (or your choice) and add a posts table and<br />
some data via SQL or migrate scripts (this being a minimal demonstration and all that).</p>
<pre  name="code" class="sql:nocontrols">
create table posts (
    id        int(11) not null auto_increment
  , title     varchar(255) not null
  , body      varchar(1024) not null
  , primary key (id)
);

insert posts values (1, "First Post", "Thank hrnt for getting passenger talking to ramaze.");
insert posts values (2, "Another Post", "Ask Pistos what SelfMarks is, because he is bored with diigo");
insert posts values (3, "IRC, you say?", "Visit #ramaze on Freenode");
</pre>
<p><H2>Model</h2>
<p>Edit the model.init.rb file with the following:</p>
<pre  name="code" class="ruby:nocontrols">
require 'activerecord'
require 'cleanup_connection_patch'

  ActiveRecord::Base.establish_connection(
    :adapter  => "mysql",
    :database => "ramaze_demo",
    :host     => "localhost",
    :username => "root",
    :password => "secret"
  )

class Post < ActiveRecord::Base
end
</pre>
<p>Important:  cleanup_connection_patch comes from <a href="http://github.com/coderrr/cleanup_connection/tree/master">github.com</a> and makes the ActiveRecord behave correctly in a threaded environment.  Please see <a href="http://coderrr.wordpress.com/2009/01/16/monkey-patching-activerecord-to-automatically-release-connections/">Monkey patching ActiveRecord to automatically release connections &laquo; coderrr</a> for more information.</p>
<h2>Controller</h2>
<p>With the model squared away, time to turn our attention to the controller.  Edit controller/init.rb:</p>
<pre  name="code" class="ruby:nocontrols">
class Controller < Ramaze::Controller
  layout '/page'
  helper <img src='http://ramblings.gibberishcode.net/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> html
  engine :Erubis
end

class PostsController < Controller
  def index
    @posts = Post.find(:all)
  end
end
</pre>
<h2>View</h2>
<p>Create a folder under view for posts and add the following Erubis template view/posts.rhtml:</p>
<pre  name="code" class="html:nocontrols">
&lt;h1&gt;Listing Posts&lt;/h1&gt;

&lt;ul&gt;
  &lt;% for post in @posts %&gt;
      &lt;li&gt;&lt;%= A(post.title, :href =&gt; "/post/#{post.id}", :title =&gt; post.body) %&gt;&lt;/li&gt;
  &lt;% end %&gt;
&lt;/ul&gt;
</pre>
<p>Note: that while Rails uses filename.html.erb, the Erubis engine expects *.rhtml extension in Ramaze.</p>
<h2>Running</h2>
<p>Test out the above with webrick, mongrel, or thin with:</p>
<pre  name="code" class="ruby:nocontrols">
ruby start.rb
</pre>
<p>If all goes well, you should see the three postings above listed.</p>
<p>Launch Apache2, if you haven't already and point your localhost's browser at http://ramaze.demo.local/posts</p>
<p>You should now have a listing of posts rendered through Apache via Passenger.</p>
<h2>Conclusion</h2>
<p>I am finding much to like about Ramaze, especially after developing with Rails for a few years now and watching it grow at an alarming rate in complexity.  Ramaze is a refreshing return to basics.  I am finding that Ramaze just may be able to give me most of what I need while giving me a sizeable performance boost in the process.  Here's a rails bench on the equivalent of the above:</p>
<pre style="overflow: hidden">
Concurrency Level:      50
Time taken for tests:   4.277 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      10218492 bytes
HTML transferred:       9595000 bytes
Requests per second:    233.83 [#/sec] (mean)
Time per request:       213.828 [ms] (mean)
Time per request:       4.277 [ms] (mean, across all concurrent requests)
Transfer rate:          2333.42 [Kbytes/sec] received
</pre>
<p>And this is Ramaze:</p>
<pre style="overflow: hidden">
Concurrency Level:      50
Time taken for tests:   2.248 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      9815000 bytes
HTML transferred:       9555000 bytes
Requests per second:    444.91 [#/sec] (mean)
Time per request:       112.383 [ms] (mean)
Time per request:       2.248 [ms] (mean, across all concurrent requests)
Transfer rate:          4264.42 [Kbytes/sec] received
</pre>
]]></content:encoded>
			<wfw:commentRss>http://ramblings.gibberishcode.net/archives/ramaze-and-activerecord/26/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Changing ANSI colors in Terminal on Macs</title>
		<link>http://ramblings.gibberishcode.net/archives/changing-ansi-colors-in-terminal-on-macs/16</link>
		<comments>http://ramblings.gibberishcode.net/archives/changing-ansi-colors-in-terminal-on-macs/16#comments</comments>
		<pubDate>Tue, 09 Sep 2008 15:56:34 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Servers]]></category>
		<category><![CDATA[Systems]]></category>
		<category><![CDATA[ansi colors]]></category>
		<category><![CDATA[Macs]]></category>
		<category><![CDATA[terminal colors]]></category>
		<category><![CDATA[vi syntax highlight]]></category>

		<guid isPermaLink="false">http://ramblings.gibberishcode.net/?p=16</guid>
		<description><![CDATA[Probably the most frustrating experience I have had with Macs so far is figuring out how to change the ANSI colors in Terminal (Terminal.app) so that I can read the outputs of man and most especially ls and comments in vi when colorization is activated and I have chosen a dark background theme.
I am using [...]]]></description>
			<content:encoded><![CDATA[<p>Probably the most frustrating experience I have had with Macs so far is figuring out how to change the ANSI colors in Terminal (Terminal.app) so that I can read the outputs of <b>man</b> and most especially <b>ls</b> and comments in <b>vi</b> when colorization is activated and I have chosen a dark background theme.</p>
<p>I am using Mac OS X Leopard 10.5.4 at the time of this writing.  These are the steps I took to fix that most hideous of all colors, dark blue on black background:</p>
<ol>
<li>Set your terminal theme colors to your liking</li>
<li>Set up <b>ls</b> to colorize directory listings by default.  There are two ways to do this:  Either set the CLICOLOR Environment variable or add an alias for ls to include the -G flag.  I chose the CLICOLOR flag:
<pre name="code" class="ruby:nocontrols">
export CLICOLOR=1
</pre>
</li>
<li>Next up, install the ANSI color SIMBL plugin found here: <a href="http://niw.at/articles/2007/11/02/TerminalColoreopard/en">http://niw.at: works of Yoshimasa Niwa</a>.  Make sure Terminal.app is closed while you install the plugin then relaunch Terminal to find under its main menu, &#8220;Color Preferences&#8230;&#8221;</li>
<li>Finally, edit that dark blue away!</li>
</ol>
<p>If you&#8217;re interested in tailoring the output of the colors even further, you can also export the LSCOLORS variable:</p>
<pre name="code" class="ruby:nocontrols">
export LSCOLORS="exfxcxdxbxegedabagacad"
</pre>
<p>And then change according to the manual entry for ls (&#8220;man ls&#8221;):</p>
<table>
<tr>
<th>a</th>
<td>black</td>
</tr>
<tr>
<th>b</th>
<td>red</td>
</tr>
<tr>
<th>c</th>
<td>green</td>
</tr>
<tr>
<th>d</th>
<td>brown</td>
</tr>
<tr>
<th>e</th>
<td>blue</td>
</tr>
<tr>
<th>f</th>
<td>magenta</td>
</tr>
<tr>
<th>g</th>
<td>cyan</td>
</tr>
<tr>
<th>h</th>
<td>light grey</td>
</tr>
<tr>
<th>A</th>
<td>bold black, usually shows up as dark grey</td>
</tr>
<tr>
<th>B</th>
<td>bold red</td>
</tr>
<tr>
<th>C</th>
<td>bold green</td>
</tr>
<tr>
<th>D</th>
<td>bold brown, usually shows up as yellow</td>
</tr>
<tr>
<th>E</th>
<td>bold blue</td>
</tr>
<tr>
<th>F</th>
<td>bold magenta</td>
</tr>
<tr>
<th>G</th>
<td>bold cyan</td>
</tr>
<tr>
<th>H</th>
<td>bold light grey; looks like bright white</td>
</tr>
<tr>
<th>x</th>
<td>default foreground or background</td>
</tr>
</table>
<p>One final trick to get my bash shell exactly like I like it was to set the prompt.  This can likewise be done by editing ~/.profile:</p>
<pre name="code" class="ruby:nocontrols">
PS1="[\u@\h \W] "
</pre>
]]></content:encoded>
			<wfw:commentRss>http://ramblings.gibberishcode.net/archives/changing-ansi-colors-in-terminal-on-macs/16/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Configuring ntpd to hand out time to local servers</title>
		<link>http://ramblings.gibberishcode.net/archives/configuring-ntpd-to-hand-out-time-to-local-servers/14</link>
		<comments>http://ramblings.gibberishcode.net/archives/configuring-ntpd-to-hand-out-time-to-local-servers/14#comments</comments>
		<pubDate>Mon, 11 Aug 2008 16:31:51 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Servers]]></category>
		<category><![CDATA[Systems]]></category>
		<category><![CDATA[ntp client]]></category>
		<category><![CDATA[ntp server]]></category>
		<category><![CDATA[yum]]></category>

		<guid isPermaLink="false">http://ramblings.gibberishcode.net/?p=14</guid>
		<description><![CDATA[Syncing your servers to public time servers is one of the most common ways of keeping server times in sync.  Apparently the less common approach of configuring one server to sync with public servers and it in turn becomes the authoritative time keeper for the rest of your servers is less well-known.  Digging [...]]]></description>
			<content:encoded><![CDATA[<p>Syncing your servers to public time servers is one of the most common ways of keeping server times in sync.  Apparently the less common approach of configuring one server to sync with public servers and it in turn becomes the authoritative time keeper for the rest of your servers is less well-known.  Digging through the copious ntp documentation, I have to say, its some very, very dense documentation mainly because the jargon isn&#8217;t well translated to a layperson&#8217;s &#8220;How do I?&#8221; inquiry.</p>
<p>I combed the documentation for days trying to figure out exactly how to set up a server to hand out time to all my other servers.  Normally, my Google-fu can pierce just about any need, but &#8220;time&#8221; &#8220;server&#8221; &#8220;local&#8221; and so on are all too common terms in both client-and-server and client-only configurations and by far and away, the bulk of the documentation guides you through the latter.  The documentation that guides you through the former is dense with references to peers, stratum, broadcasting, multi-casting, and so on.</p>
<p>So, here&#8217;s how to set up an NTP service as both client and local time server on CentOS 4:</p>
<pre  name="code" class="ruby:nocontrols">
yum install ntp
</pre>
<p>Then edit the /etc/ntp.conf file and set up the public ntp server pools and uncomment the broadcast line and change IP mask to match your network&#8217;s:</p>
<pre  name="code" class="ruby:nocontrols">
server 0.rhel.pool.ntp.org
server 1.rhel.pool.ntp.org
server 2.rhel.pool.ntp.org
broadcast 192.168.1.255
</pre>
<p>Modify your /etc/sysconfig/iptables to allow other servers to connect:</p>
<pre  name="code" class="ruby:nocontrols">
-A RH-Firewall-1-INPUT -p udp -m udp --dport 123 -j ACCEPT
</pre>
<p>Finally, go to the &#8220;client server&#8221; and install ntp on it just as you did with the ntp server, except, this time, you edit your /etc/ntp.conf file to point to your new local time server.  In my case, I set up two servers to give out times and I added ntp.1 and ntp.2 to my local DNS servers, so my config file for the &#8220;client servers&#8221; uses:</p>
<pre  name="code" class="ruby:nocontrols">
server ntp.1.example.com
server ntp.2.example.com
</pre>
<p>Its really that simple!  Its probably not <strong>the most secure</strong> way to do the job as there&#8217;s plenty of information overload in the ntp documentation on configuring securely.  However, with all of my servers sitting in a trusted VLAN and the DNS entries are only served to these servers and NTP port is blocked between this VLAN and others, I reckon it would be fairly hard to hijack the local ntp services.  In other words, the simple approach is good enough, for now.</p>
]]></content:encoded>
			<wfw:commentRss>http://ramblings.gibberishcode.net/archives/configuring-ntpd-to-hand-out-time-to-local-servers/14/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pradipta&#8217;s Rolodex</title>
		<link>http://ramblings.gibberishcode.net/archives/pradiptas-rolodex/12</link>
		<comments>http://ramblings.gibberishcode.net/archives/pradiptas-rolodex/12#comments</comments>
		<pubDate>Fri, 18 Jul 2008 14:05:20 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://ramblings.gibberishcode.net/?p=12</guid>
		<description><![CDATA[Something funny happened last night.  A one, Max Archie from Indiana hired an India-based Call Center to find a couple of Ruby developers.  Well, by and by, the recruiter mass-mails some 400 developers asking if they&#8217;re interested.  Within about 10 mins, I had to 10 emails of somewhat ticked off developers begging [...]]]></description>
			<content:encoded><![CDATA[<p>Something funny happened last night.  A one, Max Archie from Indiana hired an India-based Call Center to find a couple of Ruby developers.  Well, by and by, the recruiter mass-mails some 400 developers asking if they&#8217;re interested.  Within about 10 mins, I had to 10 emails of somewhat ticked off developers begging for people to stop replying!  Unfortunately, it was getting on late and stressed out developers up after midnight tend to get a little cantankerous and start poking real fun at the world in ways only we can do.</p>
<p>Today, we have <a href="http://groups.google.com/group/pradiptas-rolodex">Pradipta&#8217;s Rolodex</a>!<br />
<a href="http://digg.com/programming/recruiter_stupidly_CC_s_400_coders_and_one_replies_all">digg link</a> <a href="http://www.reddit.com/info/6scl4/comments/">Reddit</a>.</p>
<p>To all developers out there unfortunate enough to get caught in this web, thanks, for you have made me laugh out loud harder than I have in a good while!</p>
<p>Cheerios!</p>
]]></content:encoded>
			<wfw:commentRss>http://ramblings.gibberishcode.net/archives/pradiptas-rolodex/12/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
