<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog::Quibb &#187; jruby</title>
	<atom:link href="http://blog.quibb.org/tag/jruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.quibb.org</link>
	<description>Software development and more.</description>
	<lastBuildDate>Tue, 10 Aug 2010 14:11:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Nightly Benchmarks: Tracking Results with Codespeed</title>
		<link>http://blog.quibb.org/2010/07/nightly-benchmarks-tracking-results-with-codespeed/</link>
		<comments>http://blog.quibb.org/2010/07/nightly-benchmarks-tracking-results-with-codespeed/#comments</comments>
		<pubDate>Mon, 19 Jul 2010 14:16:54 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[benchmarks]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[jruby]]></category>

		<guid isPermaLink="false">http://blog.quibb.org/?p=204</guid>
		<description><![CDATA[Background Codespeed is a project for tracking performance. I discovered it when the PyPy project started using Codespeed to track performance. Since then development has been done to make its setup easier and provide more display options. Anyway, two posts ago I talked about running nightly benchmarks with Hudson. Then in the previous post I [...]]]></description>
			<content:encoded><![CDATA[<h2>Background</h2>
<p><a title="Codespeed" href="http://github.com/tobami/codespeed">Codespeed</a> is a project for tracking performance.  I discovered it when the <a title="PyPy" href="http://pypy.org/">PyPy</a> project started using Codespeed to track performance.  Since then development has been done to make its setup easier and provide more display options.</p>
<p>Anyway, two posts ago I talked about <a title="running nightly benchmarks with Hudson" href="http://blog.quibb.org/2010/04/nightly-benchmarks-setting-up-hudson/">running nightly benchmarks with Hudson</a>.  Then in the previous post I discussed <a title="passing parameters between builds in Hudson" href="http://blog.quibb.org/2010/04/passing-parameters-between-builds-in-hudson/">passing parameters between builds in Hudson</a>.  Both of these posts are worth reading before trying to setup Hudson with Codespeed.</p>
<h2>Codespeed Installation/Configuration</h2>
<h3>Django Quickstart</h3>
<p>Codespeed is built on Python and <a title="Django" href="http://www.djangoproject.com/">Django</a>.  Some basic knowledge of Django is needed in order to get everything up and running.  Don&#8217;t worry, it&#8217;s not that hard to learn the bit that is needed.  <a title="manage.py" href="http://docs.djangoproject.com/en/1.2/ref/django-admin/#ref-django-admin">manage.py</a> is all you need to know about to setup and view Codespeed.  There is information about <a title="deploying Django to a real web server" href="http://docs.djangoproject.com/en/1.2/howto/deployment/#howto-deployment-index">deploying Django to a real web server</a>, but I won&#8217;t be covering that here.</p>
<p>Here are the commands to get Django running:</p>
<p><a title="syncdb" href="http://docs.djangoproject.com/en/1.2/ref/django-admin/#syncdb"><strong>syncdb</strong></a></p>
<p>syncdb is used to initialize the database with the necessary tables.  It will also setup an admin account.  With the sqlite3 database selected, it will create the database file when this command is run.</p>
<p>The command is:</p>
<pre>python manage.py syncdb</pre>
<p><a title="runserver" href="http://docs.djangoproject.com/en/1.2/ref/django-admin/#runserver-port-or-ipaddr-port"><strong>runserver</strong></a></p>
<p>The next command is the runserver command.  This runs the built-in django server.  In the documentation they state you&#8217;re not supposed to use it in a production environment, so make sure to deploy to a production environment if you plan to host it on the Internet or high traffic network.</p>
<p>The command is:</p>
<pre>python manage.py runserver 0.0.0.0:9000</pre>
<p>By default the server will run on 127.0.0.1:8000.  Setting the IP to 0.0.0.0 allows connections from any computer.  This works well if you&#8217;re on a local area network and want to set it up on a VM over SSH, but still be able to access the web interface from your computer.  The port is the port for the server to run on.  To view Codespeed, point your browser at 127.0.0.1:9000 or the IP of the machine it&#8217;s on with the colon 9000.</p>
<p>Django has many <a title="Django settings" href="http://docs.djangoproject.com/en/1.2/ref/settings/#ref-settings">settings</a> that may or may not need to be tweaked for your environment.  They can be set through the <a title="speedcenter/settings.py" href="http://github.com/tobami/codespeed/blob/0.6.1/speedcenter/settings.py">speedcenter/settings.py</a> file.</p>
<h3>Codespeed Setup/Settings</h3>
<p>Now for setting up the actual Codespeed server.  First check it out using git.  The clone command is:</p>
<pre>git clone http://github.com/tobami/codespeed.git</pre>
<p>The settings file is <a title="speedcenter/codespeed/settings.py" href="http://github.com/tobami/codespeed/blob/0.6.1/speedcenter/codespeed/settings.py">speedcenter/codespeed/settings.py</a>.</p>
<p>Most of the default values will work fine.  They&#8217;re mostly for setting default values for various things in the interface.</p>
<p>One thing that does need to be configured is the environment.  Start by running the syncdb command and then run the server using runserver.  Now that the server is running, browse to the admin interface.  If you ran the server on port 9000, point your browser at http://127.0.0.1:9000/admin.  Login using the username and password you created during the syncdb call.  A Codespeed environment must be created manually.  The environment is the machine you&#8217;re running the benchmarks on.  After logging in, click Add next to the Environment label.  Fill in the various fields and remember the name of it.  Save it when you&#8217;re done.  The name will be used later when submitting benchmark data to Codespeed.</p>
<h2>Submitting Benchmarks</h2>
<p>This will pick up where my last <a title="Nightly Benchmarks: Setting up Hudson" href="http://blog.quibb.org/2010/04/nightly-benchmarks-setting-up-hudson/">tutorial</a> left off.  The benchmarks were running as a nightly job in Hudson.  Sending benchmark data to Codespeed will take a bit of programming.  I&#8217;m going to continue the example with <a title="JRuby" href="http://jruby.org/">JRuby</a>, so the benchmarks and submission process are written in Ruby.</p>
<p>In order to submit benchmarks information must be transferred from the JRuby build job to the Ruby Benchmarks job.  My last post discussed how to transfer parameters between jobs.  Using the <a title="Parameterized Trigger Plugin" href="http://wiki.hudson-ci.org/display/HUDSON/Parameterized+Trigger+Plugin">Parameterized Trigger Plugin</a> and passing extra parameters using a properties file will allow you to get all the necessary parameters to the benchmarks job.</p>
<p>The required information for submitting a benchmark result to Codespeed includes:</p>
<ul>
<li>commitid &#8211; The id of the commit, which could either be a git/mercurial hashcode or an svn revision number.</li>
<li>project &#8211; The name of the project to save.</li>
<li>executable &#8211; The name of the executable.</li>
<li>benchmark &#8211; The name of the benchmark.</li>
<li>environment &#8211; This is the name of the environment you created earlier.  It must be the name of an existing environment.</li>
<li>result_value &#8211; The runtime of the benchmark. You can configure what units a benchmark has through the admin interface. Default is seconds.</li>
</ul>
<p>This information can be included but is optional:</p>
<ul>
<li>std_dev &#8211; The standard deviation of the results of the benchmarks.</li>
<li>min</li>
<li>max</li>
<li>branch &#8211; The branch corresponding to this benchmark in the SCM repository.</li>
<li>result_date &#8211; The timestamp of the commit in the form &#8220;%Y-%m-%d %H:%M&#8221;</li>
</ul>
<p>The above information is passed to Codespeed through an encoded URL.  Have the URL point to http://127.0.0.1:9000/results/add/ and encode the parameters for sending.  For the JRuby benchmarks, the following parameters are sent from the JRuby job to the to the ruby benchmarks job.</p>
<pre>COMMIT_ID=$(git rev-parse HEAD)
COMMIT_TIME=$(git log -1 --pretty=\"format:%ad\")
RUBY_PATH=$WORKSPACE/bin/jruby
REPO_URL=git://github.com/jruby/jruby.git</pre>
<p>The other fields are derived from the benchmarks job itself.</p>
<p>Here is the source code for <a title="submission through Ruby rake file" href="http://github.com/qbproger/ruby-benchmark-suite/blob/master/rakelib/bench.rake">submission through Ruby</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">output = <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
canonical_name = doc<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;name&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#CC0066; font-weight:bold;">gsub</span> <span style="color:#996600;">'//'</span>, <span style="color:#996600;">'/'</span>
output<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'commitid'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = commitid
output<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'project'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = BASE_VM
output<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'branch'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = branch
output<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'executable'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = BASE_VM
output<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'benchmark'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">basename</span><span style="color:#006600; font-weight:bold;">&#40;</span>canonical_name<span style="color:#006600; font-weight:bold;">&#41;</span>
output<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'environment'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = environment
output<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'result_value'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = doc<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;mean&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
output<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'std_dev'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = doc<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;standard_deviation&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
output<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'result_date'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = commit_time
&nbsp;
res = <span style="color:#6666ff; font-weight:bold;">Net::HTTP</span>.<span style="color:#9900CC;">post_form</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">URI</span>.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{server}/result/add/&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>, output<span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#CC0066; font-weight:bold;">puts</span> res.<span style="color:#9900CC;">body</span></pre></div></div>

<p>It&#8217;s a good idea to always print out the response as it will contain debug information.  There is an example of <a title="save_single_result.py" href="http://github.com/tobami/codespeed/blob/0.6.1/tools/save_single_result.py">how to submit benchmarks to Codespeed using Python</a> in the Codespeed repository in the tools directory.</p>
<h2>Viewing Results</h2>
<p>After results are in the the Codespeed database, you can view the data through the web interface.  Direct a browser at http://127.0.0.1:9000.  The changes view shows the trend over the last revisions.  The timeline view allows you to see a graph of recent revisions, and the newly added comparison view will compare different executables running the same benchmark.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.quibb.org/2010/07/nightly-benchmarks-tracking-results-with-codespeed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nightly Benchmarks: Setting up Hudson</title>
		<link>http://blog.quibb.org/2010/04/nightly-benchmarks-setting-up-hudson/</link>
		<comments>http://blog.quibb.org/2010/04/nightly-benchmarks-setting-up-hudson/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 13:36:27 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[benchmarks]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[jruby]]></category>

		<guid isPermaLink="false">http://blog.quibb.org/?p=169</guid>
		<description><![CDATA[For some projects, finding out about performance regressions is important.  I&#8217;m going to write a two part series about setting up a nightly build machine and displaying the generated data.  This part is going to cover installation of Hudson, and getting the benchmarks running nightly. I decided to give Hudson a try because I had [...]]]></description>
			<content:encoded><![CDATA[<p>For some projects, finding out about performance regressions is important.  I&#8217;m going to write a two part series about setting up a nightly build machine and displaying the generated data.  This part is going to cover installation of <a title="Hudson" href="http://hudson-ci.org/">Hudson</a>, and getting the benchmarks running nightly.</p>
<p>I decided to give Hudson a try because I had heard good things about it.  Also after hearing coworkers complain about cruise control and cdash, I thought I&#8217;d try something new.  Since Hudson has pretty extensive documentation, I&#8217;ll walk you through setting up the JRuby project to build with Hudson and getting benchmarks running on it.</p>
<h2>Hudson Installation</h2>
<p>On Ubuntu it&#8217;s as simple as:</p>
<pre>sudo apt-get install hudson
</pre>
<p>While I didn&#8217;t install it on windows, the installation should require little more than installing <a title="Tomcat" href="http://tomcat.apache.org/">Tomcat</a> and then downloading the Hudson war file and put it in the web-apps directory.</p>
<p>After installation browsing to http://127.0.0.1:8080 should show the Hudson Dashboard.</p>
<h3>Hudson Configuration</h3>
<p>After Hudson installation is complete, it requires very little configuration before setting up your first project.  One thing that may be necessary is going to the plugins page and making sure your version control system is covered.  For setting up a continuous integration machine to build JRuby, the git plugin is necessary.</p>
<p>To install the Hudson Git Plugin, click <strong>Manage Hudson</strong> on the left hand side.  Then click <strong>Manage Plugins</strong> from the list in the middle of the screen.  Click the <strong>Available</strong> tab, and find the <span style="text-decoration: underline;">Hudson GIT plugin</span> in the list.  After it&#8217;s installed it will show up in the Installed tab.</p>
<p>After installing all the necessary plugins for your project go back to the Hudson Dashboard by clicking the Hudson logo, or the Back to Dashboard link.</p>
<h2>Setting up a Project to Build</h2>
<p>A good first step it to make sure the project will build on the given machine without being built through Hudson.  There may be some dependencies that got overlooked, and this is a good way to make sure everything is setup to build your project.</p>
<p>Now, click on the <strong>New Job</strong> link on the left hand side.  For the JRuby project, the <strong>Build a free-style software project</strong> is the type of project to setup.  I imagine that is the correct type of project to setup for most projects.</p>
<p>Unless you plan on keeping all the builds produced on the server, the <strong>Discard Old Builds</strong> is a good option to check, and set how long you want the builds to remain on the server.  Choose the source code management tool that you use for your project, which is Git for JRuby, and set the appropriate settings.</p>
<p>JRuby settings:</p>
<pre>URL of Repository: git://github.com/jruby/jruby.git
Branch Specifier (blank for default): master
Repository browser (Auto)
</pre>
<p>There are several types of Build Triggers by default.  More Build Triggers can be added through plugins, if you&#8217;re looking for another way to trigger a build.  For a nightly build at midnight select the <strong>Build periodically</strong> option, and put <em>@midnight</em> in the field.</p>
<p>For the build step, if you&#8217;re building a Java project select <strong>Invoke Ant</strong>.  Otherwise, <strong>Execute shell</strong> may be a good option for you.  For JRuby, select Invoke Ant and set the target to jar to build it.</p>
<p>At this point you can click the <strong>Save</strong> button at the bottom of the page and click <strong>Build Now</strong> on the next page to build your project.  It&#8217;s a good idea to make sure your project builds correctly before trying to add in nightly benchmarks.  It&#8217;s easier to debug problems before you have too much going on.  By clicking on the build from the active builds list the console output can be seen from the browser.</p>
<h2>Running the Benchmarks</h2>
<p>If your benchmarks are in the same repository, you&#8217;re mostly done.  Add another build step, and set it up to run your benchmarks.  While JRuby does have benchmarks in its repository, the benchmarks I plan on running are in a different repository.  With this goal in mind, I created another Job in Hudson to checkout and run the benchmarks.</p>
<p>Its setup is very similar to that of JRuby, it checks out the source and runs the benchmarks.  The main difference is that a parameter is passed to the project to tell it which Ruby VM to use.  The <span style="text-decoration: underline;">Parameterized Trigger Plugin</span> is necessary to pass a parameter from one project to another.  The way it works is you set a parameter in the project receiving the parameter near the top of the page.  In my case, I added a RUBY_PATH parameter.  Then you setup the build job to send that parameter to the benchmarks job.</p>
<p>To do this, I went back to the JRuby job and turned on the <strong>Trigger parameterized build on other projects</strong> option.  It should be the last option down at the bottom of the page.  I set the JRuby job to trigger with the benchmarks job name, and in the predefined parameters field I put the following:</p>
<pre> RUBY_PATH=$WORKSPACE/bin/jruby</pre>
<p>After this is in place, when a JRuby build finishes it will start a benchmarks run.  Now that your benchmarks are up and running, the next part to this series will go over how to display the information in a way that makes it easy to spot regressions.</p>
<p>If you have any questions or if I went over something too quickly, post a comment and/or ask a question.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.quibb.org/2010/04/nightly-benchmarks-setting-up-hudson/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Netbeans Debugger Not Stopping at Breakpoints</title>
		<link>http://blog.quibb.org/2008/12/netbeans-debugger-not-stopping-at-breakpoints/</link>
		<comments>http://blog.quibb.org/2008/12/netbeans-debugger-not-stopping-at-breakpoints/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 02:03:57 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ant]]></category>
		<category><![CDATA[debugger]]></category>
		<category><![CDATA[jruby]]></category>
		<category><![CDATA[netbeans]]></category>

		<guid isPermaLink="false">http://blog.quibb.org/?p=19</guid>
		<description><![CDATA[I use Netbeans for doing development for JRuby.  When I say that I don&#8217;t mean I&#8217;m developing with JRuby, I mean for JRuby.  I&#8217;m writing Java code, and wanted to use the debugger for Java code.  Everytime I mentioned JRuby people would assume I was using it and developing Ruby code, that&#8217;s not the case [...]]]></description>
			<content:encoded><![CDATA[<p>I use Netbeans for doing development for JRuby.  When I say that I don&#8217;t mean I&#8217;m developing with JRuby, I mean for JRuby.  I&#8217;m writing Java code, and wanted to use the debugger for Java code.  Everytime I mentioned JRuby people would assume I was using it and developing Ruby code, that&#8217;s not the case at all.  By the way, an awesome way to learn the ins and outs of a language is to develop <em>another</em> language in it.  I&#8217;ve learned quite a bit about Java since I started working on this, and I&#8217;d have called myself proficient in Java before starting.</p>
<p>Anyway, when I was trying to use the Netbeans debugger on JRuby it wasn&#8217;t stopping at my breakpoints, and I couldn&#8217;t figure out why.  I thought it might have something to do with me using linux, and after people ran out of ideas they seemed to think the same thing.  This turned out to not be the case.  It was a problem with the ant script for running the debugger.</p>
<p>It was as simple as changing this:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nbjpdastart</span> <span style="color: #000066;">addressproperty</span>=<span style="color: #ff0000;">&quot;jpda.address&quot;</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;JRuby&quot;</span> <span style="color: #000066;">transport</span>=<span style="color: #ff0000;">&quot;dt_socket&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;classpath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>        
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pathelement</span> <span style="color: #000066;">path</span>=<span style="color: #ff0000;">&quot;${jruby.classes.dir}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;path</span> <span style="color: #000066;">refid</span>=<span style="color: #ff0000;">&quot;build.classpath&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/classpath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>      
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nbjpdastart<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>to this:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nbjpdastart</span> <span style="color: #000066;">addressproperty</span>=<span style="color: #ff0000;">&quot;jpda.address&quot;</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;JRuby&quot;</span> <span style="color: #000066;">transport</span>=<span style="color: #ff0000;">&quot;dt_socket&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;classpath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>        
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pathelement</span> <span style="color: #000066;">path</span>=<span style="color: #ff0000;">&quot;${jruby.classes.dir}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;path</span> <span style="color: #000066;">refid</span>=<span style="color: #ff0000;">&quot;build.classpath&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/classpath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>      
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sourcepath</span> <span style="color: #000066;">path</span>=<span style="color: #ff0000;">&quot;${src.dir}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nbjpdastart<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>The sourcepath makes all the difference.  I&#8217;m posting this because nbjpdastart has very little documentation, and it took me quite a while to figure this out.  I hope this saves you some time.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.quibb.org/2008/12/netbeans-debugger-not-stopping-at-breakpoints/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sort Optimization</title>
		<link>http://blog.quibb.org/2008/11/sort-optimization/</link>
		<comments>http://blog.quibb.org/2008/11/sort-optimization/#comments</comments>
		<pubDate>Sat, 15 Nov 2008 18:31:19 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[benchmarks]]></category>
		<category><![CDATA[jruby]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[sorting]]></category>

		<guid isPermaLink="false">http://blog.quibb.org/?p=5</guid>
		<description><![CDATA[This all started one night when I was in the #JRuby channel on irc.freenode.net.  A channel user was complaining about JRuby&#8217;s sorting algorithm being slow.  I thought to myself, I should be able to speed it up.  At the time I was thinking since sorting has been so well researched it&#8217;d likely be easy to [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;">This all started one night when I was in the #JRuby channel on irc.freenode.net.  A channel user was complaining about JRuby&#8217;s sorting algorithm being slow.  I thought to myself, I should be able to speed it up.  At the time I was thinking since sorting has been so well researched it&#8217;d likely be easy to find documentation about it.  That didn&#8217;t turn out to be entirely the case.</p>
<p style="text-align: left;">I started by looking around on wikipedia, to see what that had to offer.  <a href="http://en.wikipedia.org/wiki/Introsort">IntroSort</a> caught my eye (also see: <a href="http://ralphunden.net/content/tutorials/a-guide-to-introsort/">A guide to Introsort</a>).  I thought it was interesting that after recursing to a certain depth it would switch from quicksort to heapsort.  I don&#8217;t think this optimization turned out to be that needed in the end though.  Other than switching to heapsort, it was pretty much a median of three quicksort with an insertion sort added.</p>
<p style="text-align: left;">It was a good starting point though.  I switched the heapsort for a shell sort and that dropped the number of comparisons needed by a good amount.  One thing I saw was only my &#8220;Median of 3 Killer&#8221; test case was affected by that.  I searched around the Internet often during this, and came across this page: <a href="http://arunchaganty.wordpress.com/2008/07/06/quicksort/">QuickSort</a>.  It had some interesting ideas like grouping the same element together when running the partition function.  I tried implementing that several times and it always ended up increasing the number of comparisons and the runtime.  I&#8217;m not 100% sure why.  If someone who knows more about sorting that I do has any input on that, I&#8217;d be happy to hear it.</p>
<p style="text-align: left;">Anyway, after working on that for a while I took a look at the competition.  I looked at Ruby&#8217;s C code.  They do some interesting things, which I hadn&#8217;t thought of up to that point.  First, they take the median of 7 if it has more than 200 elements.  Second, they don&#8217;t sample the end elements, this helps me out later in my optimizations.  I didn&#8217;t copy exactly what they were doing, but did a similar idea.  One thing they also did was look at the order of the 3 values that they compared last (I&#8217;ll refer to these as v1, v2, and v3).  v1 is before v2 and v3 in the list&#8217;s current state.  v2 is in the middle of the other two, and so on.</p>
<p style="text-align: left;">They had a lot more checks than what I ended up using, but I check if v1 &lt;= v2 &lt;= v3.  If this is the case I run the sequential test.  I also check if v1 &gt;= v2 &gt;= v3 to see if the list is in reversed order, and if it is I reverse the list before continuing.  While running these tests, I don&#8217;t check the first or last element of list because I have a separate test for that.  If it passes the sequential or reverse test that means the entire list is sorted except for potentially the first and/or the last element.  I then do a test on them and if they&#8217;re out of sequence I do bubble sort style swaps until they&#8217;re in the correct location.</p>
<p style="text-align: left;">Checking the end was one of the last optimizations I performed.  The main reason I added it is that case can be slow with the normal sorting algorithm, and I don&#8217;t think it&#8217;s that uncommon a case.  I&#8217;ve seen it happen where an element is appended to a sorted list and then the list is sorted again.  Overall, this catches a case with the potential to be slow in a fairly cheap manner.  These cases weren&#8217;t weeded out by the v1 &lt;= v2 &lt;= v3 style checks because the median of 7 that I use doesn&#8217;t check the end elements.</p>
<p style="text-align: left;">One of the last optimizations I performed was converting it to use a stack rather than operating recursively.  To be honest, this provided more speedup than I was expecting.  I guess all the function calls were taking a toll on the performance that I just didn&#8217;t realize at the time.</p>
<p style="text-align: left;">Another implementation technique that I ran tests to figure out which was better was whether to do insertion sort at the end on the entire list, or to do it as I find sections that are smaller than the threshold value.  After running benchmarks it turned out that putting it at the end was better.  I suspect that the extra function calls required for it to be done during the quicksort loop was more overhead than the potential gain of having more cache locality.</p>
<p style="text-align: left;">On with the benchmarks: (The numbers are time in seconds.  In parenthesis is speedup over Java.)</p>
<blockquote style="text-align: left;">
<pre>                          Java                 My Qsort
1245.repeat.1000.txt      1.6552300e-05 (1.00) 8.1874300e-06   (2.02 )
1245.repeat.10000.txt     0.00026284956 (1.00) 0.00012648017   (2.08 )
end.0.1000.txt            5.8904900e-06 (1.00) 1.7295600e-06   (3.41 )
end.0.10000.txt           8.3629030e-05 (1.00) 2.3148840e-05   (3.61 )
identical.1000.txt        3.5435500e-06 (1.00) 5.9168000e-07   (5.99 )
identical.10000.txt       3.7097050e-05 (1.00) 6.5003600e-06   (5.71 )
med.3.killer.1000.txt     1.0182050e-05 (1.00) 7.2132600e-06   (1.41 )
med.3.killer.10000.txt    0.00013968449 (1.00) 9.4941470e-05   (1.47 )
rand.dups.100.txt         1.2044400e-06 (1.00) 6.3194000e-07   (1.91 )
rand.dups.1000.txt        1.9847760e-05 (1.00) 1.0417630e-05   (1.91 )
rand.dups.10000.txt       0.00031415178 (1.00) 0.00020365385   (1.54 )
rand.no.dups.100.txt      1.2328200e-06 (1.00) 8.1612000e-07   (1.51 )
rand.no.dups.1000.txt     1.9309830e-05 (1.00) 1.1890280e-05   (1.62 )
rand.no.dups.10000.txt    0.00027436851 (1.00) 0.00017424722   (1.57 )
rand.steps.1000.txt       1.6057600e-05 (1.00) 1.0023700e-05   (1.60 )
rand.steps.10000.txt      0.00019955369 (1.00) 0.00017004971   (1.17 )
rev.ends.1000.txt         1.2306600e-05 (1.00) 2.8749300e-06   (4.28 )
rev.ends.10000.txt        9.4499880e-05 (1.00) 2.7255840e-05   (3.47 )
rev.partial.1000.txt      1.7107210e-05 (1.00) 8.7564000e-06   (1.95 )
rev.partial.10000.txt     0.00024198949 (1.00) 0.00013045623   (1.85 )
rev.saw.1000.txt          1.6793840e-05 (1.00) 9.4294600e-06   (1.78 )
rev.saw.10000.txt         0.00025133096 (1.00) 0.00014296088   (1.76 )
reverse.1000.txt          1.4600270e-05 (1.00) 1.1565800e-06   (12.6 )
reverse.10000.txt         0.00020535965 (1.00) 1.3798890e-05   (14.9 )
seq.0.is.1000.1000.txt    6.5672500e-06 (1.00) 1.4837800e-06   (4.43 )
seq.0.is.1000.10000.txt   4.7335130e-05 (1.00) 7.2842900e-06   (6.50 )
seq.partial.1000.txt      1.5497830e-05 (1.00) 6.0515300e-06   (2.56 )
seq.partial.10000.txt     0.00022936435 (1.00) 9.1791120e-05   (2.50 )
seq.saw.1000.txt          1.1645670e-05 (1.00) 4.6621150e-05   (0.250)
seq.saw.10000.txt         0.00019771144 (1.00) 0.00011184647   (1.77 )
sequential.1000.txt       3.4216700e-06 (1.00) 5.8689000e-07   (5.83 )
sequential.10000.txt      3.7812430e-05 (1.00) 6.1648500e-06   (6.13 )</pre>
</blockquote>
<p>These benchmarks were taken by running the sorting algorithm on each dataset 10000 times (to warm up the JVM), and then running it on the data 10 times to time it.  I took the average of those 10 runs.  The only case where My Qsort was slower than the built-in Java Arrays.sort() was seq.saw.1000.txt.  I attribute this to noise.  I ran it again and got the following:</p>
<blockquote>
<pre>seq.saw.1000.txt          0.00013980571 (1.00) 0.00012667049   (1.10 )</pre>
</blockquote>
<p>Hopefully this makes JRuby&#8217;s sorting comparable to Ruby&#8217;s.  One note, while Java&#8217;s sort is stable, the quicksort I wrote is not.  All that means is that if multiple entries have the same value they may get sorted differently.</p>
<p>You can do whatever you&#8217;d like with the source code.  If you do find it useful some credit and/or a link to here would be nice.</p>
<p>Here are the test files: <a href="http://blog.quibb.org/wp-content/uploads/2008/11/test_files.zip">Test Files<br />
</a></p>
<p>Here is the sort itself: <a href="http://blog.quibb.org/wp-content/uploads/2008/11/sort.zip">Sorting Algorithm </a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.quibb.org/2008/11/sort-optimization/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
