<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Realjenius.com</title>
	
	<link>http://www.realjenius.com</link>
	<description>Realjenius.com - Tech, Java, Ruby, Scala, and Sarchasm</description>
	<lastBuildDate>Thu, 05 Aug 2010 02:51:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/realjenius" /><feedburner:info uri="realjenius" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>My Experience with a MediaTemple (ve)</title>
		<link>http://feedproxy.google.com/~r/realjenius/~3/Oa3f7UPXKRU/</link>
		<comments>http://www.realjenius.com/2010/08/04/my-experience-with-a-mediatemple-ve/#comments</comments>
		<pubDate>Thu, 05 Aug 2010 02:51:01 +0000</pubDate>
		<dc:creator>R.J.</dc:creator>
				<category><![CDATA[Journal]]></category>

		<guid isPermaLink="false">http://www.realjenius.com/?p=597</guid>
		<description><![CDATA[I just switched RealJenius.com (and a whole crap-ton of other sites I host) from a MediaTemple (dv) 3.5 to one of their new MediaTemple (ve) servers. This was kind of an ideal move for me, as I&#8217;ve been using Ubuntu as my primary development desktop for months, and with my recent career change, I&#8217;ve been [...]]]></description>
			<content:encoded><![CDATA[<p>I just switched RealJenius.com (and a whole crap-ton of other sites I host) from a <a href="http://mediatemple.net/webhosting/dv/">MediaTemple (dv) 3.5</a> to one of their new<a href="http://mediatemple.net/webhosting/ve/"> MediaTemple (ve)</a> servers. This was kind of an ideal move for me, as I&#8217;ve been using Ubuntu as my primary development desktop for months, and with my recent career change, I&#8217;ve been doing a lot more system administration work (on Ubuntu VMs none-the-less).</p>
<p>If you&#8217;re as lured by the (ve) as I was, let me give you some details from my experience:</p>
<ul>
<li>Provisioning is lightning-quick. I ordered the server, and it was available within 5 minutes.</li>
<li>It is truly as they say: just a Linux box with SSH. For my install, I was given a stripped down Ubuntu 10.04 server instance and told &#8220;Go Play!&#8221;.</li>
<li>For that reason I would recommend, if you are migrating from somewhere else, that you practice the migration on a VM somewhere, like with <a href="http://www.virtualbox.org">VirtualBox</a>. Since you&#8217;re responsible for the &#8220;whole shootin&#8217; match&#8221;, it&#8217;s in your best interest to have everything inline to make your transition as seamless as possible.</li>
<li>Post-install configurations are everything! I have been using pre-packaged VPS solutions for so long, I forgot that they spend a lot of time tweaking and tuning software to fit in a box the size they choose. Software like PHP, Apache, MySQL, Java, Tomcat, etc &#8211; all comes with default values and selections that, I guarantee you, are different than most VPS&#8217;s are running.</li>
<li>Aptitude is your friend! I chose Ubuntu because I knew how blindingly simple the package manager was to use. The installation of Apache, PHP and MySQL support (while not tuned) was literally only bound by the time to download the packages. My job was to sit and watch it work.</li>
</ul>
<p>I chose to do a number of things to tune my installation after I got it up and running. There are a lot of things to consider when you are your own sys-admin!</p>
<h2>Tuning Apache Memory</h2>
<p>First &#8211; tell Apache to calm down on memory usage. The default Apache install will use <em>massive</em> amounts of room in each thread stack (mostly because Linux tells it to). In reality, unless you&#8217;re expecting to handle some pretty impressive load while shipping some pretty impressive HTML, you probably don&#8217;t need 8MB <em>per stack</em>. To detune Apache in Ubuntu 10.04 to use less memory, you can edit &#8216;/etc/init.d/apache2&#8242; and put a stack-ulimit adjustment at the top of the file:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">ulimit</span> <span style="color: #660033;">-s</span> <span style="color: #000000;">256</span></div></td></tr></tbody></table></div>
<p>Lowering my stack for Apache to 256k (which coincidentally is Java&#8217;s default stack size), lowered my memory usage for Apache and whatever else was on the box at the time (running standard pre-fork) from 750MB, to 280MB. Now, that includes virtual memory and everything else &#8211; but when you&#8217;ve only got 1GB to work with, that&#8217;s a pretty significant savings.</p>
<h2>Switching Apache&#8217;s Multi-Processing Module</h2>
<p>The next thing I did to trim the Apache fat was to switch to mpm-worker threads instead of mpm-prefork. Now, most folks may comment here that mpm-worker actually uses more memory at idle, and while that&#8217;s technically true, it is much more predictable and scales much better from a memory perspective (think threads vs. processes if you are a Java or Ruby developer). It also generally happens to be faster, which is a nice benefit.</p>
<p>Unfortunately, when you move away from pre-fork, you also move away from easy PHP installations. To get PHP to work with mpm-workers, you have to use something like FastCGI, which acts as a PHP worker process pool that runs outside of the Apache process. Now &#8211; I made this a lot harder on myself by trying to host sites outside of /var/www &#8211; I wanted all of the folks sites I host to be under their respective home folder: /home/guy-who-mooches/guys-site.com/yadaydayada (just kidding people who I host!). I&#8217;ll point you to several articles on the net about it:</p>
<ul>
<li><a href="http://www.howtoforge.com/how-to-set-up-apache2-with-mod_fcgid-and-php5-on-ubuntu-8.10">http://www.howtoforge.com/how-to-set-up-apache2-with-mod_fcgid-and-php5-on-ubuntu-8.10</a></li>
<li><a href="http://www.chriswiegman.com/2010/06/running-apachefastcgisuexec-in-ubuntu-10-04-without-varwww/">http://www.chriswiegman.com/2010/06/running-apachefastcgisuexec-in-ubuntu-10-04-without-varwww/</a></li>
<li><a href="http://www.unixguru.biz/howto-apache2-suexec-php5-and-fastcgi-for-virtual-domains/">http://www.unixguru.biz/howto-apache2-suexec-php5-and-fastcgi-for-virtual-domains/</a></li>
<li><a href="http://www.linode.com/forums/viewtopic.php?t=2982">http://www.linode.com/forums/viewtopic.php?t=2982</a></li>
</ul>
<p>All of these sites have different (albeit similar) approaches. The key things to double check in this effort are:</p>
<ul>
<li>Install apache-suexec-custom  (the &#8216;custom&#8217; is key!). Some sites suggest that you have to compile your own apache-suexec install; this is no longer true (that&#8217;s what the custom is for).</li>
<li>Leave Apache running (or make Apache run) as &#8216;www-data&#8217; &#8211; I made the mistake of switching it to the user apache/apache, and getting suexec-custom to work with that user was a fool&#8217;s errand for me.</li>
<li>With 10.04, you have to edit the file in /etc/init.d/apache2/suexec called &#8216;www-data&#8217; and change the first line from &#8216;/var/www&#8217; to wherever you want suexec to be allowed to run from (for me it had to be &#8216;/home&#8217;).</li>
<li>You&#8217;ll need to create a wrapper script for each user. Don&#8217;t use symbolic links. This wrapper script must have that user as the owner/group (whatever user is going in the suexec directive, anyway).</li>
<li>Pay attention to the properties you set in the wrapper script! They have drastic impacts on both performance and resource utilization. You need to have a feel for your site&#8217;s intended usage to be able to tune these.</li>
<li>The suxec directive and FCGI wrapper directives in the Virtual Host file vary in every article I read about this (there is more than one way to skin a cat) &#8211; I tried both the Action/AddHandler combo approach, and the FCGIWrapper approach. FCGIWrapper is simpler, but Action/AddHandler is more flexible. I&#8217;d start with FCGIWrapper to get it working, and when you are feeling more confident, try action/addhandler if you think you need it.</li>
</ul>
<p>Anyway &#8211; rather than rehash a full walk-through, I felt it would be better to provide some bullet-points. Until I embraced understanding how FastCGI actually worked, I found I was struggling to properly implement it. So take your time, read the articles, try to understand the scripts, and come back here and read my tips. I think you&#8217;ll be better off for it!</p>
<h2>Best Apache Tuning Tip</h2>
<p>Many folks say the best Apache tuning tip is to use <a href="http://nginx.org/">Nginx</a>. That may be true &#8211; I wanted to move fast, and I know very little about administering Nginx. I know that I will have to do some .htaccess file conversion&#8230; so maybe in a couple weeks.</p>
<h2>User Management</h2>
<p>I highly recommend creating a non-root user for yourself. Giving that non-root user sudo access gives you enough of a barrier to be careful, but still gives you the flexibility you need to administer. In Ubuntu, sudo-ing requires that your user be in the &#8220;sudo&#8221; group. That&#8217;s as simple as:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">usermod <span style="color: #660033;">-G</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>username<span style="color: #7a0874; font-weight: bold;">&#93;</span></div></td></tr></tbody></table></div>
<h2>Use Identity Files</h2>
<p>This is a huge boon in my opinion. Identity files are much more secure than passwords, and can make your login process faster (if you&#8217;re willing to trade-off the security of a passphrase). Here is a great article about it: <a href="http://www.csua.berkeley.edu/~ranga/notes/ssh_nopass.html">http://www.csua.berkeley.edu/~ranga/notes/ssh_nopass.html</a></p>
<h2>Learn to SSH Tunnel</h2>
<p>SSH tunneling is secure. If you know how to tunnel, there is no reason to want to install PHP My Admin for example. It&#8217;s a security risk (don&#8217;t believe me? scan the Apache access logs of any decently popular domain, and you will see hack-attempts against dozens of phpmyadmin common URLs), and it&#8217;s not a very awesome administration tool. Meanwhile, MySQL administrator and MySQL Query Browser are awesome and just need an HTTP port. Here is one way to do it:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">ssh</span> <span style="color: #660033;">-L</span> <span style="color: #000000;">1234</span>:127.0.0.1:<span style="color: #000000;">3306</span> myuser<span style="color: #000000; font-weight: bold;">@</span>myfakeserver.com</div></td></tr></tbody></table></div>
<p>This forwards the port 1234 on your machine to port 3306 on your server (which is the default port for MySQL). Then, when you open MySQL Administrator/Query Browser, just try to connect to 127.0.0.1 on port 1234. Now you have full administrative access to MySQL (bells and whistles abounding) and you can be comfortable that the traffic is encrypted.</p>
<p>Tunneling with -D (dynamic SOCKS proxy) is also an excellent way to monitor a Java instance as well, using VisualVM and JMX (<a href="http://stackoverflow.com/questions/1609961/visualvm-over-ssh">http://stackoverflow.com/questions/1609961/visualvm-over-ssh</a>). Again, totally secure monitoring of a running JVM &#8211; hard to beat.</p>
<h2>Conclusion</h2>
<p>Media-Temple&#8217;s (ve) offering is excellent in my estimation. The servers are fast, the memory #s are phenomenal (especially considering you can run whatever you want), and you have total unadulterated control. Two-thumbs-up MT!</p>
<img src="http://feeds.feedburner.com/~r/realjenius/~4/Oa3f7UPXKRU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.realjenius.com/2010/08/04/my-experience-with-a-mediatemple-ve/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.realjenius.com/2010/08/04/my-experience-with-a-mediatemple-ve/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</feedburner:origLink></item>
		<item>
		<title>JRuby and Sinatra in 2 Minutes</title>
		<link>http://feedproxy.google.com/~r/realjenius/~3/05s2wnK6-4o/</link>
		<comments>http://www.realjenius.com/2010/07/17/jruby-and-sinatra-in-2-minutes/#comments</comments>
		<pubDate>Sat, 17 Jul 2010 16:53:22 +0000</pubDate>
		<dc:creator>R.J.</dc:creator>
				<category><![CDATA[Journal]]></category>
		<category><![CDATA[bundler]]></category>
		<category><![CDATA[glassfish]]></category>
		<category><![CDATA[JRuby]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[sinatra]]></category>

		<guid isPermaLink="false">http://www.realjenius.com/?p=591</guid>
		<description><![CDATA[While at RubyMidwest I decided to explore Sinatra in more detail. I&#8217;ve spent a lot of time with Rails, and while I love it, there is something alluring about the simplicity of Sinatra (and, well&#8230; ooh shiny). Being a recovering Java developer (Hi, I&#8217;m R.J., and I haven&#8217;t developed in Java for 18 hours) I [...]]]></description>
			<content:encoded><![CDATA[<p>While at <a href="http://www.rubymidwest.com">RubyMidwest</a> I decided to explore <a href="http://www.sinatrarb.com/">Sinatra</a> in more detail. I&#8217;ve spent a lot of time with <a href="http://www.rubyonrails.org">Rails</a>, and while I love it, there is something alluring about the simplicity of Sinatra (and, well&#8230; ooh shiny). Being a recovering Java developer (Hi, I&#8217;m R.J., and I haven&#8217;t developed in Java for 18 hours) I have a server that runs Java, and would like to be able to use Sinatra to build my fancy-awesome web-apps. On those lines, I want all of the shiny benefits of <a href="http://www.jruby.org">JRuby&#8217;s</a> multi-threading awesome-ness, as opposed to just trying to use WEBrick, which does not a powerful server make. So here is a 2 minute tutorial (well, depending on the performance of your computer, and how fast you type) startup with <a href="http://www.sinatrarb.com">Sinatra</a>, <a href="http://www.jruby.org">JRuby</a>, <a href="http://www.gembundler.com">Bundler</a>, and <a href="http://wiki.glassfish.java.net/Wiki.jsp?page=JRuby">Glassfish</a>.</p>
<p>I&#8217;m cheating already by assuming you already have JRuby installed as your default Ruby installation. No? <a href="http://www.jruby.org">Go get it!</a></p>
<p>Next step is to get bundler:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">gem <span style="color: #c20cb9; font-weight: bold;">install</span> bundler</div></td></tr></tbody></table></div>
<p>Now we need to make a home for our application, and prep it for Bundler:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> testapp<br />
<span style="color: #7a0874; font-weight: bold;">cd</span> testapp<br />
edit Gemfile</div></td></tr></tbody></table></div>
<p>Here I&#8217;m creating a new file in testapp called &#8216;Gemfile&#8217; in your favorite editor. This is where we will sketch out our dependencies for Bundler to do all the hard work for us &#8211; here are the contents for this example:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">source :rubygems<br />
gem &quot;sinatra&quot;<br />
gem &quot;glassfish&quot;</div></td></tr></tbody></table></div>
<p>Frankly, that&#8217;s it. We tell Bundler to look for gems in RubyGems core repo, and then we ask it to make sure we have Sinatra and Glassfish. Now we can create the program &#8211; create the file &#8216;hello.rb&#8217;, and use these contents:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;rubygems&quot;</span><br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;bundler&quot;</span><br />
Bundler.<span style="color:#9900CC;">setup</span><br />
<br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;sinatra&quot;</span><br />
<br />
get <span style="color:#996600;">'/hi'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; <span style="color:#996600;">&quot;Hello World!&quot;</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>So what&#8217;s special for JRuby? Absolutely nothing. We do have special sauce for Bundler, (by calling Bundler.setup prior to the require for &#8216;sinatra&#8217;) but trust me &#8211; you&#8217;ll be happy you used it. You&#8217;ll also make <a href="http://www.twitter.com/wycats">@wycats</a> happy.</p>
<p>And &#8211; that&#8217;s it! Now, if you were to start this file the standard (well, bundler-standard) way, we&#8217;ll see this:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">realjenius$ bundle <span style="color: #7a0874; font-weight: bold;">exec</span> hello.rb<br />
== Sinatra<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1.0</span> has taken the stage on <span style="color: #000000;">4567</span> <span style="color: #000000; font-weight: bold;">for</span> development with backup from WEBrick<br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2010</span>-07-<span style="color: #000000;">17</span> <span style="color: #000000;">11</span>:<span style="color: #000000;">24</span>:<span style="color: #000000;">46</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> INFO &nbsp;WEBrick 1.3.1<br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2010</span>-07-<span style="color: #000000;">17</span> <span style="color: #000000;">11</span>:<span style="color: #000000;">24</span>:<span style="color: #000000;">46</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> INFO &nbsp;ruby 1.8.7 <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">2010</span>-06-06<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>java<span style="color: #7a0874; font-weight: bold;">&#93;</span><br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2010</span>-07-<span style="color: #000000;">17</span> <span style="color: #000000;">11</span>:<span style="color: #000000;">24</span>:<span style="color: #000000;">46</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> INFO &nbsp;WEBrick::HTTPServer<span style="color: #666666; font-style: italic;">#start: pid=44490 port=4567</span></div></td></tr></tbody></table></div>
<p>&#8230;and we can visit this URL: <a href="http://localhost:4567/hi">http://localhost:4567/hi</a>. But, recall that our goal was to work with Glassfish, not WEBrick. All that has to change (and for folks who has done Glassfish/Rails before, this won&#8217;t be a surprise) is to run this startup instead</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">realjenius$ bundle <span style="color: #7a0874; font-weight: bold;">exec</span> glassfish<br />
Log <span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #000000; font-weight: bold;">/</span>Users<span style="color: #000000; font-weight: bold;">/</span>realjenius<span style="color: #000000; font-weight: bold;">/</span>Projects<span style="color: #000000; font-weight: bold;">/</span>testapp<span style="color: #000000; font-weight: bold;">/</span>log<span style="color: #000000; font-weight: bold;">/</span>development.log does not exist. Creating a new one...<br />
Starting GlassFish server at: 0.0.0.0:<span style="color: #000000;">3000</span> <span style="color: #000000; font-weight: bold;">in</span> development environment...<br />
Writing log messages to: <span style="color: #000000; font-weight: bold;">/</span>Users<span style="color: #000000; font-weight: bold;">/</span>realjenius<span style="color: #000000; font-weight: bold;">/</span>Projects<span style="color: #000000; font-weight: bold;">/</span>testapp<span style="color: #000000; font-weight: bold;">/</span>log<span style="color: #000000; font-weight: bold;">/</span>development.log.<br />
Press Ctrl+C to stop.<br />
<br />
Running sinatra</div></td></tr></tbody></table></div>
<p>This time, we&#8217;ll visit this URL: <a href="http://localhost:3000/hi">http://localhost:3000/hi</a>, and if all worked as desired, Sinatra will be crooning away. Boom goes the dynamite.</p>
<img src="http://feeds.feedburner.com/~r/realjenius/~4/05s2wnK6-4o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.realjenius.com/2010/07/17/jruby-and-sinatra-in-2-minutes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.realjenius.com/2010/07/17/jruby-and-sinatra-in-2-minutes/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</feedburner:origLink></item>
		<item>
		<title>Upgraded to WordPress 3.0</title>
		<link>http://feedproxy.google.com/~r/realjenius/~3/EqFHIOq_9vE/</link>
		<comments>http://www.realjenius.com/2010/06/24/upgraded-to-wordpress-3-0/#comments</comments>
		<pubDate>Fri, 25 Jun 2010 02:37:23 +0000</pubDate>
		<dc:creator>R.J.</dc:creator>
				<category><![CDATA[Journal]]></category>

		<guid isPermaLink="false">http://www.realjenius.com/?p=574</guid>
		<description><![CDATA[I just completed the upgrade to WordPress 3.0. So far, the upgrade appeared to go seamlessly. Everything is running, no plugins are complaining, yadayadayada. If you have a problem on the site please be sure to let me know. If you are a WordPress user, and want to see what has changed since 2.9, here [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.realjenius.com/wp-content/uploads/2009/09/wordpress-logo-stacked-bg.png#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed"><img class="alignright size-full wp-image-111" title="wordpress-logo-stacked-bg" src="http://www.realjenius.com/wp-content/uploads/2009/09/wordpress-logo-stacked-bg.png" alt="" width="176" height="145" /></a></p>
<p>I just completed the upgrade to WordPress 3.0. So far, the upgrade appeared to go seamlessly. Everything is running, no plugins are complaining, yadayadayada. If you have a problem on the site please be sure to let me know.</p>
<p>If you are a WordPress user, and want to see what has changed since 2.9, here is a lovely screencast that covers the particulars:</p>
<p><embed src="http://v.wordpress.com/wp-content/plugins/video/flvplayer.swf?ver=1.21" type="application/x-shockwave-flash" width="640" height="360" wmode="transparent" seamlesstabbing="true" allowfullscreen="true" allowscriptaccess="always" overstretch="true" flashvars="guid=BQtfIEY1&amp;width=640&amp;height=360&amp;locksize=no&amp;dynamicseek=false&amp;qc_publisherId=p-18-mFEk4J448M" title="Introducing WordPress 3.0 &quot;Thelonious&quot;"></embed></p>
<img src="http://feeds.feedburner.com/~r/realjenius/~4/EqFHIOq_9vE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.realjenius.com/2010/06/24/upgraded-to-wordpress-3-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.realjenius.com/2010/06/24/upgraded-to-wordpress-3-0/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</feedburner:origLink></item>
		<item>
		<title>Distilling JRuby: Frames and Backtraces</title>
		<link>http://feedproxy.google.com/~r/realjenius/~3/C8B4_rES_GA/</link>
		<comments>http://www.realjenius.com/2010/03/15/distilling-jruby-frames-backtraces/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 10:00:11 +0000</pubDate>
		<dc:creator>R.J.</dc:creator>
				<category><![CDATA[Distilling JRuby]]></category>
		<category><![CDATA[Code Analysis]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JRuby]]></category>

		<guid isPermaLink="false">http://www.realjenius.com/?p=530</guid>
		<description><![CDATA[Welcome back JRuby fans. I took a poll on twitter about what distilling article to do next, and frames and backtraces was the clear winner &#8211; so here we are! (three months later) In previous &#8220;distilling&#8221; articles, I discussed how methods are dispatched, and then how the scope of variables in each method and block [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.realjenius.com/wp-content/uploads/2009/09/logo.png" alt="Ruby Logo" title="Ruby Logo" width="99" height="119" class="alignright size-full wp-image-181" /><br />
Welcome back JRuby fans. I took a poll on twitter about what distilling article to do next, and frames and backtraces was the clear winner &#8211; so here we are! (three months later)</p>
<p>In previous &#8220;distilling&#8221; articles, I discussed how methods are dispatched, and then how the scope of variables in each method and block is managed. The scope and dispatch rules are only part of the big picture, however. Ruby, as a programming language, must gather rich information about the execution of the program, and must be able to share this with the developer when errors occur. Furthermore, Ruby itself provides a number of kernel-level methods for accessing and manipulating the current invocation stack (such as Kernel.caller).</p>
<p>This article is all about how JRuby implements those concepts.</p>
<p><span id="more-530"></span></p>
<div class="seriesNote">
This is <strong>Part 4</strong> in a series on JRuby I have started, called &#8220;Distilling JRuby&#8221; &#8211; the <a href="http://www.realjenius.com/category/distilling-jruby/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed">entire series is available here</a>. The preceding articles to this one are available here:<br />
<a href="http://www.realjenius.com/2009/09/16/distilling-jruby-method-dispatching-101/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed">Part 1: Method Dispatching 101</a><br />
<a href="http://www.realjenius.com/2009/09/25/distilling-jruby-tracking-scope/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed">Part 2: Tracking Scope</a><br />
<a href="http://www.realjenius.com/2009/10/06/distilling-jruby-the-jit-compiler/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed">Part 3: The JIT Compiler</a>
</div>
<h2>Overview</h2>
<p>A frame in JRuby parlance is a representation of a method call, block call, eval, etc. kept for presentation to the developer. A backtrace is a representation of the active method stack at any point in time &#8211; in other words, it&#8217;s a stack of frames. In Java, this would typically be referred to as a &#8216;stack trace&#8217; &#8211; at least, that&#8217;s the most direct counterpart.</p>
<p>It can be difficult when juggling a language implementation around in your head to realize that the trace we&#8217;re talking about is specific to the method calls in Ruby itself. JRuby may execute a number of &#8220;native&#8221; methods (code written in Java) that do not show up as part of this backtrace &#8211; the code that must run in between steps of the Ruby code executing is implementation-specific to JRuby; the Ruby developer shouldn&#8217;t care what internal magic JRuby had to do to get a method to invoke (nor would they know what to do with that knowledge if they did have it).</p>
<p>While it may not seem incredibly important initially, JRuby goes to great pains to be as compatible as possible with MRI in terms of what backtraces are generated (This &#8216;compatibility mode&#8217; incurs a certain cost, and it may be preferrable to turn this off to give JRuby an opportunity to bypass this internal bookkeeping if, as a developer, you don&#8217;t need a backtrace to match MRI; but we&#8217;ll get into those experimental optimizations later). Backtrace information turns out to be quite important, as it is the first set of information a developer typically uses to trace execution issues in their own code; if it isn&#8217;t accurate (or at least traversable) it could easily make a small problem a big one.</p>
<h2>Tracking Frames</h2>
<p><em>I would like to mention at this point that it would be in your best interests to read the earlier Distilling JRuby articles, if you haven&#8217;t already. Method dispatching, scope, and the JIT compiler are all entertwined with the concept of frames, and I will be talking about these various relationships throughout this article.</em></p>
<p>You may recall that during the article regarding tracking variable scope, I mentioned that the ThreadContext is consulted on a number of occasions to find data in the variable table. At the time, I was talking about how variables are managed; but that same context class acts as the main source for tracking the frames of method invocation. We saw previously that when a Ruby method is dispatched, a variant of method named &#8220;preMethod{&#8230;}()&#8221; would be called on the ThreadContext class, and that would in turn tell the ThreadContext to create another DynamicScope object and put it on the top of the stack. It turns out this is exactly where the frame is managed as well. Here is a block of code I showed from the JRuby codebase in that previous article:</p>
<div class="codecolorer-container java twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> preMethodFrameAndScope<span style="color: #009900;">&#40;</span>RubyModule clazz, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> name, IRubyObject self, Block block, StaticScope staticScope<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; RubyModule implementationClass <span style="color: #339933;">=</span> staticScope.<span style="color: #006633;">getModule</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; pushCallFrame<span style="color: #009900;">&#40;</span>clazz, name, self, block<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// &lt;-- What we care about this time</span><br />
&nbsp; pushScope<span style="color: #009900;">&#40;</span>DynamicScope.<span style="color: #006633;">newDynamicScope</span><span style="color: #009900;">&#40;</span>staticScope<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; pushRubyClass<span style="color: #009900;">&#40;</span>implementationClass<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Note how this method not only creates a new scope to represent the method&#8217;s static scope, but also calls &#8216;pushCallFrame(&#8230;)&#8217;. This is where the new frame is created to represent the method that is being invoked. This frame is represented by a &#8216;org.jruby.runtime.Frame&#8217; object, which is put on the top of the frame stack.</p>
<p>By most accounts, the Frame object in JRuby is a simple mutable Java bean. The class is relatively simple, and carries a few key pieces of information:</p>
<ul>
<li>The object that owns the code being invoked</li>
<li>The name of the method (or block or eval) being invoked</li>
<li>The visibility of the method</li>
<li>The name of the file <em>where the invocation of the frame occurred</em>.</li>
<li>The line number in the calling file <em>where the invocation of the frame occurred</em>.</li>
</ul>
<p>&#8230; and that&#8217;s it! This is basically all that is required to produce a single line in a backtrace. The entire stack of frames then, in turn, represents the entire backtrace.</p>
<h2>The Magic Line Number</h2>
<p>While the program is executing, the line number is constantly changing. The frame has some idea of this line number, but only in terms of when the method was called in the enclosing code &#8211; it&#8217;s not a live representation. However, when you think about a running program, the number on the top of the trace is constantly changing &#8211; and on top of that, the frame that <em>is </em>the top of the trace is constantly changing as well &#8211; so who is keeping track of this magic number?</p>
<p>It turns out it&#8217;s the ThreadContext again, where an integer is kept to keep track of the most current line number (and actually the most current file, as well). In the basic (interpreted) mode of JRuby, the various AST nodes (control statements like if and while, blocks, methods, etc) all have their line number baked into them. When they are invoking, they will update the line number on the thread context. For example, here is the top part of the &#8216;interpret&#8217; method on org.jruby.ast.IfNode:</p>
<div class="codecolorer-container java twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@Override<br />
<span style="color: #000000; font-weight: bold;">public</span> IRubyObject interpret<span style="color: #009900;">&#40;</span>Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; ISourcePosition position <span style="color: #339933;">=</span> getPosition<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; context.<span style="color: #006633;">setFile</span><span style="color: #009900;">&#40;</span>position.<span style="color: #006633;">getFile</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; context.<span style="color: #006633;">setLine</span><span style="color: #009900;">&#40;</span>position.<span style="color: #006633;">getStartLine</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// ...</span></div></td></tr></tbody></table></div>
<p>For JIT compiler fans, note that it also manages the line number like the interpreted nodes, but as usual is a little more obscure. Two things are done for the JIT compiler: first &#8211; code is generated that will call into the ThreadContext to update the line number information like above (See ASTCompiler#compileNewLine). Additionally, however, the line numbers are also actually written into the generated Java bytecode using the standard label/line-number bytecode structures (This will provide distinct advantages in generating backtraces, as we will see later).</p>
<p>As the various code is invoked, this number is constantly being changed to represent the position from the original source. When a new method or block is invoked, that value is copied onto the frame and preserved. This allows the frame to keep track of when it lost control of the execution, while the thread context keeps track of the live line number.</p>
<p>Let&#8217;s take a look at a sample backtrace for a specific example:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">./another.rb:7:in `do_something_else': undefined method `call' for nil:NilClass (NoMethodError)<br />
&nbsp; &nbsp; from ./another.rb:3:in `do_something'<br />
&nbsp; &nbsp; from test.rb:5:in `run'<br />
&nbsp; &nbsp; from test.rb:9</div></td></tr></tbody></table></div>
<p>So what this tells us is that in the method &#8216;do_something_else&#8217; in another.rb, on line 7, we had a NoMethodError trying to call the method &#8216;call&#8217; on a nil variable. Additionally, we know the three method calls it took to get to this point. Here is a diagram that shows what the frame stack looks like in the runtime at the moment this occurs (as usual, I&#8217;ve done some hand-wavy magic here to simplify a few less-important details&#8230;):</p>
<div id="attachment_464" class="wp-caption aligncenter" style="width: 237px"><a href="http://www.realjenius.com/wp-content/uploads/2010/03/traces1.png#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed"><img src="http://www.realjenius.com/wp-content/uploads/2010/03/traces1.png" alt="" title="traces1" width="227" height="299" class="size-full wp-image-464" /></a><p class="wp-caption-text">Note the line number mis-match</p></div>
<p>As you can see, the line number stored on the frame correlates to the position in the previous call where the invocation occurred. Also notice that the thread context carries the currently active file and line &#8211; but the method name is inferred from the top frame. This mixed relationship, while effective for the way that frames are recorded, can be confusing at first.</p>
<h2>Managing Frames at Runtime</h2>
<p>JRuby tries to avoid creating a huge volume of frame objects during execution; in general, the expectation is that a program is going to invoke a lot of methods during execution. If each method was represented by a frame, that would mean a lot of frame objects. To combat this, the frame objects are pre-allocated on the frame stack, and reused. Since programs are generally going to repeatedly traverse up and down the frame-stack, hovering around the same depth of execution, this is one place in Java code where pooling of objects probably makes good sense. Rather than JRuby creating thousands and thousands of frame objects, it will only create enough for the deepest level of execution per thread.</p>
<p>Internally speaking, the ThreadContext class keeps a growable Frame[], but in the process it also ensures that each slot is pre-filled with a ready-to-use frame object. If the allocation needs to grow, the array is increased by a capacity, the existing frame objects are moved to the new array, and the new empty slots are filled with additional Frame allocations.</p>
<p>When a Frame object is set up for use, some variant of the #updateFrame method is called, which basically captures all of the invocation information &#8211; it effectively behaves as a constructor:</p>
<div class="codecolorer-container java twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp;<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> updateFrame<span style="color: #009900;">&#40;</span>RubyModule klazz, IRubyObject self, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> name,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Block block, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> fileName, <span style="color: #000066; font-weight: bold;">int</span> line, <span style="color: #000066; font-weight: bold;">int</span> jumpTarget<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">self</span> <span style="color: #339933;">=</span> self<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">name</span> <span style="color: #339933;">=</span> name<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">klazz</span> <span style="color: #339933;">=</span> klazz<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">fileName</span> <span style="color: #339933;">=</span> fileName<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">line</span> <span style="color: #339933;">=</span> line<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">block</span> <span style="color: #339933;">=</span> block<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">visibility</span> <span style="color: #339933;">=</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Avisibility+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Visibility</span></a>.<span style="color: #000000; font-weight: bold;">PUBLIC</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">isBindingFrame</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">jumpTarget</span> <span style="color: #339933;">=</span> jumpTarget<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<h2>Dispatching Options</h2>
<p>In all of the past three articles, I have brushed by the CallConfiguration enumeration. This enum is a pretty significant lynch-pin in the dispatching and execution of program flow, as it decides a number of things about method and block invocation. Each method may be dispatched using a number of possible call configurations, based on the state of the running program, and the needs of code block being executed. This CallConfiguration decides not only whether a Frame object is required for the call, but also whether or not a Scope is required. This abstraction is very useful as both the interpreter, and the JIT-compiled code dispatch using this configuration strategy.</p>
<p>Just as certain methods may not require an explicit scope (no variables are mutated), some methods also don&#8217;t require frames. With both scope and frame, the primary reasons for skipping their use is performance. In the case of scope, the code which manages this is entirely transparent; you don&#8217;t care how your variables are managed, as long as they are managed.</p>
<p>However, with frames it&#8217;s not that simple. We&#8217;ve already discussed how method invocations can be compiled in to Java code in JRuby &#8211; effectively avoiding the overhead of making a series of reflection calls in favor for a generated block of Java code that properly preps the Ruby context, and invokes the method through the call site. In this process, a number of possible invocations can be generated &#8211; some that setup the frame constructs, and some that don&#8217;t. If you tell Ruby it can optimize away as much as possible through flags, it will generate these method connectors to be ultra-super-cool-fast.</p>
<p>Strictly speaking, to turn off frames in the compilation process, you simply need to set &#8216;jruby.compile.frameless&#8217; to true &#8211; although to get the most speed, you could instead set &#8216;jruby.compile.fastest&#8217; (which implies a number of other settings as well).</p>
<p>It should be noted that, by default, these settings are turned off, and both are marked as experimental. By leaving them disabled by default, it ensures that JRuby, out of the box, is compatible with MRI Ruby as it pertains to generated backtraces and frame manipulation, and is as stable as possible. Turning them on can easily break certain frameworks and libraries that expect the frame or backtrace to be consistent, and manageable. In many cases, however, your application won&#8217;t need that kind of control over the frame, and you may not care that the backtrace be exact.</p>
<p>Here are some general rules followed when dispatching to a method or block:</p>
<ul>
<li>A full frame will <em>always</em> be used if compatibility mode is enabled (jruby.compile.frameless is set to false).</li>
<li>Certain system-level invocations (such as the &#8216;eval&#8217; method) get a frame no matter what, as they are frame aware.</li>
<li>In all other cases either a backtrace-only frame (a &#8220;lite&#8221; frame) will be used at most.</li>
<li>If jruby.compile.fastest is set to true, then frames will not be used at all unless it is required by the running program to exist. This obviously has some impact on the readability of the execution.</li>
</ul>
<p>As mentioned above, readability of backtraces is an issue with jruby.compile.fastest &#8212; less accurate information will be available. For example, the trace above that was used looks like this when run with fastest-compilation on:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">./another.rb:7:in `do_something_else': undefined method `call' for nil:NilClass (NoMethodError)<br />
&nbsp; &nbsp; from ./another.rb:3:in `do_something'<br />
&nbsp; &nbsp; from :1:in `run'<br />
&nbsp; &nbsp; from :1</div></td></tr></tbody></table></div>
<p>Note that all frames but the top are completely unaware of the execution details &#8211; in many cases this may be sufficient information to fix a problem, but it is certainly <em>less</em> than what is available in compatibility mode.</p>
<p>The &#8216;lite&#8217; backtrace-only frame I mentioned is basically a trimmed down representation that doesn&#8217;t hold on to references to the owning object. While this can reduce the usability of the frame (particularly for methods like &#8216;eval&#8217; that may need to interact with the caller), it&#8217;s a significant optimization as it takes several objects off the object graph, preventing long-lived references to live objects in from the program flow (such as the object that is being invoked against). This will allow the GC to handle these objects sooner than may otherwise be possible.</p>
<h2>Execution Flow</h2>
<p>When an error occurs, the execution needs to stop and unwind from the exception to the first point it is properly handled (with a rescue, or all the way out of the program). This can make following the JRuby code complicated, as Java exception flow is used as the back-bone for the Ruby exception flow, and so the two intermingle and must be kept separate in your mind.</p>
<p>The primary class that represents an exception in Ruby is org.jruby.RubyException, which is the JRuby native implementation of the Exception class in Ruby. There are a number of subclasses that are constructed (such as ArgumentError, as we will see below) that let Ruby code handle errors in a typed way, but effectively everything extends this &#8216;Exception&#8217; class. Now, while this is called &#8216;Exception&#8217;, it&#8217;s not actually a Java exception. It extends RubyObject (like all JRuby native peers), and is a representation of a Ruby exception for the runtime, but has no effect on Java as anything but a standard object.</p>
<p>However, RubyExceptions can be encountered during execution, and that should interrupt execution. Somehow this has to be handled in Java code. As an example, the &#8216;to_sym&#8217; method on RubyString is implemented natively in Java, and that method, by contract, should throw an exception if the string is empty.</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ruby -e '&quot;&quot;.to_sym'<br />
-e:1:in `to_sym': interning empty string (ArgumentError)<br />
&nbsp; &nbsp; from -e:1<br />
$ jruby -e '&quot;&quot;.to_sym'<br />
-e:1: interning empty string (ArgumentError)</div></td></tr></tbody></table></div>
<p>As it turns out, the easiest way to interrupt Java code like this is to use a Java exception. For this, JRuby uses the class &#8216;org.jruby.RaiseException&#8217;, which is, in fact, a real Java exception. As the name hints, it represents the execution of a &#8216;raise&#8217; keyword in Ruby (which is roughly analogous to a Java throw, but is actually a method on the Thread class). RaiseException contains the RubyException representing the error in Ruby code.</p>
<p>When Ruby code invokes &#8216;raise&#8217;, this method will delegate through org.jruby.RubyKernel#raise, which for the most part will end up throwing a new RaiseException. Now, this is where it gets tricky to distinguish the two. Keep in mind that the RaiseException simply exists so JRuby can back up the Java code to find the right Ruby code to handle the error. On the <em>other</em> side of the equation, the code in JRuby follows a pattern roughly like this:</p>
<div class="codecolorer-container java twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> interpret<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; runBodyRubyCode<span style="color: #009900;">&#40;</span>...<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">catch</span><span style="color: #009900;">&#40;</span>RaiseException e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; runRescueRubyCode<span style="color: #009900;">&#40;</span>e.<span style="color: #006633;">getRubyException</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">finally</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; runEnsureRubyCode<span style="color: #009900;">&#40;</span>...<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>This is pseudo-code mixed from the AST RescueNode and EnsureNode, but it captures the idea. First, the code is run &#8211; then, if a RaiseException occurs, the exception is sent into a rescue block of code. Keep in mind that when the rescue code is run, the Ruby exception is unboxed so it&#8217;s directly accessible to that code block (as it always is in Ruby). The ensure code is actually handled by a separate AST node (since it may be included independently of rescue), but the concept is the same as seen above.</p>
<p>The JIT obviously changes how this code is actually invoked (via generated Java code), but the same general logic applies.</p>
<p>If an exception <em>isn&#8217;t</em> handled via a mechanism like raise, then the RaiseException itself is handled by the Java bootstrap (such as the executable). This has some special consequences when it comes to embedded code, and we&#8217;ll get into that shortly.</p>
<p>Additionally, there is a special version of RaiseException called NativeException (this also exists in MRI) &#8211; this is a special wrapper for exceptions that occur in Java code called from JRuby code. When this happens, the stack trace for those native parts is actually <em>preserved</em> in the Ruby stack up to the point the Ruby code invoked the Java code. Here is an example of a backtrace that was created by an exception occurring in some Java code:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">java/lang/NumberFormatException.java:48:in 'forInputString': java.lang.NumberFormatException: For input string: &quot;15123sdfs&quot; (NativeException)<br />
&nbsp; &nbsp; from java/lang/Long.java:419:in 'parseLong'<br />
&nbsp; &nbsp; from java/lang/Long.java:468:in 'parseLong'<br />
&nbsp; &nbsp; from ./another.rb:7:in 'do_something_else'<br />
&nbsp; &nbsp; from ./another.rb:5:in 'do_something'<br />
&nbsp; &nbsp; from [script]:5:in 'run'<br />
&nbsp; &nbsp; from [script]:9</div></td></tr></tbody></table></div>
<h2>Constructing Backtraces</h2>
<p>Throughout this article, we&#8217;ve seen examples of backtraces that were (seemingly) generated off of the frame stack. To create a proper backtrace, the currently active frame stack must be copied and turned into a point-in-time snapshot of backtrace information. When an error occurs, the backtrace is captured with participation between the RaiseException, RubyException, and the ThreadContext.</p>
<p>When the RubyException is constructed, it asks the ThreadContext to create a backtrace, which then iterates over the current frame stack, creating a RubyStackTraceElement array. This array is then bound to the RubyException. Here is a sample of the loop that creates the backtrace array (I&#8217;ve trimmed some unnecessary details):</p>
<div class="codecolorer-container java twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> IRubyObject createBacktraceFromFrames<span style="color: #009900;">&#40;</span>Ruby runtime, RubyStackTraceElement<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> backtraceFrames<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp;RubyArray backtrace <span style="color: #339933;">=</span> runtime.<span style="color: #006633;">newArray</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>backtraceFrames <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">||</span> backtraceFrames.<span style="color: #006633;">length</span> <span style="color: #339933;">&lt;=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">return</span> backtrace<span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">int</span> traceSize <span style="color: #339933;">=</span> backtraceFrames.<span style="color: #006633;">length</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> traceSize <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;RubyStackTraceElement frame <span style="color: #339933;">=</span> backtraceFrames<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;addBackTraceElement<span style="color: #009900;">&#40;</span>runtime, backtrace, frame, backtraceFrames<span style="color: #009900;">&#91;</span>i <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp;<span style="color: #000000; font-weight: bold;">return</span> backtrace<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>In the normal &#8220;framed backtrace&#8221; workflow, that&#8217;s all there is to it. That array can then be used to emit to the console, or whatever else needs to occur.</p>
<p>Interestingly, there are a number of other &#8220;super secret&#8221; ways the backtrace can be generated. As best as I can tell, these are entirely undocumented on the JRuby site &#8211; these are simply custom values for &#8220;jruby.backtrace.style&#8221; &#8211; these include:</p>
<ul>
<li>&#8220;raw&#8221; &#8211; This version provides a very explicit output of what happened, including all of the internal JRuby stack &#8211; very useful for JRuby development:
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">from java/lang/Long.java:419:in `parseLong'<br />
&nbsp; &nbsp; from java/lang/Long.java:468:in `parseLong'<br />
&nbsp; &nbsp; from Thread.java:1460:in `getStackTrace'<br />
&nbsp; &nbsp; from RubyException.java:143:in `setBacktraceFrames'<br />
&nbsp; &nbsp; from RaiseException.java:177:in `setException'<br />
&nbsp; &nbsp; from RaiseException.java:119:in `&lt;init&gt;'<br />
&nbsp; &nbsp; from RaiseException.java:101:in `createNativeRaiseException'<br />
&nbsp; &nbsp; from JavaSupport.java:188:in `createRaiseException'<br />
&nbsp; &nbsp; from JavaSupport.java:184:in `handleNativeException'<br />
&nbsp; &nbsp; from JavaCallable.java:170:in `handleInvocationTargetEx'<br />
(... removed the rest for brevity ...)</div></td></tr></tbody></table></div>
</li>
<li>&#8220;raw_filtered&#8221; &#8211; Just like &#8216;raw&#8217;, but it omits any Java classes starting with &#8216;org.jruby&#8217;. This is handy if you have code-flows that go from Ruby -> Java -> Ruby -> Java, etc &#8211; and need to see the Java code intermixed. I&#8217;ve used this when coding in Swing and SWT where event hooks may go into Java, and back into Ruby.</li>
<li>&#8220;ruby_framed&#8221; (the default) &#8211; This uses the internal Ruby frame stack to generate an MRI-friendly backtrace. &#8220;rubinus&#8221; is currently compatible with this version. Depending on the settings you have enabled, this can return different values (as described above).</li>
<li>&#8220;ruby_compiled&#8221; &#8211; This uses the Java stack trace, and parses the compiled class names. When JRuby generates compiled invokers for methods, they will have mangled names that can be re-parsed (looking for sentinels like $RUBY$). Additionally, remember earlier how I said that the line numbers were actually compiled in to the Java code straight from the Ruby code? Well, that means the Java stack trace will automatically have the correct line numbers in it, so building the Ruby backtrace is truly just a matter of parsing the Java StackTraceElement[]. Because of the nature of the bytecode and the Java VM capturing this information, when running with jruby.compile.fastest set to true, this mode can actually return <em>more</em> accurate information than ruby_framed will. Note that if a method isn&#8217;t compiled, it will not show up in the Java stack, and as such the stack will only contain Java methods that were invoked (of which there may be none).</li>
<li>&#8220;ruby_hybrid&#8221; (currently disabled) &#8211; This version is meant to be able to munge compiled and interpreted information together into a mega-stack-trace, allowing for compiled and interpreted methods to show up in the same stack trace, using the Java stack to (auspiciously) improve performance where possible &#8212; I&#8217;m assuming it&#8217;s commented out due to some flaw in the implementation.</li>
</ul>
<h2>Embedding JRuby Programs in Java</h2>
<p>When embedding JRuby in Java programs, errors that occur can potentially leave the Ruby runtime altogether. When this happens, Java code is in total control. To make this transition as seamless as possible, JRuby performs some nifty tricks with traditional Java stack-traces.</p>
<p>Our old friend RaiseException actually generates the object-graph for a backtrace like above, and then creates a pseudo-Ruby stack in the Java code that lets a Java programmer see where in the Ruby code the error occurred. Here is the example from way up above as generated in Java code:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Exception in thread &quot;main&quot; javax.script.ScriptException: org.jruby.exceptions.RaiseException: undefined method 'call' for nil:NilClass<br />
&nbsp; &nbsp; at org.jruby.embed.jsr223.JRubyEngine.wrapException(JRubyEngine.java:112)<br />
&nbsp; &nbsp; at org.jruby.embed.jsr223.JRubyEngine.eval(JRubyEngine.java:173)<br />
&nbsp; &nbsp; at realjenius.SampleProgram.main(SampleProgram.java:13)<br />
Caused by: org.jruby.exceptions.RaiseException: undefined method 'call' for nil:NilClass<br />
&nbsp; &nbsp; at Kernel.call(./another.rb:7)<br />
&nbsp; &nbsp; at Another.do_something_else(./another.rb:3)<br />
&nbsp; &nbsp; at Another.do_something([script]:5)<br />
&nbsp; &nbsp; at MyClass.run([script]:9)<br />
&nbsp; &nbsp; at (unknown).(unknown)(:1)</div></td></tr></tbody></table></div>
<p>Other conversions for the backtrace (such as the fancy NativeException stuff) works naturally with this code as well, allowing for diversions in Ruby code to show up naturally in the Java stack.</p>
<h2>Frame Peeking with Ruby Programs</h2>
<p>I previously mentioned Kernel#caller, which is a method for peeking at the going-ons in the Ruby trace. Now that we understand the structure of the frames, it is probably pretty easy to see how they will be used. The implementation of org.jruby.RubyKernel#caller simply calls ThreadContext#createCallerBacktrace which is much like all of the other code we looked at, but it creates a RubyArray containing strings representing the state of the frames in the context at that time.</p>
<div class="codecolorer-container java twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> IRubyObject createCallerBacktrace<span style="color: #009900;">&#40;</span>Ruby runtime, <span style="color: #000066; font-weight: bold;">int</span> level<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">int</span> traceSize <span style="color: #339933;">=</span> frameIndex <span style="color: #339933;">-</span> level <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; RubyArray backtrace <span style="color: #339933;">=</span> runtime.<span style="color: #006633;">newArray</span><span style="color: #009900;">&#40;</span>traceSize<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> traceSize <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i<span style="color: #339933;">--</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addBackTraceElement<span style="color: #009900;">&#40;</span>runtime, backtrace, frameStack<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>, frameStack<span style="color: #009900;">&#91;</span>i <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> backtrace<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>It&#8217;s probably also clear by now why optimizations like &#8216;jruby.compile.fastest&#8217; can break these methods; the frames aren&#8217;t there for the ThreadContext to report against.</p>
<h2>Conclusion</h2>
<p>While the frame concepts in JRuby in and of themselves aren&#8217;t that complicated, you have to have a strong foundational knowledge of how Ruby works and how method dispatching in JRuby works to understand the code flows. I hope I&#8217;ve been able to condense the concepts into an easy enough walkthrough.</p>
<p>I&#8217;m by no means done with these JRuby articles &#8212; I took a little hiatus for work and personal reasons, but hope to have more coming out of the gates real soon. Here is a peek at some possible subjects:</p>
<ul>
<li>The Library Load Service</li>
<li>Continuations (Kernel#callcc)</li>
<li>Java Proxying and Support</li>
<li>The New Kid on the Block: Duby</li>
</ul>
<p>As usual, votes are welcome: <a href="http://www.realjenius.com/contact#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed">http://www.realjenius.com/contact</a>.</p>
<p>Stay Tuned!</p>
<img src="http://feeds.feedburner.com/~r/realjenius/~4/C8B4_rES_GA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.realjenius.com/2010/03/15/distilling-jruby-frames-backtraces/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.realjenius.com/2010/03/15/distilling-jruby-frames-backtraces/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</feedburner:origLink></item>
		<item>
		<title>The Ides of March</title>
		<link>http://feedproxy.google.com/~r/realjenius/~3/PZKkep45gTA/</link>
		<comments>http://www.realjenius.com/2010/03/13/the-ides-of-march/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 06:05:41 +0000</pubDate>
		<dc:creator>R.J.</dc:creator>
				<category><![CDATA[Journal]]></category>
		<category><![CDATA[Birthday]]></category>
		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://www.realjenius.com/?p=561</guid>
		<description><![CDATA[So Monday is my birthday: March 15th. For years I remember two things about the way adults reacted to me as a child: (1) Oh, your name is R.J.! That&#8217;s just like Dallas! (and for the record, no, no it is not). Or (2) Oh my! You were born on the Ides of March! It&#8217;s funny, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.realjenius.com/wp-content/uploads/2010/03/JuliusCaesar.png#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed"><img class="alignright size-full wp-image-562" title="JuliusCaesar" src="http://www.realjenius.com/wp-content/uploads/2010/03/JuliusCaesar.png" alt="" width="190" height="250" /></a>So Monday is my birthday: <a href="http://en.wikipedia.org/wiki/March_15">March 15th</a>. For years I remember two things about the way adults reacted to me as a child: (1) Oh, your name is R.J.! That&#8217;s just like Dallas! (and for the record, <a href="http://en.wikipedia.org/wiki/Dallas_(TV_series)">no, no it is not</a>). Or (2) Oh my! You were born on the <a href="http://en.wikipedia.org/wiki/Ides_of_March">Ides of March</a>!</p>
<p>It&#8217;s funny, because when I was a kid, I had no idea what the ides of march was; I just knew it carried with it a certain degree of playful dread, given the reaction of adults. As I&#8217;ve gotten older, I&#8217;ve learned a lot more about what the day actually is, and not what people seem to attribute to it.</p>
<p>If you have no idea what I&#8217;m talking about, I&#8217;m not surprised. It seems like the superstition around the date has faded in recent years. Historically speaking, the term &#8216;ides&#8217; meant the middle of the month for either Martius (March), Maius (May), Quintillis (July), or October on the Roman calendar. On the Ides of March, the Romans actively celebrated for Mars, the god of war (who, by the way, is awesome).<span id="more-561"></span></p>
<p>But the reason that we don&#8217;t go around talking about the ides of October is not because the God of the Month was less impressive, but simply because of the historical significance of 3/15. Julius Caesar (a rather important Roman) was murdered by the Brutus&#8217;, Longinus, and a bunch of other political turds.</p>
<p>So over the years, the day has carried a negative connotation. It has Dark Ominous Tones.</p>
<p>Now, the truth is, I am no Julius Caesar. Additionally, I find it highly unlikely that anyone will stab me to death. However, I&#8217;ve had enough people come up and chatter at me about the ides doom and gloom that I can think of a few to poke with the pointy end of a stick, at least threateningly.</p>
<p>Incidentally &#8211; you&#8217;ll likely notice that Quintillis is the only month that doesn&#8217;t have any aural relationship to it&#8217;s English counterpart. Well, it turns out that one of Julius Caesar&#8217;s many faults (for which he got the stabby stabby) was reforming the national calendar. The Roman calendar became the Julian calendar as he worked to resolve the listing that occurred in the traditional model set up by Romulus, which had 304 days, and was then later refined by Numa (Numa) which had 355 days. The Julian calendar is identical to our modern Gregorian calendar in terms of length and usage of leap years, but was simply not shifted to match the same days of the year.</p>
<p>When Julius Caesar was murdered, they renamed Quintillis to Julius, and then bippity-boppity-bacon you hava July.</p>
<p>So anyway, that&#8217;s how I began to call myself the Roman god of war. Don&#8217;t make me smite you.</p>
<img src="http://feeds.feedburner.com/~r/realjenius/~4/PZKkep45gTA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.realjenius.com/2010/03/13/the-ides-of-march/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.realjenius.com/2010/03/13/the-ides-of-march/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</feedburner:origLink></item>
		<item>
		<title>Check Out the Play Framework</title>
		<link>http://feedproxy.google.com/~r/realjenius/~3/USf8kExtFjU/</link>
		<comments>http://www.realjenius.com/2010/03/01/check-out-the-play-framework/#comments</comments>
		<pubDate>Mon, 01 Mar 2010 16:54:10 +0000</pubDate>
		<dc:creator>R.J.</dc:creator>
				<category><![CDATA[Journal]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Play Framework]]></category>
		<category><![CDATA[Scala]]></category>

		<guid isPermaLink="false">http://www.realjenius.com/?p=454</guid>
		<description><![CDATA[I&#8217;ve spent a lot of time recently investigating a variety of languages other than Java, such as JRuby and Scala, and truly believe from these experiences that traditional Java MVC web frameworks are inherently flawed in design and implementation. The effort involved in implementing on a framework like Struts or Spring MVC is astronomical, especially [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-455" title="play" src="http://www.realjenius.com/wp-content/uploads/2010/03/play.png" alt="play" width="177" height="64" /><br />
I&#8217;ve spent a lot of time recently investigating a variety of languages other than Java, such as <a href="http://jruby.org">JRuby</a> and <a href="http://scala-lang.org">Scala</a>, and truly believe from these experiences that traditional Java MVC web frameworks are inherently flawed in design and implementation. The effort involved in implementing on a framework like Struts or Spring MVC is astronomical, especially if you are going to implement things &#8220;the right way&#8221;.</p>
<p>It&#8217;s amazing to me how much these platforms push &#8220;hello, world&#8221; examples that are simply not realistic web applications. After trying these short examples, developers turn around and start trying to implement a complete application, and this simple example balloons into a mess of code, and that&#8217;s without any real functionality yet in the application. A co-worker of mine is a fan of saying &#8220;[These frameworks] make the simple things trivial, and the hard things impossible&#8221;.</p>
<p>Historically, I&#8217;ve been known to say &#8220;If you are doing web-development in Java, use <a href="http://wicket.apache.org">Wicket</a>&#8220;; this was based on the fact that to my experience Wicket took the most advantages from the strongly-typed, and strongly IDE-supported, Java language, as opposed to trying to hide them behind anemic and broken templating languages that have horrid editors and basically trade one problem for another.</p>
<p>Recently, however, I spent some time doing some significant development with the <a href="http://playframework.org">Play Framework</a>. I have to say that I think the Play Framework has eclipsed my Wicket fever. That&#8217;s not to say that I don&#8217;t still think Wicket is very powerful, but I have been particularly impressed with the feedback loop provided by Play. It has, without a doubt, the most direct code-test-cycle I have seen in any platform for Java (it approaches the instant feedback of Rails), and also has the distinct advantage of being stateless out-of-the-box (something Wicket is definitely not).</p>
<p>Play manages this feedback loop problem in a rather novel way &#8211; embedded in the framework is the <a href="http://www.eclipse.org">Eclipse </a>compiler for Java (ECJ). This means that when you&#8217;re coding for the play framework, you&#8217;re not sending it your class files, but rather your source files. This allows Play to recompile code in a running instance on the fly &#8211; I literally only restarted my application a handful of times while I was coding over <em>the course of several days</em>. It also integrates seamlessly with IDEs, and ships with an embedded HTTP runtime (no deployment is necessary during development).</p>
<p>There are a number of other benefits Play can provide by working with source files instead of class files. Much like Rails ability to add functionality to your application at runtime, Play can (and does) pre-process certain Java classes to add functionality.</p>
<p>I was further heartened to see that the next release of Play is meant to fully support Scala, which would allow for other modern language features to be used with this highly interactive framework.</p>
<p>It&#8217;s hard to describe all of the neat features Play provides in a few hundred words, but I would highly recommend <a href="http://www.playframework.org">you check it out</a> &#8211; they have a 10 minute screencast they sells it better than I can. While I&#8217;m still convinced Java (as a language) will be surpassed for an overwhelming majority of the web-development as the language continues to stagnate, this is a compelling framework for the Java platform as a whole, even if Java isn&#8217;t your language of choice.</p>
<img src="http://feeds.feedburner.com/~r/realjenius/~4/USf8kExtFjU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.realjenius.com/2010/03/01/check-out-the-play-framework/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.realjenius.com/2010/03/01/check-out-the-play-framework/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</feedburner:origLink></item>
		<item>
		<title>JRuby “IO.foreach” Performance</title>
		<link>http://feedproxy.google.com/~r/realjenius/~3/hHoszWOxYNs/</link>
		<comments>http://www.realjenius.com/2009/11/03/jruby-io-foreach-performance/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 04:19:55 +0000</pubDate>
		<dc:creator>R.J.</dc:creator>
				<category><![CDATA[Article]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JRuby]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Profiling]]></category>

		<guid isPermaLink="false">http://www.realjenius.com/?p=405</guid>
		<description><![CDATA[I&#8217;ve been spending some time dipping my toes in patch contribution for JRuby recently. I started with a few easy, isolated, spec issues, and have since been working my way into more entrenched problems. The past few weeks I spent a good bit of time toying with solutions to JRUBY-2810: &#8220;IO foreach performance is slower [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.realjenius.com/wp-content/uploads/2009/09/logo.png" alt="Ruby Logo" title="Ruby Logo" width="99" height="119" class="alignright size-full wp-image-181" />I&#8217;ve been spending some time dipping my toes in patch contribution for JRuby recently. I started with a few easy, isolated, spec issues, and have since been working my way into more entrenched problems. The past few weeks I spent a good bit of time toying with solutions to <a href="http://jira.codehaus.org/browse/JRUBY-2810">JRUBY-2810</a>: &#8220;IO foreach performance is slower than MRI&#8221;. The exercise was interesting enough, that I thought it might be worth posting here. This isn&#8217;t meant to be a study of the JRuby code in particular, but more-so in the thought process of diagnosing a performance problem in foreign code.<span id="more-405"></span></p>
<h3>Proof is in the Benchmark</h3>
<p>Performance is a very multi-faceted thing &#8211; there are so many measuring sticks (CPU, memory, I/O, startup time, scalability, &#8216;warm up&#8217; time, etc). This makes quantifying a performance problem hard.</p>
<p>Furthermore, improvements for most performance problems typically involves making some kind of trade-off (unless you&#8217;re just dealing with bad code). The goal is to trade-off a largely-available resource for a sparse one (cache more in memory to save the CPU, or use non-blocking IO to use more CPU rather than waiting on the disk, etc).</p>
<p>JRuby always has a few open, standing performance bugs. It&#8217;s the nature of the beast that it is compared to MRI (the &#8220;reference&#8221; implementation), and anywhere it performs less favorably is going to be considered a bug (fast enough be damned). The performance measurement is up to the beholder, but CPU timings are generally the most popular.</p>
<p><a href="http://jira.codehaus.org/browse/JRUBY-2810">JRUBY-2810</a> is an interesting case. IO line looping was proving to be slower than MRI Ruby; in some cases <strong>much</strong> slower. In this particular case, CPU was the closely-watched resource.</p>
<p>The first step I took to analyzing the problem was reproducing it. With Ruby this is usually pretty easy, as arbitrary scripts can just be picked up and executed, as opposed to Java, where all too often you have to build a special harness or test class just to expose the problem. Scripts are very natural for this, and in this particular case, the user had already provided one in the benchmarks folder that ships with the JRuby source.</p>
<p>Having run that file, I quickly saw the performance discrepancy reported in the bug. At this point in my experimenting, I was running inside an Ubuntu VM through VirtualBox on my Windows machine, so I think that level of indirection exasperated the numbers, so I checked my Macbook Pro as well. In both cases, the differences were significant: on Ubuntu, MRI Ruby was running the code in under <strong>10 seconds</strong>, where JRuby was taking <strong>30 seconds to a minute</strong>; the Macbook was still twice as slow in JRuby (<strong>12 seconds</strong>) as compared to MRI (<strong>6.5 seconds</strong>).</p>
<p>When faced with a big gap like this, I generally start by profiling. Running the entire process under analysis will generally grab some hotspots that need some tuning. I&#8217;m enamored with how low the barrier to entry on profiling has become on modern Java VMs (something that I think is actually a big selling point for JRuby as compared to other Ruby implementations; but I digress). To do my work here, I simply ran the benchmark, and popped open VisualVM. From there, I simply connected and performed CPU profiling (which automagically connects and injects profiling code into the running system).</p>
<p>In this particular case, the first problem was quickly uncovered:</p>
<div id="attachment_419" class="wp-caption aligncenter" style="width: 565px"><img class="size-full wp-image-419" title="jruby-2810-profile" src="http://www.realjenius.com/wp-content/uploads/2009/10/jruby-2810-profile.png" alt="Great Odin's Raven!" width="555" height="168" /><p class="wp-caption-text">Great Odin&#39;s Raven!</p></div>
<p>Clearly, a very large amount of time is being spent in ByteList.grow. I felt fairly fortunate at this point, as rarely is it this straightforward; having a performance problem reported with this singular of a hot-spot. When nearly 80% of the processing time is spent in a single method, it brings up several questions: What is ByteList? Why does IO.foreach use it? Why must it keeping &#8216;growing&#8217;? Did I leave the iron on? To answer these questions (most of them, anyway) you simply have to get your feet wet in the code.</p>
<h3>Coding for Crackers</h3>
<p>At its heart, IO.foreach (and the close counterpart, each/each_line) is simply a line iterator that hands off each line of text off to a receiving block &#8211; there are a number of caveats and subtleties built into that idea, but at its core, it allows developers to write code like this:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">io = <span style="color:#008000; font-style:italic;">#...</span><br />
io.<span style="color:#9900CC;">each_line</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>line<span style="color:#006600; font-weight:bold;">|</span><br />
<span style="color:#CC0066; font-weight:bold;">puts</span> line<br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Deceptively, simple &#8211; isn&#8217;t it? It turns out that a lot of wrangling has to occur to make this so simple &#8211; much of it having to do with how files are encoded, and the variety of line separators that may exist. Thankfully, the good folks at JRuby have cemented this in the code fairly decently &#8211; for my part, I mostly had to draw boxes around the complex encoding and line termination algorithms, and focus on the loop and data-reading itself. Most of this was occurring in a single method (for the code-eager, this was in RubyIO#getline and its derivatives). This method is used in a number of scenarios: the traditional looping algorithms, the 1.9 inverted enumerator stuff (handing the ownership of &#8220;next&#8221; off to the caller) as well as basic calls to &#8216;IO.gets&#8217;. Internally, each call to getline allocates a new ByteList and copies data from the input stream into it.</p>
<p>This is where the high-CPU numbers started. ByteList is simply an easier-to-use wrapper around a byte[]. It backs several JRuby data structures &#8211; the most notable probably being RubyString (the Java peer for String objects in JRuby). In fact, the ByteList allocated in this routine is eventually given to a String object, and returned at the end of the call. The &#8216;grow&#8217; method on ByteList (the offending code-point) is the automatic capacity increase mechanism, and does this via an an array-allocation and copy (much like ArrayList); this method uses a fairly standard 1.5x grow factor.</p>
<p>It&#8217;s easy to see how ByteList would be central to the benchmark since it represents the primary data structure holding the bytes from the input source, but it seemed suspicious that &#8216;grow&#8217; was the offending hotspot. I would expect it to be one of the copy methods, like &#8216;append&#8217;, which is really where the algorithm <em>should</em> be spending its time (that, and &#8216;read&#8217; from the input source). To understand why &#8216;grow&#8217; was so cranky, I had to look more closely at the code I was invoking: the benchmark.</p>
<h3>Understanding the Benchmark</h3>
<p>The original benchmark used to test the &#8216;foreach&#8217; performance in JRuby when 2810 was first opened performed something like 10,000 line iterations on a file with relatively short lines. Halfway through the life of this bug, those values were adjusted in this original benchmark in a way that exposed a short-coming in the JRuby line-read routine &#8211; by generating only 10 lines that were very, very long instead.</p>
<p>For any Ruby implementation, reading a file with particularly long lines using foreach is prohibitively expensive, as the entire line has to be read into memory as a single string object that is then shared with the code block. Normally, you wouldn&#8217;t want to read data this way if you knew that the file was structured so wide, and should probably consider a streamed-read instead. That being said, MRI Ruby performed much more admirably in this scenario, so it was something to be analyzed.</p>
<p>The root of the problem was this: JRuby was starting with an empty ByteList, and was then creating subsequently larger byte[]s indirectly (via ByteList.grow) &#8211; the 1.5x factor wasn&#8217;t enough, as the chunks were being read 4k at a time, and these files were significantly wider than 4k. For that reason alone, the ByteList was having to grow a number of times for each line, and when we&#8217;re talking about a byte[] several kilobytes in size, array copies are simply going to be expensive &#8211; all those together combine to make this an unfriendly performance proposition.</p>
<p>As I mentioned previously, the benchmark used to be a very different performance model. I decided at this point it was good to split the benchmark so that both could be run side by side, and I could see both the &#8216;wide&#8217; scenario and the &#8216;tall&#8217; scenario at the same time. It turned out via profiling that the tall file was experiencing pains from &#8216;grow&#8217;, but not nearly so badly. Even at 10,000 lines the amount of adverse memory allocation and churn was much smaller, as a single 4k allocation on each line was more than sufficient.</p>
<p>For reference, here is what the &#8216;tall&#8217; benchmark looks like:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'benchmark'</span><br />
<br />
MAX &nbsp;= <span style="color:#006666;">1000</span><br />
BLOCKSIZE = <span style="color:#006666;">16</span> <span style="color:#006600; font-weight:bold;">*</span> <span style="color:#006666;">1024</span><br />
LINE_SIZE = <span style="color:#006666;">10</span><br />
LINES = <span style="color:#006666;">10000</span><br />
FILE = <span style="color:#996600;">'io_test_bench_file.txt'</span><br />
<br />
<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>FILE, <span style="color:#996600;">'w'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>fh<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; LINES.<span style="color:#9900CC;">times</span><span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>n<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; LINE_SIZE.<span style="color:#9900CC;">times</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; fh.<span style="color:#CC0066; font-weight:bold;">print</span> <span style="color:#996600;">&quot;This is time: #{t} &quot;</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; fh.<span style="color:#CC0066; font-weight:bold;">puts</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span><br />
<span style="color:#006600; font-weight:bold;">&#125;</span><br />
<br />
stat = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">stat</span><span style="color:#006600; font-weight:bold;">&#40;</span>FILE<span style="color:#006600; font-weight:bold;">&#41;</span><br />
<span style="color:#006600; font-weight:bold;">&#40;</span>ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#006666;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_i</span>.<span style="color:#9900CC;">times</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; <span style="color:#CC00FF; font-weight:bold;">Benchmark</span>.<span style="color:#9900CC;">bm</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">30</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>x<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; x.<span style="color:#9900CC;">report</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'IO.foreach(file)'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; MAX.<span style="color:#9900CC;">times</span><span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#CC00FF; font-weight:bold;">IO</span>.<span style="color:#9900CC;">foreach</span><span style="color:#006600; font-weight:bold;">&#40;</span>FILE<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span>FILE<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exists</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>FILE<span style="color:#006600; font-weight:bold;">&#41;</span></div></td></tr></tbody></table></div>
<p>The only difference in the wide benchmark is the tuning parameters:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">LINE_SIZE = <span style="color:#006666;">10000</span><br />
LINES = <span style="color:#006666;">10</span></div></td></tr></tbody></table></div>
<p>So <strong>&#8216;tall&#8217;</strong> can be read as <strong>&#8217;10000 lines, 10 sentences long&#8217;</strong>, and <strong>&#8216;wide&#8217;</strong> can be read as <strong>&#8217;10 lines, 10000 sentences long&#8217;</strong>.</p>
<p>Also for reference, here is what it looks like to run a benchmark using this framework &#8211; 5 iterations are run (as defined in the file), and the various aspects of CPU usage are measured. Generally, the most important number is the &#8216;real&#8217; column when measuring performance between Ruby and JRuby, as the two report user/system CPU usage very differently.</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># Running with JRuby</span><br />
realjenius:~<span style="color: #000000; font-weight: bold;">/</span>projects<span style="color: #000000; font-weight: bold;">/</span>jruby<span style="color: #000000; font-weight: bold;">/</span>bench$ jruby <span style="color: #660033;">--server</span> bench_io_foreach_wide.rb<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;user &nbsp; &nbsp; system &nbsp; &nbsp; &nbsp;total &nbsp; &nbsp; &nbsp; &nbsp; real<br />
IO.foreach<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">file</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000;">63.970000</span> &nbsp; <span style="color: #000000;">0.000000</span> &nbsp;<span style="color: #000000;">63.970000</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span> <span style="color: #000000;">63.764000</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;user &nbsp; &nbsp; system &nbsp; &nbsp; &nbsp;total &nbsp; &nbsp; &nbsp; &nbsp; real<br />
IO.foreach<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">file</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000;">30.212000</span> &nbsp; <span style="color: #000000;">0.000000</span> &nbsp;<span style="color: #000000;">30.212000</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span> <span style="color: #000000;">30.212000</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;user &nbsp; &nbsp; system &nbsp; &nbsp; &nbsp;total &nbsp; &nbsp; &nbsp; &nbsp; real<br />
IO.foreach<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">file</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000;">30.973000</span> &nbsp; <span style="color: #000000;">0.000000</span> &nbsp;<span style="color: #000000;">30.973000</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span> <span style="color: #000000;">30.973000</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;user &nbsp; &nbsp; system &nbsp; &nbsp; &nbsp;total &nbsp; &nbsp; &nbsp; &nbsp; real<br />
IO.foreach<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">file</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000;">30.768000</span> &nbsp; <span style="color: #000000;">0.000000</span> &nbsp;<span style="color: #000000;">30.768000</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span> <span style="color: #000000;">30.767000</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;user &nbsp; &nbsp; system &nbsp; &nbsp; &nbsp;total &nbsp; &nbsp; &nbsp; &nbsp; real<br />
IO.foreach<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">file</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000;">32.813000</span> &nbsp; <span style="color: #000000;">0.000000</span> &nbsp;<span style="color: #000000;">32.813000</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span> <span style="color: #000000;">32.813000</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<br />
<span style="color: #666666; font-style: italic;">#Running with MRI Ruby</span><br />
realjenius:~<span style="color: #000000; font-weight: bold;">/</span>projects<span style="color: #000000; font-weight: bold;">/</span>jruby<span style="color: #000000; font-weight: bold;">/</span>bench$ ruby bench_io_foreach_wide.rb<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;user &nbsp; &nbsp; system &nbsp; &nbsp; &nbsp;total &nbsp; &nbsp; &nbsp; &nbsp; real<br />
IO.foreach<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">file</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">0.200000</span> &nbsp; <span style="color: #000000;">9.500000</span> &nbsp; <span style="color: #000000;">9.700000</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span> &nbsp;<span style="color: #000000;">9.982682</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;user &nbsp; &nbsp; system &nbsp; &nbsp; &nbsp;total &nbsp; &nbsp; &nbsp; &nbsp; real<br />
IO.foreach<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">file</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">0.230000</span> &nbsp; <span style="color: #000000;">9.430000</span> &nbsp; <span style="color: #000000;">9.660000</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span> &nbsp;<span style="color: #000000;">9.889992</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;user &nbsp; &nbsp; system &nbsp; &nbsp; &nbsp;total &nbsp; &nbsp; &nbsp; &nbsp; real<br />
IO.foreach<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">file</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">0.560000</span> &nbsp; <span style="color: #000000;">9.340000</span> &nbsp; <span style="color: #000000;">9.900000</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span> <span style="color: #000000;">10.232858</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;user &nbsp; &nbsp; system &nbsp; &nbsp; &nbsp;total &nbsp; &nbsp; &nbsp; &nbsp; real<br />
IO.foreach<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">file</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">0.520000</span> &nbsp; <span style="color: #000000;">9.270000</span> &nbsp; <span style="color: #000000;">9.790000</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span> <span style="color: #000000;">10.054699</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;user &nbsp; &nbsp; system &nbsp; &nbsp; &nbsp;total &nbsp; &nbsp; &nbsp; &nbsp; real<br />
IO.foreach<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">file</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">0.600000</span> &nbsp; <span style="color: #000000;">9.350000</span> &nbsp; <span style="color: #000000;">9.950000</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span> <span style="color: #000000;">10.348258</span><span style="color: #7a0874; font-weight: bold;">&#41;</span></div></td></tr></tbody></table></div>
<p>After splitting the benchmarks, here is a breakdown of my two configurations:</p>
<table class="infoTable">
<tr>
<th>Environment</th>
<th>&#8216;wide&#8217; MRI</th>
<th>&#8216;wide&#8217; JRuby</th>
<th>&#8216;tall&#8217; MRI</th>
<th>&#8216;tall&#8217; JRuby</th>
</tr>
<tr>
<td>Ubuntu VM</td>
<td>10 seconds</td>
<td>30 seconds</td>
<td>6 seconds</td>
<td>11 seconds</td>
</tr>
<tr>
<td>Macbook Pro</td>
<td>6.5 seconds</td>
<td>12 seconds</td>
<td>8 seconds</td>
<td>15 seconds</td>
</tr>
</table>
<p>Keep in mind I&#8217;m just rounding here; not really trying to be exact for this blog post. Check the bugs for more exact numbers.</p>
<h3>A Solution Lurks</h3>
<p>So, we have performance problems on tall files, and a whole lot more performance problems on wide files, particularly depending on the environment. Because of the environmental discrepencies, I spent some more time comparing the two test environments. It turned out that the Macbook Pro was simply working with a more resource-rich environment, and as such wasn&#8217;t hitting the wall as badly when allocating the new immense byte[]s. The implementation in JRuby was not degrading as well on older (or more restricted) hardware as MRI.</p>
<p><em>(It&#8217;s probably good to note here the value of testing in multiple environments, and from multiple angles)</em></p>
<p>My first pass at a solution to this problem was to consider a byte[] loan algorithm. Basically, at the start of foreach, I effectively allocated a single ByteList (byte[] container), and for each iteration of the loop, I just reused the same ByteList &#8212; eventually the byte[] being used internally would be sufficient to contain the data for each line, and would not need to grow any more (yay recycling!).</p>
<p>I encapsulated most of this &#8216;unsafe&#8217; byte[] wrangling and copying into a small inner class called ByteListCache &#8211; at the start of the loop, the ByteListCache is created, and then it is shared for each iteration, being passed down into &#8216;getline&#8217; as an optional parameter, the side effect being that the first call to &#8216;getline&#8217; manually allocates a large byte[] (just like it did pre-patch), and each subsequent call can simply reuse the previously allocated byte[] that is already quite large. If the need arises to grow it more, it can, but it becomes increasingly less likely with each line.</p>
<p>Once the iteration is completed, the ByteListCache is dropped out of scope, ready for garbage collection. The number of calls to &#8216;grow&#8217; drops dramatically with this implementation, and so did the impacts to the performance:</p>
<table class="infoTable">
<tr>
<th>Environment</th>
<th>&#8216;wide&#8217; MRI</th>
<th>&#8216;wide&#8217; JRuby</th>
<th>&#8216;wide&#8217; JRuby (v1)
<th>&#8216;tall&#8217; MRI</th>
<th>&#8216;tall&#8217; JRuby</th>
<th>&#8216;tall&#8217; JRuby (v1)</th>
</tr>
<tr>
<td>Ubuntu VM</td>
<td>10 seconds</td>
<td>30 seconds</td>
<td><strong>7 seconds</strong></td>
<td>6 seconds</td>
<td>11 seconds</td>
<td><strong>8 seconds</strong></td>
</tr>
<tr>
<td>Macbook Pro</td>
<td>6.5 seconds</td>
<td>12 seconds</td>
<td><strong>7 seconds</strong></td>
<td>8 seconds</td>
<td>15 seconds</td>
<td><strong>9 seconds</strong></td>
</tr>
</table>
<p>Unfortunately, they were only this fast because the implementation was now <strong>thoroughly broken</strong>.</p>
<h3>Stop Breaking Crap</h3>
<p>Okay, so I had amazing performance numbers. Except. Now over 50 ruby spec tests were failing. Oh yeah, that might be a problem. Needless to say the problem was obvious the minute I realized what I had done (I actually woke up at 6:00am realizing this, which if you know me, is a bad sign). Remember how earlier I said that the ByteList was used as a backing store for the String? Well, at the time I implemented this, that point had eluded me. I was (accidentally) creating strings with my shared bytelist, so you can probably see where that would end up creating some significant issues with data integrity.</p>
<p>To fix this, the solution was simple &#8211; create a perfectly-sized ByteList at the end of the line-read the exact size necessary for the String, copying into it from the shared bytelist, and then passing it in to the String constructor. Obviously this cut into my performance numbers by a percentage on each, but it also fixed the data corruption, which is nice.</p>
<table class="infoTable">
<tr>
<th>Environment</th>
<th>&#8216;wide&#8217; MRI</th>
<th>&#8216;wide&#8217; JRuby</th>
<th>&#8216;wide&#8217; JRuby (v2)
<th>&#8216;tall&#8217; MRI</th>
<th>&#8216;tall&#8217; JRuby</th>
<th>&#8216;tall&#8217; JRuby (v2)</th>
</tr>
<tr>
<td>Ubuntu VM</td>
<td>10 seconds</td>
<td>30 seconds</td>
<td><strong>14 seconds</strong></td>
<td>6 seconds</td>
<td>11 seconds</td>
<td><strong>10 seconds</strong></td>
</tr>
<tr>
<td>Macbook Pro</td>
<td>6.5 seconds</td>
<td>12 seconds</td>
<td><strong>10 seconds</strong></td>
<td>8 seconds</td>
<td>15 seconds</td>
<td><strong>13 seconds</strong></td>
</tr>
</table>
<p>The lesson learned here, obviously, is that you need to run a variety of tests (a full suite of specs if you have them) when considering bug fixes. For JRuby, that means (at a minimum) running the specs, which is easy with the Ant script:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ant spec <span style="color: #666666; font-style: italic;"># or ant spec-short to just run interpreted tests</span></div></td></tr></tbody></table></div>
<h3>A Word on Limited Application</h3>
<p>Note that I isolated the use of this construct to the foreach and each_line algorithms, as these had deterministic, single-threaded behavior, and would benefit from the overhead of dealing with this additional object. The new Ruby 1.9 enumerator stuff does not use it, as there is no guarantee of single-threaded usage of the enumerator, so we can&#8217;t reuse a single byte list. Similarly, individual calls to &#8216;gets&#8217; do not currently use it, for the same general reason.</p>
<p>Changes could be made to make this byte[] re-use more long-lasting/global &#8211; but the changes required felt a little too overwhelming for a first pass, even if they did offer potentially larger benefits.</p>
<h3>Rinse and Repeat</h3>
<p>Now that I had two tests, and I had seen some improvements (but not quite in the range of MRI), it was time to revisit. Re-running the benchmarks, it was fascinating to see a new prime offender &#8211; incrementlineno. It turns out that a global variable was having to be updated through a very indirect routine that contains a fixnum representing the line number in the file, and all of this heavy-weight variable updating (going through call-sites and arg file lookups) was very expensive in comparison to the rest of the iteration.</p>
<p>At this point, I&#8217;d spend a lot of time explaining how I improved the performance of this little gem, however the truth be told once I hit this, I simply had to inform the powers-that-be, and back up. You see, I couldn&#8217;t figure out (for the life of me) why this method was doing what it was doing; why it was so important for this line number to be set. This is one of the perils that I have verbally discussed with folks about consuming foreign code-bases. You can&#8217;t assume secret sauce is a bad thing &#8211; I had to assume it is there for a reason, even if I don&#8217;t know what it is.</p>
<p>It turns out, the JRuby folks didn&#8217;t know the reason either. Well, that&#8217;s not exactly true; it didn&#8217;t take long for Charles Nutter to figure out why it was there, but it was clear it was only for rare file execution scenarios, and not appropriate for the more general looping scenarios I was debugging. To follow his efforts on how he optimized that code path, you can reference his commit here: <a href="http://jira.codehaus.org/browse/JRUBY-4117">JRUBY-4117</a>.</p>
<p>After his optimizations, the numbers boosted again:</p>
<table class="infoTable">
<tr>
<th>Environment</th>
<th>&#8216;wide&#8217; MRI</th>
<th>&#8216;wide&#8217; JRuby</th>
<th>&#8216;wide&#8217; JRuby (v3)
<th>&#8216;tall&#8217; MRI</th>
<th>&#8216;tall&#8217; JRuby</th>
<th>&#8216;tall&#8217; JRuby (v3)</th>
</tr>
<tr>
<td>Ubuntu VM</td>
<td>10 seconds</td>
<td>30 seconds</td>
<td><strong>11 seconds</strong></td>
<td>6 seconds</td>
<td>11 seconds</td>
<td><strong>8.5 seconds</strong></td>
</tr>
<tr>
<td>Macbook Pro</td>
<td>6.5 seconds</td>
<td>12 seconds</td>
<td><strong>6.3 seconds</strong></td>
<td>8 seconds</td>
<td>15 seconds</td>
<td><strong>9.5 seconds</strong></td>
</tr>
</table>
<h3>Summary</h3>
<p>I think it&#8217;s fascinating how varied the numbers are depending on the platform. This is a complicated benchmark, and as Charles Nutter mentioned to me, one problem we&#8217;ll continue to face is that we have no control element in this benchmark. You can get consistency through repetition, but there are simply too many variables to predict exactly what the outcome will be on any given platform. I find it interesting how well the Macbook handles the wide files compared to the Ubuntu VM, which just dies a slow death in comparison &#8211; this has to be a side-effect of resource starvation in the VM; but whatever the case, it&#8217;s an interesting dichotomy.</p>
<p>On average, the new numbers are much more competitive with MRI, even if they don&#8217;t beat it in most cases. As I learned from working with others on this bug, your mileage may vary significantly, but it&#8217;s clear from the implementation that we&#8217;re causing a lot less resource churn for very little cost (the trade off here is retained memory), and that&#8217;s generally a good sign things are going in the right direction. Certainly, profiling has shown that the effort is much more focused on reading from the input channel.</p>
<p>That being said, I&#8217;m sure there is more performance to be found &#8211; MRI is just a hop-skip-and-jump away!</p>
<img src="http://feeds.feedburner.com/~r/realjenius/~4/hHoszWOxYNs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.realjenius.com/2009/11/03/jruby-io-foreach-performance/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.realjenius.com/2009/11/03/jruby-io-foreach-performance/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</feedburner:origLink></item>
		<item>
		<title>Fistful of Awesome: IntelliJ Open-Sourced</title>
		<link>http://feedproxy.google.com/~r/realjenius/~3/_-U7YueeI2o/</link>
		<comments>http://www.realjenius.com/2009/10/15/fistful-of-awesome-intellij-open-sourced/#comments</comments>
		<pubDate>Thu, 15 Oct 2009 20:39:00 +0000</pubDate>
		<dc:creator>R.J.</dc:creator>
				<category><![CDATA[Journal]]></category>

		<guid isPermaLink="false">http://www.realjenius.com/?p=401</guid>
		<description><![CDATA[In a surprising move, the JetBrains team has decided to open-source the JavaSE portions of IntelliJ IDEA 9.0 and beyond under an Apache 2.0 license. They will begin offering two products, a community edition, and an ultimate edition: Starting with the upcoming version 9.0, IntelliJ IDEA will be offered in two editions: Community Edition and Ultimate [...]]]></description>
			<content:encoded><![CDATA[<p>In a surprising move, the JetBrains team <a href="http://blogs.jetbrains.com/idea/2009/10/intellij-idea-open-sourced/">has decided to open-source</a> the JavaSE portions of IntelliJ IDEA 9.0 and beyond under an Apache 2.0 license. They will begin offering two products, a community edition, and an ultimate edition:</p>
<blockquote><p>Starting with the upcoming version 9.0, <a style="font-family: 'trebuchet ms', verdana, tahoma, arial, sans-serif; font-size: 1em; line-height: 1.5em; color: #043dbc; text-decoration: none; border-bottom-style: solid; border-bottom-color: #3d7dc7; padding: 0pt; margin: 0pt; border: 0px initial initial;" rel="nofollow" href="http://www.jetbrains.com/idea/nextversion/index.html?utm_source=IDEA_BLOG&amp;utm_media=Anouncement&amp;utm_campaign=IDEA9_CE">IntelliJ IDEA</a> will be offered in two editions: Community Edition and Ultimate Edition. The Community Edition focuses on Java SE technologies, Groovy and Scala development. It’s free of charge and open-sourced under the Apache 2.0 license. The Ultimate edition with full Java EE technology stack remains our standard commercial offering. See the <a style="font-family: 'trebuchet ms', verdana, tahoma, arial, sans-serif; font-size: 1em; line-height: 1.5em; color: #043dbc; text-decoration: none; border-bottom-style: solid; border-bottom-color: #3d7dc7; padding: 0pt; margin: 0pt; border: 0px initial initial;" rel="nofollow" href="http://www.jetbrains.com/idea/nextversion/editions_comparison_matrix.html?utm_source=IDEA_BLOG&amp;utm_media=Anouncement&amp;utm_campaign=IDEA9_CE">feature comparison matrix</a> for the differences.</p></blockquote>
<p>Very cool news! The impact in competition for other IDEs (namely <a href="http://www.eclipse.org">Eclipse</a> and <a href="http://www.netbeans.org">NetBeans</a>) remains to be seen, but this certainly brings another aggressive (and already well-liked competitor) to a broader market.</p>
<img src="http://feeds.feedburner.com/~r/realjenius/~4/_-U7YueeI2o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.realjenius.com/2009/10/15/fistful-of-awesome-intellij-open-sourced/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.realjenius.com/2009/10/15/fistful-of-awesome-intellij-open-sourced/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</feedburner:origLink></item>
		<item>
		<title>WordPress 2.9 Beta Testing Call to Arms</title>
		<link>http://feedproxy.google.com/~r/realjenius/~3/sREvADjRPdA/</link>
		<comments>http://www.realjenius.com/2009/10/13/wordpress-2-9-beta-testing-call-to-arms/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 01:44:23 +0000</pubDate>
		<dc:creator>R.J.</dc:creator>
				<category><![CDATA[Journal]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[Realjenius.com]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.realjenius.com/?p=393</guid>
		<description><![CDATA[&#8220;For a limited time only &#8211; you can beta-test WordPress 2.9 from the comfort of your own installation!&#8221; In the &#8220;another reason I like WordPress better for blogging&#8221; category, the folks over at WordPress.com have published a detailed article on how WordPress users can get involved in the beta-testing of WordPress 2.9 &#8211; the next [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-111" title="wordpress-logo-stacked-bg" src="http://www.realjenius.com/wp-content/uploads/2009/09/wordpress-logo-stacked-bg.png" alt="wordpress-logo-stacked-bg" width="176" height="145" /></p>
<p>&#8220;For a limited time only &#8211; you can beta-test WordPress 2.9 from the comfort of your own installation!&#8221;</p>
<p>In the &#8220;another reason I like WordPress better for blogging&#8221; category, the folks over at WordPress.com have published a detailed article on how WordPress users can <a href="http://wordpress.org/development/2009/10/getting-involved-with-the-2-9-beta-testing/">get involved in the beta-testing of WordPress 2.9</a> &#8211; the next major release. Included in the options for aspiring beta-testers is a plug-in that will automatically upgrade your site to the new version, and will keep you on the up-and-up.<span id="more-393"></span></p>
<blockquote><p>To make is as easy as possible for you to get a beta testing install up and running we have put together a small WordPress plugin which makes it really easy to convert a test install of the latest release version of WordPress into a beta test install of the next up and coming release.  The plugin is called <a style="text-decoration: none; color: #21759b; font-weight: normal; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #dfdfdf;" href="http://wordpress.org/extend/plugins/wordpress-beta-tester/">WordPress Beta Tester</a> and is available to download from WordPress Extend or can be installed using the built-in plugin installer.  Please make sure you to only install this plugin on a test site, as we don’t recommend running beta versions on your normal live sites in case anything goes wrong.  You can read more about the plugin in “<a style="text-decoration: none; color: #4ca6cf; font-weight: normal; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #dfdfdf;" href="http://westi.wordpress.com/2009/06/22/making-it-easy-to-be-a-wordpress-tester/">Making it easy to be a WordPress Tester</a>”</p></blockquote>
<p>I don&#8217;t want to suggest that Drupal doesn&#8217;t work for transparency in their development, or that they don&#8217;t encourage community participation; but certainly, they don&#8217;t package it up as nicely as the WordPress folks have right here. While I won&#8217;t be upgrading RealJenius.com until final drops (I did consider pulling a Picard maneuver and upgrading now), it&#8217;s nice to know that the option is there. The release schedule for 2.9 has been revisited in this entry as well.</p>
<blockquote><p>We are aiming to release the first beta version of 2.9 around the end of October, once we have put the finishing touches on the new features, and then we switch to full on beta testing mode and your help and feedback will be very much appreciated.  During the beta program will push out new builds for automated upgrades regularly and once we feel that a suitable level of stability has been achieves we will release a release candidate, and we hope to be able to make the final release 2.9 build available in either late November or early December.</p></blockquote>
<img src="http://feeds.feedburner.com/~r/realjenius/~4/sREvADjRPdA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.realjenius.com/2009/10/13/wordpress-2-9-beta-testing-call-to-arms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.realjenius.com/2009/10/13/wordpress-2-9-beta-testing-call-to-arms/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</feedburner:origLink></item>
		<item>
		<title>What Am I Downloading Today, Eclipse?</title>
		<link>http://feedproxy.google.com/~r/realjenius/~3/yumkuL21i1o/</link>
		<comments>http://www.realjenius.com/2009/10/08/what-am-i-downloading-today-eclipse/#comments</comments>
		<pubDate>Fri, 09 Oct 2009 00:41:43 +0000</pubDate>
		<dc:creator>R.J.</dc:creator>
				<category><![CDATA[Journal]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Updates]]></category>

		<guid isPermaLink="false">http://www.realjenius.com/?p=379</guid>
		<description><![CDATA[With the release of Eclipse 3.5, the plugin installation and update manager was completely revisited once again; the update process was reorganized, and the strengths of the p2 provisioning framework were surfaced. It&#8217;s nice to be able to hop in, download updates, and go. However, I think Eclipse, as a product, still has a way [...]]]></description>
			<content:encoded><![CDATA[<p>With the release of Eclipse 3.5, the plugin installation and update manager was completely revisited once again; the update process was reorganized, and the strengths of the p2 provisioning framework were surfaced. It&#8217;s nice to be able to hop in, download updates, and go.</p>
<p>However, I think Eclipse, as a product, still has a way to go.<span id="more-379"></span>There are a number of products I use everyday that frequently require or recommend updates and upgrades. Some good examples include:</p>
<ul>
<li><a href="http://www.mozilla.com/en-US/firefox/firefox.html">Mozilla Firefox</a></li>
<li><a href="http://www.android.com/">Android and Android Applications</a></li>
<li><a href="http://wordpress.org/">WordPress</a></li>
<li>Windows</li>
<li><a href="http://www.apple.com/macosx/">Mac OS X</a></li>
<li><a href="http://www.getsongbird.com/">Songbird</a></li>
<li><a href="http://eclipse.org/">Eclipse</a></li>
</ul>
<p>&#8230;and, of course, the list goes on. All of these apps have different ways to handle notifying and installing these upgrades.</p>
<p>Of course, both Windows and Mac OS X have built in update mechanisms, the former being the ever-controversial &#8220;Windows Update&#8221; tool, and the latter being Mac&#8217;s Apple Software Update (which has also recently <a href="http://arstechnica.com/apple/news/2009/09/apple-pushes-unwanted-enterprise-tool-to-windows-users.ars">been pissing people off</a>). Firefox and Songbird use their own update mechanism that&#8217;s part of the Gecko platform. Most Mac users are also probably aware of <a href="http://sparkle.andymatuschak.org/">Sparkle</a> (or at least have seen it in action), as many Mac software distributions (like <a href="http://www.barebones.com/products/TextWrangler/">TextWrangler</a>) use it as their update mechanism.</p>
<p>Your mileage may vary with the different implementations; some are more informative than others, and some are more reliable than others. But one thing can generally be said: each of these mechanisms tie in with documentation explaining what was updated, corrected, or otherwise tweaked. Some tools, like Sparkle, embed the update information in the notification dialog. Other tools, like the Firefox notifier, provide a link to the content that takes you to a rich and user-friendly webpage.</p>
<div id="attachment_384" class="wp-caption aligncenter" style="width: 444px"><img class="size-full wp-image-384" title="firefox" src="http://www.realjenius.com/wp-content/uploads/2009/10/firefox.png" alt="Firefox has thorough documentation online" width="434" height="370" /><p class="wp-caption-text">Firefox has thorough documentation online</p></div>
<p>Today when I came in to the office I decided to perform an update check in Eclipse, and was presented with a number of plug-ins that had newer replacements. At the time, I didn&#8217;t grab a screenshot, but here is an example from a brand-new download of 3.5, which has been since supplanted by 3.5.1:</p>
<div id="attachment_385" class="wp-caption aligncenter" style="width: 469px"><img class="size-full wp-image-385" title="eclipse_updates" src="http://www.realjenius.com/wp-content/uploads/2009/10/eclipse_updates.png" alt="So, is this a good thing?" width="459" height="497" /><p class="wp-caption-text">So, is this a good thing?</p></div>
<p>Unfortunately, this doesn&#8217;t show off the obscure list of plug-ins my installation did earlier today, but there is still plenty I can pick on. So, what&#8217;s wrong with this picture?</p>
<ul>
<li>I have no information on what is being changed or improved in this update.</li>
<li>The &#8216;Details&#8217; section is suspiciously empty.</li>
<li>The version number is unnecessarily cryptic for end users.</li>
<li>The &#8216;More&#8217; button simply gives me the description, copyright, and license for the plugin/feature being shown, which in this case is basically empty boxes.</li>
<li>The version number is cryptic for an end user.</li>
</ul>
<p>Now, as an Eclipse-enthusiast, I have no problem deciphering what is going on here (particularly not since I had to contrive this picture for the blog entry), however as an end-user product, this could use some work. More information could be provided, condensing what was actually improved or fixed in this release (any information at all would be nice).</p>
<p>I understand that Eclipse is a platform first, and a product second, however I think this is one area that could use improvement.</p>
<img src="http://feeds.feedburner.com/~r/realjenius/~4/yumkuL21i1o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.realjenius.com/2009/10/08/what-am-i-downloading-today-eclipse/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.realjenius.com/2009/10/08/what-am-i-downloading-today-eclipse/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</feedburner:origLink></item>
	</channel>
</rss><!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->
