<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><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" version="2.0">

<channel>
	<title>The Devver Blog</title>
	
	<link>http://devver.net/blog</link>
	<description>A Boulder startup improving the way developers work.</description>
	<pubDate>Wed, 19 Nov 2008 22:19:52 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.3</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/devver/blog" type="application/rss+xml" /><item>
		<title>Ruby Beanstalkd distributed worker intermediate lessons</title>
		<link>http://devver.net/blog/2008/11/ruby-beanstalkd-distributed-worker-intermediate-lessons/</link>
		<comments>http://devver.net/blog/2008/11/ruby-beanstalkd-distributed-worker-intermediate-lessons/#comments</comments>
		<pubDate>Wed, 19 Nov 2008 22:19:01 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[Hacking]]></category>

		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://devver.net/blog/?p=839</guid>
		<description><![CDATA[This post is a follow up to Ruby beanstalkd basics, I will try to make the example code little more interesting and useful. I am calling this is a Ruby beanstalkd intermediate write up, it sets up a few workers and distributes and receives results simultaneously. In this example the code resembles real code a [...]]]></description>
			<content:encoded><![CDATA[<p>This post is a follow up to <a href="http://devver.net/blog/2008/10/ruby-beanstalkd-distributed-worker-basics/">Ruby beanstalkd basics</a>, I will try to make the example code little more interesting and useful. I am calling this is a Ruby <a href="http://xph.us/software/beanstalkd/">beanstalkd</a> intermediate write up, it sets up a few workers and distributes and receives results simultaneously. In this example the code resembles real code a bit more (using a queue cache and block passing). If there is enough interest in the Ruby/beanstalkd community, I will follow up with beanstalkd advanced lessons, and go into how we deal with failure cases such as worker dying during jobs, random jobs failing, processing multiple &#8216;projects&#8217; at one time, using job priority settings, and using TTR/timeouts.</p>
<p>So in this example we are making an estimate of PI. Yes I know that there are far better approximations out there than my simple results, but this was what I came up with for an incredibly simple distributed computing problem. I based my example on the <a href="https://computing.llnl.gov/tutorials/parallel_comp/#ExamplesPI">PI Calculation</a> problem from an <a href="https://computing.llnl.gov/tutorials/parallel_comp/">Introduction to Parallel Computing</a>. The basic idea is that you can calculate pi by guessing random points in a square and then seeing how many points are inside a circle that fits inside the square (PI= 4 * points_in_circle/total_points).</p>
<p>I made a bunch of comments in the code that should help you follow but there are a few key sections worth pointing out.</p>
<p>In the <a href="http://devver.net/blog/2008/10/ruby-beanstalkd-distributed-worker-basics/">Ruby beanstalkd Basics</a>, both the Server and the Clients only used one queue at a time. Now since we are sending on one queue while also listening on another we need access to both queues at once. We simply have a helper function with a queue_cache to make getting and reusing multiple queues incredibly easy.</p>
<pre name="code" class="ruby">def get_queue(queue_name)
    @queue_cache ||= {}
    if @queue_cache.has_key?(queue_name)
      return @queue_cache[queue_name]
    else
      queue = Beanstalk::Pool.new(["#{SERVER_IP}:#{DEFAULT_PORT}"])
      queue.watch(queue_name)
      queue.use(queue_name)
      queue.ignore('default')
      @queue_cache[queue_name] = queue
      return queue
    end
  end</pre>
<p>In the basic example each class had a function that got a job and did some work and deleted the job. It is easy to imagine workers that might have many different kinds of work to do on jobs. In every case they are going to grab a job, work on the job, and delete the job. We decided to break that up and make it easy to just pass a work block when workers get a job.</p>
<pre name="code" class="ruby">def take_msg(queue)
    msg = queue.reserve
    #by calling ybody we get the content of the message and convert it from yml
    body = msg.ybody
    if block_given?
      yield(body)
    end
    msg.delete
  end

#call take_msg like so
take_msg(queue) do |body|
  #work on body
end</pre>
<p>One other thing you should keep a look out for in the code below is checking if a queue has any jobs. Many times workers will check if jobs exist and take them, and if there aren&#8217;t any jobs the process is free to do something else. I do this in this example, the server continually checks incoming results to immediately display. If no results have arrived yet, the server continues sending out job requests as fast as it can. This is useful since taking jobs from beanstalkd is a blocking call. They did add support for non-blocking calls in beanstalkd 1.1, but I haven&#8217;t started using the newest version yet. I think everything else should be pretty self explanatory, feel free to ask me any questions. To run the code it is the same as before: download <a href="#">beanstalk_intermediate.rb</a>, start beanstalkd, and run the example with ruby.<br />
<code><br />
$ beanstalkd &amp;<br />
$ ruby beanstalk_intermediate.rb<br />
starting distributor<br />
starting client(s)<br />
distributor sending out  jobs<br />
.......................................................<br />
.............................................<br />
received all the results our estimate for pi is: 3.142776</code></p>
<table border="1" width="80%">
<tr>
<td># of workers</td>
<td>time to complete</td>
</tr>
<tr>
<td valign="top">1</td>
<td>real    0m7.282s<br />
user    0m4.114s<br />
sys     0m0.978s</td>
</tr>
<tr>
<td valign="top">2</td>
<td>real    0m5.667s<br />
user    0m2.736s<br />
sys     0m0.670s</td>
</tr>
<tr>
<td valign="top">3</td>
<td>real    0m4.999s<br />
user    0m2.014s<br />
sys     0m0.515s</td>
</tr>
<tr>
<td valign="top">4</td>
<td>real    0m4.612s<br />
user    0m1.608s<br />
sys     0m0.442s</td>
</tr>
<tr>
<td valign="top">5</td>
<td>real    0m4.517s<br />
user    0m1.474s<br />
sys     0m0.416s</td>
</tr>
</table>
<pre name="code" class="ruby">require 'beanstalk-client.rb'

DEFAULT_PORT = 11300
SERVER_IP = '127.0.0.1'
#beanstalk will order the queues based on priority, with the same priority
#it acts FIFO, in a later example we will use the priority
#(higher numbers are higher priority)
DEFAULT_PRIORITY = 65536
#TTR is time for the job to reappear on the queue.
#Assuming a worker died before completing work and never called job.delete
#the same job would return back on the queue (in TTR seconds)
TTR = 3

class BeanBase

  #To work with multiple queues you must tell beanstalk which queues
  #you plan on writing to (use), and which queues you will reserve jobs from
  #(watch). In this case we also want to ignore the default queue
  #you need a different queue object for each tube you plan on using or
  #you can switch what the tub is watching and using a bunch, we just keep a few
  #queues open on the tubes we want.
  def get_queue(queue_name)
    @queue_cache ||= {}
    if @queue_cache.has_key?(queue_name)
      return @queue_cache[queue_name]
    else
      queue = Beanstalk::Pool.new(["#{SERVER_IP}:#{DEFAULT_PORT}"])
      queue.watch(queue_name)
      queue.use(queue_name)
      queue.ignore('default')
      @queue_cache[queue_name] = queue
      return queue
    end
  end

  #this will take a message off the queue, and process it with the block
  def take_msg(queue)
    msg = queue.reserve
    #by calling ybody we get the content of the message and convert it from yml
    body = msg.ybody
    if block_given?
      yield(body)
    end
    msg.delete
  end

  def results_ready?(queue)
    queue.peek_ready!=nil
  end

end

class BeanDistributor &lt; BeanBase

  def initialize(chunks,points_per_chunk)
    @chunks = chunks
    @points_per_chunk = points_per_chunk
    @messages_out = 0
    @circle_count = 0
  end

  def get_incoming_results(queue)
    if(results_ready?(queue))
      result = nil
      take_msg(queue) do |body|
        result = body.count
      end
      @messages_out -= 1
      print "." #display that we received another result
      @circle_count += result
    else
      #do nothing
    end
  end

  def start_distributor
    request_queue = get_queue('requests')
    results_queue = get_queue('results')
    #put all the work on the request queue
    puts "distributor sending out #{@messages} jobs"
    @chunks.times do |num|
      msg = BeanRequest.new(1,@points_per_chunk)
      #Take our ruby object and convert it to yml and put it on the queue
      request_queue.yput(msg,pri=DEFAULT_PRIORITY, delay=0, ttr=TTR)
      @messages_out += 1
      #if there are results get them if not continue sending out work
      get_incoming_results(results_queue)
    end

    while @messages_out &gt; 0
      get_incoming_results(results_queue)
    end
    npoints = @chunks * @points_per_chunk
    pi = 4.0*@circle_count/(npoints)
    puts "\nreceived all the results our estimate for pi is: #{pi}"
  end

end

class BeanWorker &lt; BeanBase

  def initialize()
  end

  def write_result(queue, result)
    msg = BeanResult.new(1,result)
    queue.yput(msg,pri=DEFAULT_PRIORITY, delay=0, ttr=TTR)
  end

  def in_circle
    #generate 2 random numbers see if they are in the circle
    range = 1000000.0
    radius = range / 2
    xcord = rand(range) - radius
    ycord = rand(range) - radius
    if( (xcord**2) + (ycord**2) &lt;= (radius**2) )
      return 1
    else
      return 0
    end
  end

  def start_worker
    request_queue = get_queue('requests')
    results_queue = get_queue('results')
    #get requests and do the work until the worker is killed
    while(true)
      result = 0
      take_msg(request_queue) do |body|
        chunks = body.count
        chunks.times { result += in_circle}
      end
      write_result(results_queue,result)
    end

  end

end

############
# These are just simple message classes that we pass using beanstalks
# to yml and from yml functions.
############
class BeanRequest
  attr_accessor :project_id, :count
  def initialize(project_id, count=0)
    @project_id = project_id
    @count = count
  end
end

class BeanResult
  attr_accessor :project_id, :count
  def initialize(project_id, count=0)
    @project_id = project_id
    @count = count
  end
end

#how many different jobs we should do
chunks = 100
#how many points to calculate per chunk
points_per_chunk = 10000
#how many workers should we have
#(normally different machines, in our example fork them off)
workers = 5

# Most of the time you will have two entirely separate classes
# but to make it easy to run this example we will just fork and start our server
# and client separately. We will wait for them to complete and check
# if we received all the messages we expected.
puts "starting distributor"
server_pid = fork {
  BeanDistributor.new(chunks,points_per_chunk).start_distributor
}

puts "starting client(s)"
client_pids = []
workers.times do |num|
  client_pid = fork {
    BeanWorker.new.start_worker
  }
  client_pids &lt;&lt; client_pid
end

Process.wait(server_pid)
#take down the clients
client_pids.each do |pid|
  Process.kill("HUP",pid)
end</pre>
]]></content:encoded>
			<wfw:commentRss>http://devver.net/blog/2008/11/ruby-beanstalkd-distributed-worker-intermediate-lessons/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Shazam vs Mashup Music</title>
		<link>http://devver.net/blog/2008/11/shazam-vs-mashup-music/</link>
		<comments>http://devver.net/blog/2008/11/shazam-vs-mashup-music/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 17:21:36 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://devver.net/blog/?p=866</guid>
		<description><![CDATA[I had a funny thought while listening to some music recently and decided I needed to do battle between music mashups and music recognition software.
Shazam is a pretty cool app on the iPhone to help you recognize and find music, it uses the microphone and listens to whatever music is near the iPhone. Shazam then [...]]]></description>
			<content:encoded><![CDATA[<p>I had a funny thought while listening to some music recently and decided I needed to do battle between music mashups and music recognition software.</p>
<p><a href="http://www.shazam.com/music/web/pages/iphone.html">Shazam</a> is a pretty cool app on the iPhone to help you recognize and find music, it uses the microphone and listens to whatever music is near the iPhone. Shazam then compares the few second recorded sound to an online database of music data to try to determine the song. I was curious what would happen when it was given mashup music which contains parts of many songs. Would it just be entirely confused? Would it recognize the mashup? Would it recognize the currently most prominent sample in the mashup?</p>
<table border="1" width="100%">
<tbody>
<tr>
<td>Artist, Song Title</td>
<td>Results</td>
</tr>
<tr>
<td colspan="2">First let&#8217;s test it on some normal songs and check the accuracy</p>
<p>(played on iTunes)</td>
</tr>
<tr>
<td>Beck, Loser</td>
<td>correct</td>
</tr>
<tr>
<td>Aquabats, Red Sweater!</td>
<td>unrecognized</td>
</tr>
<tr>
<td>Beastie Boys, Intergalatic</td>
<td>correct</td>
</tr>
<tr>
<td>Pearl Jam, Elderly Woman Behind the Counter in a Small Town</td>
<td>correct</td>
</tr>
<tr>
<td>Billy Joel, Captain Jack</td>
<td>correct</td>
</tr>
<tr>
<td>Flobots, Handlebars</td>
<td>correct</td>
</tr>
<tr>
<td>Weezer, Surf Wax America</td>
<td>correct</td>
</tr>
<tr>
<td colspan="2">Now let&#8217;s throw it some mashups and see what happens</p>
<p>(Shazam used randomly during song)</td>
</tr>
<tr>
<td valign="top">Jay-Zeezer, Surf Wax Off your Shoulder</td>
<td><span style="color: green;">rating: Good</span><br />
<span style="color: red;">Fails twice</span></p>
<p>identifies as Lil Jay, Dirt off your Shoulda Shurga twice (Should be Jay-Z, Dirt Off Your Shoulder, but it is basically a cover)</p>
<p>identifies as Weezer, Surf Wax America twice</td>
</tr>
<tr>
<td valign="top">Girl Talk, <a href="http://en.wikipedia.org/wiki/Feed_The_Animals#5._.22Set_It_Off.22_-_3:42">Set It Off</a></td>
<td><span style="color: green;">rating: <strong>Great<strong></strong></strong></span><strong><strong><br />
<span style="color: red;">Fails three times</span></strong></strong></p>
<p><strong><strong>identifies as Jay-Z, Roc Boys (correctly in song)</strong></strong></p>
<p><strong><strong>identifies as Mary J. Blige, Real Love (correctly in song)</strong></strong></p>
<p><strong><strong>identifies as Fatman, Scoop Be Faithful (correctly in song)</strong></strong></td>
</tr>
<tr>
<td valign="top">Girl Talk, <a href="http://en.wikipedia.org/wiki/Feed_The_Animals#14._.22Play_Your_Part_.28Pt._2.29.22_-_3:25">Play Your Part (part 2)</a></td>
<td><span style="color: red;">rating: Poor</span><br />
<span style="color: red;">Fails eight times</span></p>
<p>identifies as Huey Pop, Lock &amp; Drop It once (correctly in song)</td>
</tr>
<tr>
<td valign="top">Girl Talk, <a href="http://en.wikipedia.org/wiki/Feed_The_Animals#2._.22Shut_the_Club_Down.22_-_3:07">Shut The Club Down</a></td>
<td><span style="color: blue;">rating: OK</span><br />
<span style="color: red;">Fails two times</span></p>
<p>identifies as Dolla Feat. T-Pain and Tay Dizm, Who The F**k is That? (correctly in song (there are multiple versions of this song see below))</p>
<p>identifies as T-Pain Feat. Dolla &amp; Akon, Who the F is That (correctly in song (there are multiple versions of this song see above))</p>
<p>identifies as Rich Boy Feat. Polow Da Don, Throw Some D&#8217;s (correctly in song)</td>
</tr>
<tr>
<td valign="top">Danger Mouse, 99 Problems (<a href="http://en.wikipedia.org/wiki/Grey_Album">The Grey Album</a>)</td>
<td><span style="color: green;">rating: <strong>Awesome!</strong></span><br />
<span style="color: green;">No Failures!</span></p>
<p>identifies as Jay-Z, 99 Problems (correctly in song)</p>
<p>identifies as Dangermouse, 99 Problems/Helter Skelter five times (This is the actual mashup)</td>
</tr>
<tr>
<td valign="top">Danger Mouse, Public Service Announcement (<a href="http://en.wikipedia.org/wiki/Grey_Album">The Grey Album</a>)</td>
<td><span style="color: red;">rating: Poor</span><br />
identifies as Jay-Z, Interlude three times (correct artist and album but the wrong song)</td>
</tr>
<tr>
<td valign="top">Danger Mouse, What More Can I Say (<a href="http://en.wikipedia.org/wiki/Grey_Album">The Grey Album</a>)</td>
<td><span style="color: green;">rating: <strong>Great</strong></span><br />
identifies as Jay-Z, What More Can I Say nine times (correctly in song)</p>
<p>identifies as George Harrison, While My Guitar Gently Weeps twice (correctly in song)</td>
</tr>
</tbody>
</table>
<p><strong>Conclusion</strong><br />
It was far more noticeable when the dominant sample was playing during both <a href="http://www.jay-zeezer.com/">Jay-Zeezer</a> and <a href="http://stereo.lu/grey/">The Grey Album</a> which seemed to mean that Shazam could pick out the individual songs easier. I was quite impressed when it even correctly identified some of the Grey Album as actually being a mashup. <a href="http://74.124.198.47/illegal-art.net/__girl__talk___feed__the__anima.ls___/">Girl Talk</a> gave the program a harder time, which makes sense seeing as many samples are put together for very small amounts of times and many of the samples are slightly altered. Some songs where there were dominant samples for a period of time, it did a decent job. It is a cool way to figure out what songs contribute to a mashup if you are unsure about a piece of a song. I was pretty impressed with Shazam&#8217;s abilities to pick apart the pieces of the songs. I guess the results aren&#8217;t really that surprising, but it was still a fun way to spend some of a Saturday afternoon listening to music and testing some software.</p>
]]></content:encoded>
			<wfw:commentRss>http://devver.net/blog/2008/11/shazam-vs-mashup-music/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Displaying code on your blog</title>
		<link>http://devver.net/blog/2008/11/displaying-code-on-your-blog/</link>
		<comments>http://devver.net/blog/2008/11/displaying-code-on-your-blog/#comments</comments>
		<pubDate>Thu, 13 Nov 2008 18:19:26 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
		
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://devver.net/blog/?p=890</guid>
		<description><![CDATA[A few weeks ago, I wrote about my desire for an awesome embeddable code widget.The most common solution that people suggested in the comments (and on the thread on Stack Overflow) was SyntaxHighlighter. I had seen the SyntaxHighlighter (SH) widget on a few blogs and was impressed, so I decided to install the WordPress plugin. [...]]]></description>
			<content:encoded><![CDATA[<p>A few weeks ago, I wrote about my desire for <a href="http://devver.net/blog/2008/10/someone-please-build-an-awesome-embeddable-code-widget/">an awesome embeddable code widget</a>.The most common solution that people suggested in the comments (and on the thread on <a href="http://stackoverflow.com/questions/251297/is-there-a-good-embeddable-code-widget-for-blogs">Stack Overflow</a>) was <a href="http://code.google.com/p/syntaxhighlighter/">SyntaxHighlighter</a>. I had seen the SyntaxHighlighter (SH) widget on a few blogs and was impressed, so I decided to install the <a href="http://wordpress.org/extend/plugins/google-syntax-highlighter/">WordPress plugin</a>. The installation was easy enough, but unfortunately the plugin comes with a slightly old version of SH. Luckily, it was really easy to download the newest version from the SH site and drop it into the plugin.</p>
<p>Now we can just wrap code in <code>&lt;pre name='code' class='ruby'&gt;...some code...&lt;/pre&gt;</code> and it will look like this:</p>
<pre class="ruby" name="code">class Foo
   def bar
     puts "Hello, world!"
   end
end</pre>
<p>Pretty sweet! In fact, we ended up converting all of the code snippets on our blog to use SH.</p>
<p>Although SH is really, really cool, it does suffer from inherent drawbacks: it has to be installed and it has to be periodically updated. What I initially described in my previous post was something simpler - a web app where you could easily post code and then embed it in your blog. In other words, <a href="http://pastie.org/">Pastie</a> with a <a href="http://youtube.com">YouTube</a>-like embed feature.</p>
<p><a href="http://pomoti.com/">Dirceu Jr.</a> pointed out <a href="http://gist.github.com/">Gist</a> from <a href="http://github.com/">GitHub</a>, which is exactly what I was looking for. Even without signing up, you can post code (<a href="http://gist.github.com/24490">like so</a>) and then embed it in your blog.</p>
<p><script src="http://gist.github.com/24490.js"></script>Dirceu Jr. even wrote a <a href="http://pomoti.com/gist-it-english">WordPress plugin</a> if you really want to install something! The only weird thing is that while the embedded code is nicely syntax-highlighted, the <a href="http://gist.github.com/24490">original gist</a> is not for some reason. <strong>Update:</strong> Yoan pointed out that you can get syntax-coloring by naming your gist properly (I renamed my gist foo.rb and it worked). It&#8217;s still not clear to me why it doesn&#8217;t work if I manually select &#8216;Ruby&#8217; as the language for an unnamed gist, however.<br />
<br/><br />
Finally, while SyntaxHighlighter supports the most popular languages (and therefore is likely to be fine for most programming blogs), Gist supports a truly insane number of languages, making it a better choice if you want to post code snippets of say, Lua, Erlang, or Haskell.</p>
<table style="text-align: left; width: 100%;" border="1">
<tbody>
<tr>
<td style="width: 33%; background-color: #c0c0c0;">Language</td>
<td style="width: 33%; background-color: #c0c0c0;">SyntaxHighlighter</td>
<td style="background-color: #c0c0c0;">Gist</td>
</tr>
<tr>
<td style="background-color: #c0c0c0;" colspan="3">Popular languages</td>
</tr>
<tr>
<td>ActionScript</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Bash</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>C</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>C#</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>C++</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>CSS</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Delphi</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Diff</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Erlang</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>HTML</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Haskell</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Io</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Java</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>JavaScript</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Lua</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>OCaml</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Objective-C</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>PHP</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Perl</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Plain Text</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Python</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>RHTML</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Ruby</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>SQL</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Scheme</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Smalltalk</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Smarty</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>VB or VB.net</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>XML</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td style="background-color: #c0c0c0;" colspan="3">Other crazy stuff</td>
</tr>
<tr>
<td>Batchfile</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Befunge</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Boo</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Brainfuck</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Common Lisp</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>D</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Darcs Patch</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Dylan</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Fortran</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>GAS</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Genshi</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Gettext Catalog</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Groff</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>HTML+PHP</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>INI</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>IRC logs</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Java Server Page</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>LLVM</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Literate Haskell</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Logtalk</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>MOOCode</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Makefile</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Mako</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Matlab</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>MiniD</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>MuPAD</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Myghty</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>NumPy</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Python Traceback</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Raw token data</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Redcode</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>S</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Tcl</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Tcsh</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>TeX</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>Text only</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>VimL</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>XSLT</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>c-objdump</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>cpp-objdump</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>d-objdump</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>objdump</td>
<td></td>
<td>X</td>
</tr>
<tr>
<td>reStructuredText</td>
<td></td>
<td>X</td>
</tr>
</tbody>
</table>
<p>Both of these projects provide great-looking ways to display code on your blog. If you know of other projects that you like, let me know in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://devver.net/blog/2008/11/displaying-code-on-your-blog/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Notes from the Boulder CTO lunch (11/3/2008)</title>
		<link>http://devver.net/blog/2008/11/notes-from-the-boulder-cto-lunch-1132008/</link>
		<comments>http://devver.net/blog/2008/11/notes-from-the-boulder-cto-lunch-1132008/#comments</comments>
		<pubDate>Fri, 07 Nov 2008 17:21:39 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
		
		<category><![CDATA[Devver]]></category>

		<category><![CDATA[Misc]]></category>

		<category><![CDATA[TechStars]]></category>

		<guid isPermaLink="false">http://devver.net/blog/?p=855</guid>
		<description><![CDATA[Although I&#8217;m not actually the CTO of Devver, I had the pleasure of attending the Boulder CTO lunch this past Monday since Dan was out of town.
This week, the group had Todd Vernon from Lijit come lead the discussion. Although Todd is currently CEO of Lijit, he was CTO at his former company, Raindance.
The group [...]]]></description>
			<content:encoded><![CDATA[<p>Although I&#8217;m not actually the CTO of Devver, I had the pleasure of attending the Boulder CTO lunch this past Monday since Dan was out of town.</p>
<p>This week, the group had <a href="http://falseprecision.typepad.com/">Todd Vernon</a> from <a href="http://www.lijit.com/">Lijit</a> come lead the discussion. Although Todd is currently CEO of Lijit, he was CTO at his former company, <a href="http://www.raindance.com/">Raindance</a>.</p>
<p>The group that was assembled was small but awesome - I had the opportunity to learn not only from Todd, but also from the CTOs of a few of last years <a href="http://techstars.org">TechStars</a> companies.</p>
<p>The discussion touched on a ton of topics, but two (related) themes that were heavily discussed were the role of the CTO and how a company grows from a technology perspective. I&#8217;ve organized my notes below. Keep in mind that these are the collected thoughts from a number of different participants and I may not have captured their ideas with 100% accuracy.</p>
<p><strong>The Role of a CTO</strong></p>
<p>What is the difference between a <span class="nfakPe">CTO</span> and a VP of Engineering?</p>
<p><span class="nfakPe">CTO</span> is about leadership for technical issues, interfacing with the business side, guiding the product, get people excited about product from a technical point of view.</p>
<p>VPoE is almost one step above Chief Architect, more on a management side, getting product delivered.</p>
<p>1st time CTOs need to figure out their exact role. It&#8217;s a very amorphous role, depending on the company.</p>
<p><span class="nfakPe">CTO</span> needs to be able to tell the whole business story, understand the good parts and bad.</p>
<p><span class="nfakPe">Early on, CTO</span> should insert themselves into the sales process as much as possible (especially right after you hire the sales person). You need to be able to hear what customers say they want, so you can translate that into what they really need.</p>
<p><em>The Technology Onion</em></p>
<p>There is a technology onion - make sure the core of the onion is owned by company (the outer layers, not as important). The <span class="nfakPe">CTO</span> needs to figure out the relationship between the technologies and the company&#8217;s partnerships. The closer a technology is to the core of the onion, the more important it is to own it and to make sure it scales.</p>
<p>For instance, if you&#8217;re depending on Google for search, you&#8217;re powerless to change features if things don&#8217;t work as your customers want/expect. If search is core to your business (near the core of the onion), consider building it internally. It&#8217;s the CTOs role to make that case, because business people will never understand the need to spend money to get &#8220;the same thing.&#8221;</p>
<p>Having to re-architect a core component of a company can really hurt growth. Assume you&#8217;re going to be successful, so plan for that.</p>
<p>Along the same lines, one concern about using EC2 is that you get tied to the platform and your business is dependent on an outside force you can&#8217;t control. Hosting on EC2 can be quite different than hosting your own boxes.</p>
<p><em>Acceptable Failures</em></p>
<p>What is acceptable downtime? It depends on when - between midnight to 1-2 AM, it might be OK to be down for a few minutes. CTOs need to determine what acceptable downtime is and tell that the to the rest of management and have people agree.</p>
<p>CTOs need to make decisions (for instance, what is the acceptable down time, acceptable data loss, or acceptable time for page load) and then tell the entire organization. That way, when something bad happens, you can explain that everyone agreed on the specific numbers. It&#8217;s unlikely your business will need to be (or can be) 100% perfect on all metrics, but people need to understand what the goal is and why it&#8217;s realistic.</p>
<p><strong>Growing/Scaling/Monitoring</strong></p>
<p>If at least one person is using your service, you should have two web servers. It gives you ton of flexibility. Having two boxes forces you to work out most of the issues early (it&#8217;s a lot different getting to 2 boxes than 3 or 4). It&#8217;s not about load, it&#8217;s about reliability.</p>
<p>No matter how useful you are, if you are not reliable, someone will blog, &#8220;it&#8217;s cool, but it doesn&#8217;t work reliably.&#8221;</p>
<p>Downtime spreads very fast across Twitter. Consider tweeting about upcoming service interruptions ahead of time so customers are aware.</p>
<p>After more than 15 people, you need a dedicated operations person. Get some basic monitoring services early - after a server is under load, it&#8217;s really hard to diagnose. Try to detect stuff early, it&#8217;s easier to debug.</p>
<p>With startups, generally the problem tends to be slow requests rather than complete service downtime. Make sure your monitoring service will alert you with slow requests.</p>
<p>Get app specific stuff - a warning like &#8220;High CPU load,&#8221; is harder to understand (it might be a problem, or maybe the machine is just handling a lot of requests successfully), but &#8220;Page X takes 80 sec to load&#8221; is more obvious.</p>
<p>As you grow, try to measure more and more. Things often degrade slowly, and one day you just notice its too slow and it&#8217;s hard to go back and find the root of the problem.</p>
<p>Make two lists: a) the most catastrophic things that could happen and b) the most likely things that could happen. Where those lists overlap, you need to fix something. But there will be some risks that you decide are reasonable risks for the business (revisit these risks regularly as things change).</p>
<p>Regarding backup - always make sure you try to restore some data (before you really need it). You need to make sure it works and make sure its fast enough.</p>
<p>You should always be able to describe at a high level how the service will scale infinitely (it doesn&#8217;t have to be technically perfect, but it has to be believable). When someone wants to purchase, that&#8217;ll be a huge help - the business guy on the other side of the table will want to buy, but the technical guy doesn&#8217;t want to buy (he wants to build it in-house).</p>
<hr />I hope those notes make some sense and give you a good feel for the discussion we had. I&#8217;m looking forward to attending more of these lunches (I hope they&#8217;ll continue to let a few CEOs sneak in&#8230;)</p>
]]></content:encoded>
			<wfw:commentRss>http://devver.net/blog/2008/11/notes-from-the-boulder-cto-lunch-1132008/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Someone please build an awesome embeddable code widget</title>
		<link>http://devver.net/blog/2008/10/someone-please-build-an-awesome-embeddable-code-widget/</link>
		<comments>http://devver.net/blog/2008/10/someone-please-build-an-awesome-embeddable-code-widget/#comments</comments>
		<pubDate>Thu, 30 Oct 2008 14:53:56 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[Hacking]]></category>

		<guid isPermaLink="false">http://devver.net/blog/?p=822</guid>
		<description><![CDATA[One awesome thing about working at a startup is that you get to focus very deeply on the problem you&#8217;re trying to solve. On the other hand, if you&#8217;ve taken the leap and founded a startup, it&#8217;s probably because you tend to see solutions and opportunities everywhere. It can be really hard to focus on [...]]]></description>
			<content:encoded><![CDATA[<p>One awesome thing about working at a startup is that you get to focus very deeply on the problem you&#8217;re trying to solve. On the other hand, if you&#8217;ve taken the leap and founded a startup, it&#8217;s probably because you tend to see solutions and opportunities everywhere. It can be really hard to focus on one thing when you often have ideas for services that you&#8217;d like to use, or better yet, build.</p>
<p>Dan and I regulary talk about services that we wish existed but we simply can&#8217;t work on due to our commitment to <a href="http://devver.net">Devver</a>. The other day we were discussing one problem we wish someone would solve: why can&#8217;t we easily post nicely formatted code in our blog posts?</p>
<p>All I want is this: I copy/paste some code into a web site, choose the programming language, copy some widget code and paste that code into my blog. The code is indented and formatted, has syntax coloration, wraps correctly (for any iPhone readers) and can be easy copied/pasted. Including line numbers (that don&#8217;t mess with copy/paste) is a bonus.</p>
<p>In other words, I just want <a href="http://pastie.org/">Pastie</a> in my blog posts.</p>
<p>Yes, I know there are a few really nice projects that you can install on your server that will do all this. But we could all host our own video as well, but it&#8217;s just easier to upload and embed a video on <a href="http://youtube.com">YouTube</a> or <a href="http://vimeo.com">Vimeo</a>.</p>
<p>This wouldn&#8217;t just have to be for the good of humanity either. Such a service could make money off ads (each widget could have a link to the full-screen code on the main site, which could have ads for programming jobs, books, and conferences) or even sell off the data about which programming languages were most popular (in blogs and on the main site).</p>
<p>Maybe there is a solution for this (if there is, please let me know in the comments. I&#8217;m more than willing to publicly display my ignorance in order to learn about it), but if there is, I don&#8217;t see it widely being used and it&#8217;s not easy to find on Google. If there isn&#8217;t (yet), please go forth and build. I&#8217;ll be anxiously waiting.</p>
]]></content:encoded>
			<wfw:commentRss>http://devver.net/blog/2008/10/someone-please-build-an-awesome-embeddable-code-widget/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Ruby Beanstalkd distributed worker basics</title>
		<link>http://devver.net/blog/2008/10/ruby-beanstalkd-distributed-worker-basics/</link>
		<comments>http://devver.net/blog/2008/10/ruby-beanstalkd-distributed-worker-basics/#comments</comments>
		<pubDate>Tue, 28 Oct 2008 21:35:14 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[Devver]]></category>

		<category><![CDATA[Hacking]]></category>

		<category><![CDATA[Tips &amp; Tricks]]></category>

		<guid isPermaLink="false">http://devver.net/blog/?p=565</guid>
		<description><![CDATA[At Devver we have a lot of jobs to do quickly, so we distribute our work out to a group of EC2 workers. We have tried and used a number of queuing solutions with Ruby, but in the end beanstalkd seemed to be the best solution for us at the time.
I have only seen a [...]]]></description>
			<content:encoded><![CDATA[<p>At Devver we have a lot of jobs to do quickly, so we distribute our work out to a group of <a href="http://aws.amazon.com/ec2/">EC2</a> workers. We have tried and used a number of <a href="http://devver.net/blog/2008/06/ruby-messaging-shootout/">queuing solutions with Ruby</a>, but in the end <a href="http://xph.us/software/beanstalkd/">beanstalkd</a> seemed to be the best solution for us at the time.</p>
<p>I have only seen a few posts about the <a href="http://nubyonrails.com/articles/about-this-blog-beanstalk-messaging-queue">basics of using beanstalkd with Ruby</a>. I decided to make two posts evolving a simple Ruby beanstalkd example into a more complicated example. This way people new to beanstalkd could see how easy it can be to get up and running with  distributed processing using Ruby and beanstalkd. Then people that are doing more advanced work with beanstalkd could see some examples of how we are working with it here at Devver. It would also be great for more experienced beanstalkd warriors to share their thoughts as there aren&#8217;t many examples out in the wild. The lack of examples makes it harder to learn and difficult to decide what the best practices are when working with beanstalkd queues.</p>
<p>I have also shared two scripts we have found useful while working with beanstalkd. <a href="http://devver.net/blog/wp-content/uploads/2008/10/beanstalk_monitor.rb">beanstalk_monitor.rb</a>, which lets you see all the queue statistics about current usage, or to monitor the information of a single queue you are interested in. Finally, <a href="http://devver.net/blog/wp-content/uploads/2008/10/beanstalk_killer.rb">beanstalk_killer.rb</a>, which is useful if you want to work on how your code will react to beanstalkd getting backed up or stalling (in beanstalkd speak, &#8220;Putting on the brakes&#8221;). It was a little harder to pull everything out and make a simple example from our code than I thought, and obviously the example is a bit useless. It should still give a solid example of how to do the basics of distributing jobs with beanstalkd.</p>
<p>For those new to beanstalk, there are a few things you will need to know like how to get a queue object, how to put objects on the queue, how to take objects off the queue, and how to control which queue you are working with. For a higher level overview or more detailed information, I recommend checking out the <a href="http://github.com/kr/beanstalkd/wikis/faq">beanstalkd FAQ</a>. The full example code is below, but first taking a look at the basic snippets might help.</p>
<pre name="code" class="ruby">
#to work with beanstalk you need to get a client connection
queue = Beanstalk::Pool.new(["#{SERVER_IP}:#{DEFAULT_PORT}"])
#by default you will be working on the 'default' tube or queue
#if we wanted to work on a different queue we could change tubes, like so
queue.watch('test_queue')
queue.use('test_queue')
queue.ignore('default')
#to put a simple string on a queue
queue.put('hello queue world')
#to receive a simple string
job = queue.reserve
puts job.body #prints 'hello queue world'
#if you don't delete the job when you're done, the queue assumes there is an error
#and the job will show back up on the queue again
job.delete
</pre>
<p><strong>How to run this example (on OS X, with <a href="http://www.macports.org/">macports</a> installed)</strong></p>
<pre name="code">&gt; sudo port install beanstalkd
&gt; sudo gem install beanstalk-client
&gt; beanstalkd
&gt; ruby beanstalk_tester.rb</pre>
<p>Download: <a href="http://devver.net/blog/wp-content/uploads/2008/10/beanstalk_tester.rb">beanstalk_tester.rb</a></p>
<pre name="code" class="ruby">
require 'beanstalk-client.rb'

DEFAULT_PORT = 11300
SERVER_IP = '127.0.0.1'
#beanstalk will order the queues based on priority, with the same priority
#it acts FIFO, in a later example we will use the priority
#(higher numbers are higher priority)
DEFAULT_PRIORITY = 65536
#TTR is time for the job to reappear on the queue.
#Assuming a worker died before completing work and never called job.delete
#the same job would return back on the queue (in seconds)
TTR = 3

class BeanBase

  #To work with multiple queues you must tell beanstalk which queues
  #you plan on writing to (use), and which queues you will reserve jobs from
  #(watch). In this case we also want to ignore the default queue
  def get_queue(queue_name)
    queue = Beanstalk::Pool.new(["#{SERVER_IP}:#{DEFAULT_PORT}"])
    queue.watch(queue_name)
    queue.use(queue_name)
    queue.ignore('default')
    queue
  end

end

class BeanDistributor &lt; BeanBase

  def initialize(amount)
    @messages = amount
  end

  def start_distributor
    #put all the work on the request queue
    bean_queue = get_queue('requests')
    @messages.times do |num|
      msg = BeanRequest.new(1,num)
      #Take our ruby object and convert it to yml and put it on the queue
      bean_queue.yput(msg,pri=DEFAULT_PRIORITY, delay=0, ttr=TTR)
    end

    puts "distributor now getting results"
    #get all the results from the results queue
    bean_queue = get_queue('results')
    @messages.times do |num|
      result = take_msg(bean_queue)
      puts "result: #{result}"
    end

  end

  #this will take a message off the queue, process it and return the result
  def take_msg(queue)
    msg = queue.reserve
    #by calling ybody we get the content of the message and convert it from yml
    count = msg.ybody.count
    msg.delete
    return count
  end

end

class BeanWorker &lt; BeanBase

  def initialize(amount)
    @messages = amount
    @received_msgs = 0
  end

  def start_worker
    results = []
    #get and process all the requests, on the requests queue
    bean_queue = get_queue('requests')
    @messages.times do |num|
      result = take_msg(bean_queue)
      results &lt;&lt; result
      @received_msgs += 1
    end

    #return all of the results, by placing them on the separate results queue
    bean_queue = get_queue('results')
    results.each do |result|
      msg = BeanResult.new(1,result)
      bean_queue.yput(msg,pri=DEFAULT_PRIORITY, delay=0, ttr=TTR)
    end

    #this is just to pass information out of the forked process
    #we return the number of messages we received as our exit status
    exit @received_msgs
  end

  #this will take a message off the queue, process it and return the result
  def take_msg(queue)
    msg = queue.reserve
    #by calling ybody we get the content of the message and convert it from yml
    count = msg.ybody.count
    result = count*count
    msg.delete
    return result
  end

end

############
# These are just simple message classes that we pass using beanstalks
# to yml and from yml functions.
############
class BeanRequest
  attr_accessor :project_id, :count
  def initialize(project_id, count=0)
    @project_id = project_id
    @count = count
  end
end

class BeanResult
  attr_accessor :project_id, :count
  def initialize(project_id, count=0)
    @project_id = project_id
    @count = count
  end
end

#write X messages on the queue
numb = 10

recv_count = 0

# Most of the time you will have two entirely seperate classes
# but to make it easy to run this example we will just fork and start our server
# and client seperately. We will wait for them to complete and check
# if we received all the messages we expected.
puts "starting distributor"
server_pid = fork {
  BeanDistributor.new(numb).start_distributor
}

puts "starting client"
client_pid = fork {
  BeanWorker.new(numb).start_worker
}

Process.wait(client_pid)
recv_count = $?.exitstatus
puts "client finished received #{recv_count} msgs"
if(numb==recv_count)
  puts "received the expected number of messages"
else
  puts "error didn't receive the correct number of messages"
end

Process.wait(server_pid)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://devver.net/blog/2008/10/ruby-beanstalkd-distributed-worker-basics/feed/</wfw:commentRss>
		</item>
		<item>
		<title>iPhone Apps I would like to have</title>
		<link>http://devver.net/blog/2008/10/iphone-apps-i-would-like-to-have/</link>
		<comments>http://devver.net/blog/2008/10/iphone-apps-i-would-like-to-have/#comments</comments>
		<pubDate>Fri, 17 Oct 2008 15:45:11 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
		
		<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://devver.net/blog/?p=711</guid>
		<description><![CDATA[I know everyone has posted a list of the best/must-have iPhone apps. I am sure many people have also posted lists of Apps they would like to have, but it is amazingly fun so I decided I should do it to.
This is my list of apps and solutions I want for the iPhone. They don&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>I know everyone has posted a list of the <a href="http://www.time.com/time/specials/packages/article/0,28804,1823107_1823513_1823586,00.html">best/must-have iPhone apps</a>. I am sure many people have also posted lists of Apps they would like to have, but it is amazingly fun so I decided I should do it to.</p>
<p>This is my list of apps and solutions I want for the iPhone. They don&#8217;t have to all necessarily be native apps. If you know of an web-app (that works on the iPhone) which provides the functionality I am looking for, let me know.</p>
<p>I want something like <a href="http://www.amazon.com/Brain-Age-Train-Your-Minutes/dp/B000EGELP0/002-6164228-9672009?SubscriptionId=1XM1P73VXKBX6ZQPKN02/mixi-20/ref=nosim">Brain Age</a> for the GameBoy on the iPhone. Spending a few minutes doing little puzzles and math when I have downtime seems like a better use of my time then just playing random games. I have <a href="http://www.gengarstudios.com/">Brain Tuner</a>, which is nice, but I want some more options/different puzzles.</p>
<p>I want a Google Contacts to Apple contacts one-time syncer, All my iPhone contacts are missing their emails. All my Gmail contacts are missing their phone numbers, someone help me sync that up.</p>
<p>I want full syncing between my Google calendar and the native apple calendar app. I always had this and it was really easy to do on pocket PC. I want a full 2 way sync. Google and Apple seem pretty buddy buddy, so get on this.</p>
<p>I want flash cards, with prebuilt decks. I would like to be able to work my way through some word decks building my vocabulary. I also would love to have some Spanish/English decks. I am working on improving my Spanish by listening to <a href="http://www.radiolinguamedia.com/cbs/www/index.html">Coffee Break Spanish</a>, and having a Spanish study deck would be great.</p>
<p>I want an EBook reader - oh wait, someone just pointed one out to me (thanks Matt) it is called <a href="http://www.lexcycle.com/iphone">Stanza</a>. It&#8217;s seriously awesome, if they add a screen reader, it would be perfect. I could listen to some classics books while jogging/driving.</p>
<p>I want GPS tracking that works. I have a great iPhone app called <a href="http://www.trailguru.com/wiki/index.php/Main_Page">Trailguru</a>, which tracks movement/location with GPS and can tell me the speed and total distance I go when I run. The problem is my GPS seems to stop working after a day or two, and won&#8217;t come back until I restart the iPhone or re-sync. Then I want a driving direction helper, something that says out loud, &#8220;turn approaching in 200 feet,&#8221; just like every in-car navigation system.</p>
<p>I want an on-the-go web reader (Ben shared this idea with me). This would offer a way to open/transfer all the tabs or URLs currently in my browser over to the iPhone. Preferably, it would open them all in an offline mode allowing me to then read the articles through out my day, while being on the move. I really would like if this wasn&#8217;t even in Safari since that crashes the iPhone too often.</p>
<p>I want a full Flash player, or at the very least the ability to play Flash videos. There are so many sites with Flash videos and streaming video that are useless on the iPhone. I really wanted to watch the debates on my iPhone because I had to leave in the middle, but while every site on the internet was streaming the debates, not one of them had a way to view the debate on an iPhone. Apparently <a href="http://www.appleinsider.com/articles/08/03/18/adobe_begins_work_on_flash_player_for_iphone.html">Adobe has confirmed working on Flash</a>, but <a href="http://daringfireball.net/2008/09/adobe_speaks_of_flash_player_for_iphone">Apple is likely to block it</a>. Screw you Apple, even Pocket PC phones years ago had Flash.</p>
<p>I want streaming internet radio. Yes, <a href="http://pandora.com/">Pandora</a> and a few others are nice, but why can&#8217;t I just browse and listen to any streaming net radio station? It would be even better if it could allow me to browse many of the well known stations (<a href="http://shoutcast.com">shoutcast</a>), with out having to search through iPhone&#8217;s browser.</p>
<p>I want something similar to <a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=609">Elasticfox</a> for managing and monitoring EC2 instances on the iPhone. Actually beyond that it would be cool to be able to manage a few scripts and SSH credentials on a site. It wouldn&#8217;t allow arbitrary SSH, but you could store ssh login keys and a few scripts it could run and return the results. This would allow you to ahead of time write some scripts to monitor, clean up, restart or do other tasks, which you could then execute and verify the results of remotely over your iPhone. A sysadmin&#8217;s dream, until then I have <a href="http://www.instantcocoa.com/products/pTerm/">pTerm</a> for slow clumsy SSH.</p>
<p>That is all I have for now, but if you have thought of iPhone apps you would like to have leave some comments. If you know of a solution to any of the problems I mention above let me know. Some of these apps I would be willing to pay for so developers get busy.</p>
]]></content:encoded>
			<wfw:commentRss>http://devver.net/blog/2008/10/iphone-apps-i-would-like-to-have/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Tracking down open files with lsof</title>
		<link>http://devver.net/blog/2008/10/tracking-down-open-files-with-lsof/</link>
		<comments>http://devver.net/blog/2008/10/tracking-down-open-files-with-lsof/#comments</comments>
		<pubDate>Thu, 09 Oct 2008 19:23:56 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[Hacking]]></category>

		<category><![CDATA[Testing]]></category>

		<category><![CDATA[Tips &amp; Tricks]]></category>

		<guid isPermaLink="false">http://devver.net/blog/?p=785</guid>
		<description><![CDATA[The other day I was running in a weird error on Devver. After running around twenty test runs on the system, the component that actually runs individual unit tests was crashing due to &#8220;Too many open files - (Errno::EMFILE)&#8221;
Unfortunately, I didn&#8217;t know much more than that. Which files were being kept open? I knew that [...]]]></description>
			<content:encoded><![CDATA[<p>The other day I was running in a weird error on Devver. After running around twenty test runs on the system, the component that actually runs individual unit tests was crashing due to &#8220;Too many open files - (Errno::EMFILE)&#8221;</p>
<p>Unfortunately, I didn&#8217;t know much more than that. Which files were being kept open? I knew that this component loaded quite a few files, and that by default, OS X only allows 256 open file descriptors (<strong><code>ulimit -n</code></strong> will tell you the default on your system). If this was a valid case of needing to load more files, I could just up the limit using <strong><code>ulimit -n &lt;bigger_number&gt;</code></strong>.</p>
<p>Fortunately, a quick Google or two pointed the way to <strong><code>lsof</code></strong>. Unfortunately, my Unix-fu is never nearly as good as I wish and I didn&#8217;t know much about this handy utility. But I quickly discovered that it&#8217;s very useful for tracking down problems like this. I quickly used <strong><code>ps</code></strong> to find the PID of the Devver process and then a quick <strong><code>lsof -p &lt;PID&gt;</code></strong> displayed all the files that the process had open. So easy!</p>
<p>Sure enough, there were a ton of redundant file handles to the file that we use to store information about the Devver run. Armed with this information, it was easy to find the buggy code where we called File.open but failed to ever close the file.</p>
<p>Unfortunately, I still don&#8217;t know how to write a good unit test for this case. I guess I could do something ugly like call sytem(&#8221;lsof -p pid | wc -l&#8221;) before and after calling the code and make sure the number of descriptors stays constant, but that&#8217;s <em>really</em> ugly. Is there a way to test this within Ruby? I&#8217;m open to ideas.</p>
<p>Still, it&#8217;s always good to learn more about a powerful Unix tool. I&#8217;m constanly amazed by the power and depth of the Unit tool set.</p>
]]></content:encoded>
			<wfw:commentRss>http://devver.net/blog/2008/10/tracking-down-open-files-with-lsof/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Sending Files with EventMachine</title>
		<link>http://devver.net/blog/2008/10/sending-files-with-eventmachine/</link>
		<comments>http://devver.net/blog/2008/10/sending-files-with-eventmachine/#comments</comments>
		<pubDate>Wed, 08 Oct 2008 15:22:27 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://devver.net/blog/?p=753</guid>
		<description><![CDATA[Devver has to keep the developer&#8217;s environment synchronized with our servers. To do this our Devver client sends all of the project files to our servers. We currently have a EventMachine client transfer files over SSL to a EventMachine server. We went through various stages and methods of sending files with EventMachine before finding a [...]]]></description>
			<content:encoded><![CDATA[<p>Devver has to keep the developer&#8217;s environment synchronized with our servers. To do this our Devver client sends all of the project files to our servers. We currently have a <a href="http://rubyeventmachine.com">EventMachine</a> client transfer files over SSL to a EventMachine server. We went through various stages and methods of sending files with EventMachine before finding a good solution. On smaller projects we didn&#8217;t even realize how bad our performance was. After bringing up some larger projects we realized we needed to look more into our file transfer performance. Since I couldn&#8217;t find much out on the web about this, I thought sharing some examples of how we had set up our EventMachine clients and servers to send files might be useful to someone else out there.</p>
<p>I got some help from people on the EventMachine mailing list, here is the thread discussing <a href="http://groups.google.com/group/eventmachine/browse_thread/thread/3e16f6cdac91b216">sending large files with EventMachine</a>.</p>
<p>Since I was already playing around with a few of our options, I decided to do some comparisons between using EM.send_data, EM.stream_file_data, an <a href="http://pastie.textmate.org/private/ykjtuipjedrwgzwgggu5w">alternative buffer recommended by James Tucker</a>, our crappy buffer we have been using before we discovered the default <a href="http://rubyeventmachine.com/browser/branches/raggi/lib/protocols/buftok.rb?rev=766">EM BufferedTokenizer</a>, and layering compression on top of the various methods. We had hacked together our buffer tokenizer rather quickly, and it always performed well enough in our initial testing, but it shows why performance tests are worth a little bit of effort. The benchmarks on the various setups are below (This was all done on localhost, it is worth noting that compression helps much more between remote servers).</p>
<p><strong>Sending log file with compression turned off (5 times)</strong><br />
OurBadBufferedTokenizer: 10.40 s<br />
Standard EM BufferedTokenizer: 0.93 s<br />
Tucker&#8217;s BufferedTokenizer: 0.92 s<br />
steam_file_data w/ EM BufferedTokenizer: 0.98 s</p>
<p><strong>Sending log file with compression turned on (5 times)</strong><br />
OurBadBufferedTokenizer: 1.02 s<br />
Standard EM BufferedTokenizer: 0.99 s<br />
Tucker&#8217;s BufferedTokenizer: 1.04 s<br />
steam_file_data w/ EM BufferedTokenizer: N/A can&#8217;t use stream_file_data with on the fly compression</p>
<p><strong>Sending compressed Mp3 file with compression turned off (5 times)</strong><br />
OurBadBufferedTokenizer: 18.55 s<br />
Standard EM BufferedTokenizer: 1.09 s<br />
Tucker&#8217;s BufferedTokenizer: 1.10 s<br />
steam_file_data w/ EM BufferedTokenizer: 1.22 s</p>
<p>Adding compression to already compressed files like mp3s doesn&#8217;t change the time significantly. This is a longer run just to show how the times vary with a larger test. I also tested on full projects and the variance seemed to hold.<br />
<strong>Sending compressed Mp3 file with compression turned off (25 times)</strong><br />
OurBadBufferedTokenizer: N/A takes too long<br />
Standard EM BufferedTokenizer: 5.70 s<br />
Tucker&#8217;s BufferedTokenizer: 4.38 s<br />
steam_file_data w/ EM BufferedTokenizer: 4.82 s</p>
<p>Below are the little tests and examples I was working with. Obviously you won&#8217;t have the same files on your system or Tucker&#8217;s buffer, so I packed everything up as zip. To try everything out just download the <a href="http://devver.net/blog/wp-content/uploads/2008/10/send_file_test.zip">EventMachine sending files tests zip</a>. Then extract, and run &#8216;ruby em_send_file_test.rb&#8217;. Any thoughts or feedback are welcome, I am still learning the ins and outs of EventMachine so feel free to send me any tips.</p>
<pre name="code" class="ruby">
dir = File.expand_path(File.dirname(__FILE__))
unless($LOAD_PATH.member?(dir))
  $LOAD_PATH.unshift(dir)
end

require 'test/unit'
require 'eventmachine'
require 'zlib'
require 'yaml'
require 'ruby-debug'
require 'buffered_tokenizer_pastie'
require 'benchmark'

Thread.abort_on_exception = true

SERVER_PORT = 7999
SERVER_IP = '127.0.0.1'
TOKEN = "|DEFAULTDELIMITED|"
#check with different types of files compression
#results varies a bunch for txt vs compressed like mp3
FILE_NAME = '~/development.log'
#FILE_NAME = '~/Blue.mp3'
COMPRESS = false
#COMPRESS = true

TIMES = 5

class EmClientExample &lt; EventMachine::Connection

  def unbind
    puts "client connection has terminated"
  end

  def process(data)
    puts "client got data: #{data}"
    send_files() if data=="success"
    send(prepare("some_msg")) if data=="filesDone"
    send(prepare("quit")) if data=="ack"
    if(data=="goodbye")
      puts "Client successfully sent all data shutting down!!!!"
      EventMachine::stop_event_loop
    end
  end

  def send_files()
    puts "sending files"
    @files = Array.new(TIMES,[FILE_NAME, Time.now.to_s])
    send_files_loop
  end

  def send_files_loop
    if @files &amp;&amp; @files.length &gt; 0
      file = @files.shift
      EM.next_tick do
        send_file(file[0],file[1])
        send_files_loop
      end
    else
      puts "done syncing files"
      send(prepare("files_completed"))
    end
  end

  def send_file(path,mtime)
    puts "Syncing "+path
    contents = File.read(File.expand_path(path))
    contents = Zlib::Deflate.deflate(contents,Zlib::BEST_SPEED) if COMPRESS
    send(prepare("send_file #{path}, #{mtime}, content:#{contents}"))
  end

  def send(str)
    #puts "sending: #{str}"
    send_data str
  end

  def prepare(str)
    str+TOKEN
  end

  def self.push_start()
    EventMachine.connect(SERVER_IP,SERVER_PORT,self) do |c|
      c.send_files()
    end
  end

end

class EmClientExampleBadBuffer &lt; EmClientExample

  attr_accessor :buffer

  def initialize(*args)
    super
    @buffer = DataBuffer.new
  end

  def receive_data(data)
    @buffer.append(data)
    while(command = @buffer.grab)
      process(command)
    end
  end

  def prepare(str)
    @buffer.prepare(str)
  end

end

class EmClientExampleBuffToken &lt; EmClientExample

  def initialize(*args)
    super
    @recv_buffer = BufferedTokenizer.new(TOKEN)
  end

  def receive_data(data)
    @recv_buffer.extract(data).each do |m|
      process(m)
    end
  end

end

class EmClientExampleStreamBuffToken &lt; EmClientExample

  def initialize(*args)
    super
    @recv_buffer = BufferedTokenizer.new(TOKEN)
  end

  def send_files_loop
    if @files &amp;&amp; @files.length &gt; 0
      file = @files.shift
      EM.next_tick do
        send_file(file[0],file[1])
      end
    else
      puts "done syncing files"
      send(prepare("files_completed"))
    end
  end

  def send_file(path,mtime)
    puts "Syncing "+path
    send("send_file #{path}, #{mtime}, content:")

    EM::Deferrable.future( stream_file_data(File.expand_path(path)) ) {
      send(prepare(""))
      send_files_loop
    }
  end

  def receive_data(data)
    @recv_buffer.extract(data).each do |m|
      process(m)
    end
  end

end

class EmClientExamplePastie &lt; EmClientExample

  def initialize(*args)
    super
    @recv_buffer = BufferedTokenizerPastie.new(TOKEN)
  end

  def receive_data(data)
    @recv_buffer.extract(data).each do |m|
      process(m)
    end
  end

end

class EmServerExample &lt; EventMachine::Connection

  def post_init
    if(@signature)
      client = Socket.unpack_sockaddr_in(get_peername)
      puts "Received a new connection from #{client.last}:#{client.first}"
    end
  end

  def unbind
    puts "server connection has terminated\n"
  end

  def process(data)
    #puts "server: #{data[0..15]}"
    send(prepare("success")) if data=="login"
    send(prepare("filesDone")) if data=="files_completed"
    send(prepare("ack")) if data=="some_msg"
    if data.match(/^send_file/)
      #puts data[0..40]
      puts "received file"
      start = data.index(", content:") + ", content:".length
      ender = data.length
      contents = data[start,ender]
      contents = Zlib::Inflate.inflate(contents) if COMPRESS
      file_contents = File.read(File.expand_path(FILE_NAME))
      if contents != file_contents
        puts "file was corrupted"
        puts "received length: #{contents.length} file lenght: #{file_contents.length}"
        #File.open(File.expand_path("~/copy.file"),"w") do |f|
        #  f &lt;&lt; contents
        #end
      end
    end
    if data=="quit"
      send(prepare("goodbye"))
      close_connection_after_writing
    end
  end

  def prepare(str)
    str+TOKEN
  end

  def send(msg)
    #puts "server sent: #{msg}"
    send_data msg
  end

end

class EmServerExampleBadBuffer &lt; EmServerExample

  def initialize(*args)
    super
    @buffer = DataBuffer.new
  end

  def receive_data(data)
    @buffer.append(data)
    while(command = @buffer.grab)
      process(command)
    end
  end

  def prepare(str)
    @buffer.prepare(str)
  end

end

class EmServerExampleBuffToken &lt; EmServerExample

  def initialize(*args)
    super
    @recv_buffer = BufferedTokenizer.new(TOKEN)
  end

  def receive_data(data)
    @recv_buffer.extract(data).each do |m|
      process(m)
    end
  end

end

class EmServerExamplePastie &lt; EmServerExample

  def initialize(*args)
    super
    @recv_buffer = BufferedTokenizerPastie.new(TOKEN)
  end

  def receive_data(data)
    @recv_buffer.extract(data).each do |m|
      process(m)
    end
  end

end

class DataBuffer
  FRONT_DELIMITER = "0x5b".hex.chr # '['
  BACK_DELIMITER = "0x5d".hex.chr #']'[0].to_s(16).hex.chr
  DELIMITER = "|#{FRONT_DELIMITER}#{FRONT_DELIMITER}#{FRONT_DELIMITER}GT_DELIM#{BACK_DELIMITER}#{BACK_DELIMITER}#{BACK_DELIMITER}#{BACK_DELIMITER}|"
  DELIM_ESCAPE = /#{Regexp.escape(DELIMITER)}/
    DELIM_ESCAPE_END = /#{Regexp.escape(DELIMITER)}\Z/

    def initialize
      @unprocessed = ""
      @commands = []
    end

    def grab
      new_messages = @unprocessed.split(DELIM_ESCAPE)
      while new_messages.length &gt; 1
        @commands &lt;&lt; new_messages.shift
      end
      msg_length = new_messages.length
      if msg_length &gt; 0
        if msg_length == 1 &amp;&amp; (@unprocessed=~DELIM_ESCAPE_END)
          @commands.push(new_messages.shift)
          @unprocessed = ""
        else
          #put the rest of the last statement back into the buffer
          while(cut=@unprocessed.index(DELIM_ESCAPE))
            @unprocessed = (@unprocessed[cut..@unprocessed.length]).sub(DELIMITER,"")
          end
        end
      end
      if @commands.length &gt; 0
        return @commands.shift
      else
        return nil
      end
    end

    def prepare(str)
      str.to_s+DELIMITER
    end

    def append(data)
      @unprocessed = @unprocessed + data
    end

  end

  class EmSendFileTest &lt; Test::Unit::TestCase

    def test_placeholder
      assert true
    end

    def start_server(server_type)
      server_pid = fork {
        EventMachine::run do
          EventMachine::start_server SERVER_IP, SERVER_PORT, server_type
          puts "Server now accepting requests..."
        end
      }
      server_pid
    end

    def start_client(client_type)
      client_pid = fork {
        EventMachine::run { client_type.push_start() }
      }
      client_pid
    end

    def run_against_server_client(client_example, server_example)
      assert_nothing_raised do
        puts Benchmark.realtime {
          server_pid = start_server(server_example)
          #make sure server is up for client to connect to
          sleep(0.2)
          client_pid = start_client(client_example)
          sleep(0.2)

          Process.wait(client_pid)
          puts "client finished"

          #I don't know a clean way to end event machine take it down
          Process.kill('KILL',server_pid)
          Process.waitall
        }
        puts "##############################################################"
      end
    end

    def test_em_send_files_with_em_buffered_tokenizer
      puts "send files test with em buffered tokenizer"
      client_example = EmClientExampleBuffToken
      server_example = EmServerExampleBuffToken
      run_against_server_client(client_example, server_example)
    end

    def test_em_stream_files_with_em_buffered_tokenizer
      puts "steam_file_data test with em buffered tokenizer"
      if COMPRESS == true
        puts "steam_file_data can't be used with on the fly compression"
      else
        client_example = EmClientExampleStreamBuffToken
        server_example = EmServerExampleBuffToken
        run_against_server_client(client_example, server_example)
      end
    end

    def test_em_send_files_with_bad_tokenizer
      puts "send files test with our bad bueffered tokenizer"
      client_example = EmClientExampleBadBuffer
      server_example = EmServerExampleBadBuffer
      run_against_server_client(client_example, server_example)
    end

    def test_em_send_files_with_pastie_tokenizer
      puts "send files test with the pastied tokenizer"
      client_example = EmClientExamplePastie
      server_example = EmServerExamplePastie
      run_against_server_client(client_example, server_example)
    end

  end
</pre>
]]></content:encoded>
			<wfw:commentRss>http://devver.net/blog/2008/10/sending-files-with-eventmachine/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Ruby Tools Roundup</title>
		<link>http://devver.net/blog/2008/10/ruby-tools-roundup/</link>
		<comments>http://devver.net/blog/2008/10/ruby-tools-roundup/#comments</comments>
		<pubDate>Fri, 03 Oct 2008 17:25:13 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[Hacking]]></category>

		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[Tips &amp; Tricks]]></category>

		<guid isPermaLink="false">http://devver.net/blog/?p=567</guid>
		<description><![CDATA[I collected all of the Ruby tools posts I made this week into a single roundup. You can quickly jump to any tool that interests you or read my reviews start to finish. If you just want to read a individual section here are the previous posts Ruby Code Quality Tools, Ruby Test Quality Tools, [...]]]></description>
			<content:encoded><![CDATA[<p>I collected all of the Ruby tools posts I made this week into a single roundup. You can quickly jump to any tool that interests you or read my reviews start to finish. If you just want to read a individual section here are the previous posts <a href="http://devver.net/blog/2008/10/ruby-code-quality-tools/">Ruby Code Quality Tools</a>, <a href="http://devver.net/blog/2008/09/ruby-test-quality-tools/">Ruby Test Quality Tools</a>, and <a href="http://devver.net/blog/2008/09/ruby-performance-tools/">Ruby Performance Tools</a>.</p>
<p>There have been a bunch of interesting tools released for Ruby lately. I decided to write about a few of my favorite Ruby tools and give some of the new tools a shot as well. Simply put, better tools can help you be a better developer. I am ignoring the entire topic of IDEs as tools, as I have written about <a href="http://devver.net/blog/2008/08/leaving-netbeans-for-emacs-as-my-ruby-editor/">Ruby IDEs before</a>, and it is basically a religious war. If you use any Ruby tools I don&#8217;t mention be sure to let me know as I am always interested in trying something new out.</p>
<table border="1" width="100%">
<tbody>
<tr>
<td width="120" valign="top">Tool Name</td>
<td valign="top">Description</td>
</tr>
<tr align="center" bgcolor="grey">
<td colspan="2" align="center" valign="top">Code Quality Tools</td>
</tr>
<tr>
<td width="120" valign="top"><a href="#Roodi">Roodi</a></td>
<td valign="top">Roodi gives developers information about common mistakes in their Ruby code. It makes it easy to clean up your code before things start to get ugly.</td>
</tr>
<tr>
<td width="120" valign="top"><a href="#Dust">Dust</a></td>
<td valign="top">Dust is a new tool that will analyze your code, detect unsafe blocks and unused code. Dust is being created by the same mind behind Heckle</td>
</tr>
<tr>
<td width="120" valign="top"><a href="#Flog">Flog</a></td>
<td valign="top">Flog essentially scores an <a href="http://c2.com/cgi/wiki?AbcMetric">ABC metric</a>, giving you a good understanding of the overall code complexity of any give file or method.</td>
</tr>
<tr>
<td width="120" valign="top"><a href="#Saikuro">Saikuro</a></td>
<td valign="top">When given Ruby source code, Saikuro will generate a report listing the <a href="http://en.wikipedia.org/wiki/Cyclomatic_complexity">cyclomatic complexity</a> of each method found.</td>
</tr>
<tr align="center" bgcolor="grey">
<td colspan="2" align="center" valign="top">Test Quality Tools</td>
</tr>
<tr>
<td width="120" valign="top"><a href="#Heckle">Heckle</a></td>
<td valign="top">Heckle helps test your Ruby tests (how cool is that?). Heckle is a <a href="http://en.wikipedia.org/wiki/Mutation_testing">mutation tester</a>. It alters/breaks code and verifies that tests fail.</td>
</tr>
<tr>
<td width="120" valign="top"><a href="#Rcov">rcov</a></td>
<td valign="top">rcov is the easiest way to get information about your current code coverage.</td>
</tr>
<tr align="center" bgcolor="grey">
<td colspan="2" align="center" valign="top">Ruby/Rails Performance Tools</td>
</tr>
<tr>
<td width="120" valign="top"><a href="#RubyProf">ruby-prof</a></td>
<td valign="top">ruby-prof is a fast and easy-to-use Ruby profiler. The first of four tools that can help you solve performance issues.</td>
</tr>
<tr>
<td width="120" valign="top"><a href="#NewRelic">New Relic</a></td>
<td valign="top">New Relic is one of the three Rails plugin performance debugging and monitoring tools recently released.</td>
</tr>
<tr>
<td width="120" valign="top"><a href="#TuneUp">TuneUp</a></td>
<td valign="top">TuneUp a Rails performance tool from FiveRuns. This tool has an interesting community built around it as well.</td>
</tr>
<tr>
<td width="120" valign="top"><a href="#RubyRun">RubyRun</a></td>
<td valign="top">Ruby Run is a Rails performance tool similar to New Relic and TuneUp</td>
</tr>
</tbody>
</table>
<p>Lets get into it&#8230;</p>
<p><a name="Roodi"></a></p>
<h3>Roodi</h3>
<hr /><a href="http://roodi.rubyforge.org/">Roodi</a> gives you a bunch of interesting warnings about your Ruby code. We are about to release some code, so I took the opportunity to fix up anything Roodi complained about. It helped identify refactoring opportunities, both with long methods, and overly complex methods. The code and tests became cleaner and more granular after breaking some of the methods down. I even found and fixed one silly performance issue that was easy to see after refactoring, which improved the speed of our code. Spending some time with Roodi looks like it could easily improve the quality and readability of most Ruby projects with very little effort. I didn&#8217;t solve every problem because in one case I just didn&#8217;t think the method could be simplified anymore, but the majority of the suggestions were right on. Below is an example session with Roodi</p>
<p><code><br />
dmayer$ sudo gem install roodi<br />
dmayer$ roodi lib/client/syncer.rb<br />
lib/client/syncer.rb:136 - Block cyclomatic complexity is 5.  It should be 4 or less.<br />
lib/client/syncer.rb:61 - Method name "excluded" has a cyclomatic complexity is 10.  It should be 8 or less.<br />
lib/client/syncer.rb:101 - Method name "should_be_excluded?" has a cyclomatic complexity is 9.  It should be 8 or less.<br />
lib/client/syncer.rb:132 - Method name "find_changed_files" has a cyclomatic complexity is 10.  It should be 8 or less.<br />
lib/client/syncer.rb:68 - Rescue block should not be empty.<br />
lib/client/syncer.rb:61 - Method name "excluded" has 25 lines.  It should have 20 or less.<br />
lib/client/syncer.rb:132 - Method name "find_changed_files" has 27 lines.  It should have 20 or less.<br />
Found 7 errors.<br />
</code></p>
<p><strong>After Refactoring:</strong><br />
<code><br />
~/projects/gridtest/trunk dmayer$ roodi lib/client/syncer.rb<br />
lib/client/syncer.rb:148 - Block cyclomatic complexity is 5.  It should be 4 or less.<br />
lib/client/syncer.rb:82 - Rescue block should not be empty.<br />
Found 2 errors.<br />
</code></p>
<p>I did have one problem with Roodi - the errors about rescue blocks just seemed to be incorrect. For code like the little example below it kept throwing the error even though I obviously am doing some work in the rescue code.</p>
<pre name="code" class="ruby">Roodi output: lib/client/syncer.rb:68 - Rescue block should not be empty.
begin
  socket = TCPSocket.new(server_ip,server_port)
  socket.close
  return true
rescue Errno::ECONNREFUSED
  return false
end</pre>
<p><a name="Dust"></a></p>
<h3>Dust</h3>
<hr /><a href="http://github.com/kevinclark/dust/tree/master">Dust</a> detects unused code like unused variables,branches, and blocks. I look forward to see how the project progresses. Right now there doesn&#8217;t seem to be much out there on the web, and the README is pretty bare bones. Once you can pass it some files to scan, I think this will be something really useful. For now I didn&#8217;t think there wasn&#8217;t much I could actually do besides check it out. Kevin, who also helped create the very cool <a href="http://glu.ttono.us/articles/2006/12/19/tormenting-your-tests-with-heckle">Heckle</a>, does claim that code scanning is coming soon, so I look forward to doing a more detailed write up eventually.</p>
<p><a name="Flog"></a></p>
<h3>Flog</h3>
<hr /><a href="http://ruby.sadi.st/Flog.html">Flog</a> gives feedback about the quality of your code by scoring code using the <a href="http://c2.com/cgi/wiki?AbcMetric">ABC metric</a>. Using Flog to help guide refactoring, code cleanup, and testing efforts can be highly effective. It is a little easier to understand the reports after reading <a href="http://ruby.sadi.st/Flog.html">how Flog scores your code</a>, and <a href="http://jakescruggs.blogspot.com/2008/08/whats-good-flog-score.html">what is a good Flog score</a>. Once you get used to working with Flog you will likely want to run it often against your whole project after making any significant changes. There are two easy ways to do this <a href="http://www.brynary.com/2007/9/13/scourging-your-ruby-code-with-flog">a handy Flog Rake task</a> or <a href="http://jakescruggs.blogspot.com/2008/09/metric-fu-is-now-gem.html">MetricFu</a> which works with both Flog and Saikuro.</p>
<p><span style="color: #00ff00;"><span style="color: #0000ff;">Running Flog against any subset of a project is easy, here I am running it against our client libraries</span> </span><br />
<code>find ./lib/client/ -name \*.rb | xargs flog -n -m &gt; flog.log</code></p>
<p><span style="color: #00ff00;"><span style="color: #0000ff;">Here some example Flog output when run against our client code.</span> </span></p>
<pre>Total score = 1364.52395469781

Client#send_tests: (64.3)
    14.3: assignment
    13.9: puts
    10.7: branch
    10.5: send
     4.7: send_quit
     3.4: message
     3.4: now
     2.0: create_queue_test_msg
     1.9: create_run_msg
     1.9: test_files
     1.8: dump
     1.7: each
     1.7: report_start
     1.7: length
     1.7: get_tests
     1.7: -
     1.7: open
     1.7: load_file
     1.6: empty?
     1.6: nil?
     1.6: use_cache
     1.6: exists?
ModClient#send_file: (32.0)
    12.4: branch
     5.4: +
     4.3: assignment
     3.9: send
     3.1: puts
     2.9: ==
     2.9: exists?
     2.9: directory?
     1.9: strftime
     1.8: to_s
     1.5: read
     1.5: create_file_msg
     1.4: info
Syncer#sync: (30.8)
    13.2: assignment
     8.6: branch
     3.6: inspect
     3.2: info
     3.0: puts
     2.8: +
     2.6: empty?
     1.7: map
     1.5: now
     1.5: length
     1.4: send_files
     1.3: max
     1.3: &gt;
     1.3: find_changed_files
     1.3: write_sync_time
Syncer#find_changed_files: (26.2)
    15.6: assignment
     8.7: branch
     3.5: &lt;&lt;
     1.8: to_s
     1.7: get_relative_path
     1.7: &gt;
     1.7: mtime
     1.6: exists?
     1.6: ==
     1.5: prune
     1.4: should_be_excluded?
     1.3: get_removed_files
     1.3: find
... and so on ...</pre>
<p><a name="Saikuro"></a></p>
<h3>Saikuro</h3>
<hr /><a href="http://saikuro.rubyforge.org">Saikuro</a> is another code complexity tool. It seems to give a little less information than some of the others. It does generate nice HTML reports. Like other code complexity tools it can be helpful to discover the most complex parts of your projects for refactoring and to help focus your testing. I liked the way Flog broke things down for me into a bit more detail, but either is a useful tool and I am sure it is a matter of preference depending on what you are looking for.</p>
<p><a href="http://devver.net/blog/wp-content/uploads/2008/09/saikuro.jpg"><img class="alignnone size-medium wp-image-659" title="saikuro" src="http://devver.net/blog/wp-content/uploads/2008/09/saikuro.jpg" alt="saikuro screenshot" width="500" /></a><br />
Saikuro Screenshot</p>
<p><a name="Heckle"></a></p>
<h3>Heckle</h3>
<hr /><a href="http://glu.ttono.us/articles/2006/12/19/tormenting-your-tests-with-heckle">Heckle</a> is an interesting tool to do <a href="http://en.wikipedia.org/wiki/Mutation_testing">mutation testing</a> of your tests. Heckle currently supports Test:Unit and RSpec, but does have a number of issues. I had to run it on a few different files and methods before I got some useful output that helped me improve my testing. The first problem was it crashing when I passed it entire files (crashing the majority of the time). I then began passing it single methods I was curious about, which still occasionally caused Heckle to get into an infinite loop case. This is a noted problem in Heckle, but -T and providing a timeout should solve that issue. In my case it was actually not an infinite loop timing error, but an error when attempting to rewrite the code, which lead to a continual failure loop that wouldn&#8217;t time out. When I found a class and method that Heckle could test I got some good results. I found one badly written test case, and one case that was never tested. Lets run through a simple Heckle example.</p>
<pre><strong>#install heckle</strong>
dmayer$ sudo gem install heckle

<strong>#example of the infinite loop Error Heckle run</strong>
<code>heckle Syncer should_be_excluded? --tests test/unit/client/syncer_test.rb -v</code>
Setting timeout at 5 seconds.
Initial tests pass. Let's rumble.

**********************************************************************
***  Syncer#should_be_excluded? loaded with 13 possible mutations
**********************************************************************
...
2 mutations remaining...
Replacing Syncer#should_be_excluded? with:

2 mutations remaining...
Replacing Syncer#should_be_excluded? with:
... loops forever ...

<strong>#Heckle run against our Client class and the process method</strong>
<code>dmayer$ heckle Client process --tests test/unit/client/client_test.rb</code>
Initial tests pass. Let's rumble.

**********************************************************************
***  Client#process loaded with 9 possible mutations
**********************************************************************

9 mutations remaining...
8 mutations remaining...
7 mutations remaining...
6 mutations remaining...
5 mutations remaining...
4 mutations remaining...
3 mutations remaining...
2 mutations remaining...
1 mutations remaining...

The following mutations didn't cause test failures:

--- original
+++ mutation

 def process(command)

   case command
   when @buffer.Ready then
     process_ready
-  when @buffer.SetID then
+  when nil then
     process_set_id(command)
   when @buffer.InitProject then
     process_init_project
   when @buffer.Result then
     process_result(command)
   when @buffer.Goodbye then
     kill_event_loop
   when @buffer.Done then
     process_done
   when @buffer.Error then
     process_error(command)
   else
     @log.error("client ignoring invalid command #{command}") if @log
   end
 end

--- original
+++ mutation
 def process(command)
   case command
   when @buffer.Ready then
     process_ready
   when @buffer.SetID then
     process_set_id(command)
   when @buffer.InitProject then
     process_init_project
   when @buffer.Result then
     process_result(command)
   when @buffer.Goodbye then
     kill_event_loop
   when @buffer.Done then
     process_done
   when @buffer.Error then
     process_error(command)
   else
-    @log.error("client ignoring invalid command #{command}") if @log
+    nil if @log
   end
 end

Heckle Results:

Passed    :   0
Failed    :   1
Thick Skin:   0

Improve the tests and try again.

<strong>#Tests added / changed to improve Heckle results</strong>
<pre name="code" class="ruby">def test_process_process_loop__random_result
    Client.any_instance.expects(:start_tls).returns(true)
    client = Client.new({})
    client.stubs(:send_data)
    client.log = stub_everything
    client.log.expects(:error).with("client ignoring invalid command this is random")
    client.process("this is random")
  end

  def test_process_process_loop__set_id
    Client.any_instance.expects(:start_tls).returns(true)
    client = Client.new({})
    client.stubs(:send_data)
    client.log = stub_everything
    cmd = DataBuffer.new.create_set_ids_msg("4")
    client.expects(:process_set_id).with(cmd)
    client.process(cmd)
  end</pre>
<p><strong>#A final Heckle run, showing successful results</strong><br />
<code>dmayer$ heckle Client process --tests test/unit/client/client_test.rb</code><br />
Initial tests pass. Let&#8217;s rumble.</p>
<p>**********************************************************************<br />
***  Client#process loaded with 9 possible mutations<br />
**********************************************************************</p>
<p>9 mutations remaining&#8230;<br />
8 mutations remaining&#8230;<br />
7 mutations remaining&#8230;<br />
6 mutations remaining&#8230;<br />
5 mutations remaining&#8230;<br />
4 mutations remaining&#8230;<br />
3 mutations remaining&#8230;<br />
2 mutations remaining&#8230;<br />
1 mutations remaining&#8230;<br />
No mutants survived. Cool!</p>
<p>Heckle Results:</p>
<p>Passed    :   1<br />
Failed    :   0<br />
Thick Skin:   0</p>
<p>All heckling was thwarted! YAY!!!</pre>
<p><a name="Rcov"></a></p>
<h3>rcov</h3>
<hr /><a href="http://eigenclass.org/hiki.rb?rcov">rcov</a> is a <a href="http://en.wikipedia.org/wiki/Code_coverage">code coverage</a> tool for Ruby. If you are doing testing you should probably be monitoring your coverage with a code coverage tool. I don&#8217;t know of a better tool for code coverage than rcov. It is simple to use and generates beautiful, easy-to-read HTML charts showing the current coverage broken down by file. An easy way to make you project more stable is to occasionally spend some time increasing the coverage you have on your project. I have always found it a great way to get back into a project if you have been off of it for awhile. You just need to find some weak coverage points and get to work.<br />
<a href="http://devver.net/blog/wp-content/uploads/2008/09/rcov.jpg"><img class="alignnone size-medium wp-image-603" title="rcov" src="http://devver.net/blog/wp-content/uploads/2008/09/rcov.jpg" alt="Rcov Screenshot" width="500" /></a><br />
rcov screenshot</p>
<p><a name="RubyProf"></a></p>
<h3>ruby-prof</h3>
<hr /><a href="http://ruby-prof.rubyforge.org/">ruby-prof</a> does what every other profiler does, but it is much faster than the one built in to Ruby. It also makes it easy to output the information you are seeking to HTML pages, such as call graphs. If you are just looking for a simple write up to <a href="http://symbiotix.net/articles/ruby-performance-tuning-ruby-prof">get started with ruby-prof</a> I recommend the previous link. I will talk a little more about the kinds of problems I find and how I have solved them with ruby-prof.</p>
<p>I have used ruby-prof a number of times to isolate the ways to speed up my code. I haven&#8217;t used it to identify why an entire Rails application is slow (there are better tools I discuss later for that), but if you have a small but highly important piece of code ruby-prof is often the best way to isolate the problem. I used ruby-prof to identified the two slowest lines of code of a spellchecker, which was rewritten to become twice as fast.</p>
<p>Most recently I used it to identify where the code was spending all of its time in a loop for a file syncer. It turns out that for thousands of files each time through the loop we were continually calling Pathname.new(path).relative_path_from(@dir_path) over and over. Putting a small cache around that call essentially eliminated all delays in our file synchronization. Below is a simple example of how a few lines of code can make all the difference in performance and how easily ruby-prof can help you isolate the problem areas and where to spend your time. I think seeing the code that ruby-prof helped isolate, and the changes made to the code might be useful if you are new to profiling and performance work.</p>
<p><span style="color: #00ff00;"><span style="color: #0000ff;">changes in our spellchecker / recommender</span> </span></p>
<pre name="code" class="ruby">#OLD Way
 alteration = []
    n.times {|i| LETTERS.each_byte {
        |l| alteration &lt;&lt; word[0...i].strip+l.chr+word[i+1..-1].strip } }
 insertion = []
     (n+1).times {|i| LETTERS.each_byte {
        |l| insertion &lt;&lt; word[0...i].strip+l.chr+word[i..-1].strip } }
 #NEW Way
    #pre-calculate the word breakups
    word_starts = []
    word_missing_ends = []
    word_ends = []
    (n+1).times do |i|
      word_starts &lt;&lt; word[0...i]
      word_missing_ends &lt;&lt; word[i+1..-1]
      word_ends &lt;&lt; word[i..-1]
    end

 alteration = []
    n.times {|i|
      alteration = alteration.concat LETTERS.collect { |l|
        word_starts[i]+l+word_missing_ends[i] } }
 insertion = []
    (n+1).times {|i|
      insertion = insertion.concat LETTERS.collect { |l|

        word_starts[i]+l+word_ends[i] } }</pre>
<p><span style="color: #0000ff;">Changes in our file syncer </span></p>
<pre name="code" class="ruby">#OLD
 path_name = Pathname.new(path).relative_path_from(@dir_path).to_s
 #NEW
 path_name = get_relative_path(path)

  def get_relative_path(path)
    return @path_cache[path] if @path_cache.member?(path)
    retval = Pathname.new(path).relative_path_from(@dir_path).to_s
    @path_cache[path] = retval
    return retval
  end</pre>
<p><a name="NewRelic"></a></p>
<h3>New Relic</h3>
<hr /><a href="http://newrelic.com/">New Relic</a> is a performance monitoring tool for Rails apps. It has a great development mode that will help you track down performance issues before they even become a problem, and live monitoring so that you can find any hiccups that are slowing down the production application. The entire performance monitoring space for Ruby/Rails seems to be heating up. I guess it is easy to see why, when scaling has been such an issue for some Rails apps. Just playing around with New Relic was exciting and fun. I could quickly track down the slowest pages, and our most problematic SQL calls, in this case I was testing New Relic on <a href="http://seekler.com">Seekler</a> (an old project of ours) since I didn&#8217;t think I would find much interesting on our current Devver site. Seekler had some glaring performance issues and I think if we had New Relic from the beginning we could have avoided many of them. Sounds like I might have a day project involving New Relic and giving Seekler as much of a performance boost as possible. New Relic turned out to be my favorite of the performance monitoring tools. For a much more detailed writeup check out <a href="http://railstips.org/2008/9/17/rails-app-monitoring">RailsTips New Relic Review</a>.</p>
<p><a href="http://devver.net/blog/wp-content/uploads/2008/09/newrelic.jpg"><img class="alignnone size-medium wp-image-597" title="newrelic" src="http://devver.net/blog/wp-content/uploads/2008/09/newrelic.jpg" alt="newrelic screenshot" width="500" /></a><br />
New Relic screenshot</p>
<p><a name="TuneUp"></a></p>
<h3>TuneUp</h3>
<hr /><a href="http://www.fiveruns.com/products/tuneup">TuneUp</a> another easy-to-install and use Rails performance monitoring solution. The problem I had with TuneUp was I couldn&#8217;t get it working on test app for these sorts of things. I tried running Seekler with TuneUp, but had no luck. I found that many people on the message boards seemed to be having various compatibility issues. I looked at the <a href="http://www.fiveruns.com/products/tuneup/screencast">TuneUp screencast</a> and the kind of information that they give you and I feel like this would be equal to New Relic if it works for you. I am emailing back and forth with FiveRuns support who have been very attentive and helpful, so if I get it working I will update this section.</p>
<p><strong>Update:</strong> <a href="http://fiveruns.com">FiveRuns</a> is pretty amazing with their support. I haven&#8217;t got TuneUp fully working yet, but have made some progress. Some good things to know are that some plugins like safe_erb and output_compression can cause problems with TuneUp. They are aware of the issues, and actively looking into it.</p>
<p><a name="RubyRun"></a></p>
<h3>Ruby Run</h3>
<hr /><a href="http://www.rubysophic.com/products/RubyRun/">RubyRun</a> provides live performance monitoring and debugging tools. I hadn&#8217;t ever heard of this product before I started doing some research while writing this blog article. I am sorry to say but this was the hardest to set up, and gave back less valuable information. I think they need a simple screencast on how to get set up and get useful information back. After getting setup and running I could only get ugly CSV reports that didn&#8217;t tell me much more than the regular Rails log files. I started reading the <a href="http://www.rubysophic.com/download/files/rubyrun-0.9.7.htm">RubyRun Manual</a> but it was about as long as Moby Dick and all I wanted was how to view simple easy-to-read reports which is a snap in New Relic and TuneUp. Since the site didn&#8217;t mention RubyRun providing better data than New Relic or TuneUp which were much more user friendly, I don&#8217;t think I would recommend RubyRun.<br />
<br/><br />
<strong>UPDATE:</strong> After reading about my difficulties with <a href="http://www.rubysophic.com/download/">RubyRun</a> the great folks from <a href="http://www.rubysophic.com/">Rubysophic</a> got in touch with me. They offered to help me get the tool working and posted a <a href="http://www.rubysophic.com/download/files/README.txt">RubyRun quick start guide</a> to their site. I got it working in a snap thanks to an email from their dev and the amazingly simple quick start guide. I still didn&#8217;t get the same depth of information that I got with New Relic, although RubyRun has a ton of settings so it is likely you can get more depth to the reports. Something worth pointing out is that RubyRun is working on Seekler, which I haven&#8217;t been able to get TuneUp running on. So if you have been having problems with TuneUp or New Relic, definitely give RubyRun a look. In the end I think the other offerings are slightly more user friendly (less complex settings), and easier to explore the data (link in the feed to both reports, at least when in developer mode). That being said RubyRun offers some great information and options that the others don&#8217;t and with a bit more UI tuning RubyRun would be at the top of the pack. Thanks to the helpful devs at Rubysophic for helping me to get the most out of RubyRun.</p>
<p><a href="http://devver.net/blog/wp-content/uploads/2008/10/rubyrun.jpg"><img class="alignnone size-medium wp-image-789" title="rubyrun" src="http://devver.net/blog/wp-content/uploads/2008/10/rubyrun.jpg" alt="RubyRun screenshot" width="500" /></a><br />
RubyRun screenshot<br />
<a href="http://devver.net/blog/wp-content/uploads/2008/10/rubyrun2.jpg"><img src="http://devver.net/blog/wp-content/uploads/2008/10/rubyrun2.jpg" alt="RubyRun second screen shot" title="rubyrun2" width="500" class="alignnone size-medium wp-image-791" /></a><br />
screenshot of a different RubyRun report</p>
<p>That is it, hope you learned about a new Ruby tool. So get to work, try a new tool, and get to know your code a little better than you did before.</p>
<p>While I was writing this article, people pointed out to me two more tools worth pointing out. I didn&#8217;t get a chance to try them out or review them, but thought I should point them out. <a href="http://gilesbowkett.blogspot.com/2008/09/towelie-keeps-your-code-dry.html">Towlie</a>, helps keep your code dry by finding redundant methods. and finally <a href="http://vision-media.ca/resources/ruby/source-code-analysis-gem">Source ANalysis (SAN)</a>, which is described as, &#8220;a Ruby gem for analyzing the contents of source code including comment to script ratios, todo items, declared functions, classes, and much more&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://devver.net/blog/2008/10/ruby-tools-roundup/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
