Skip to content

Profiling and Benchmarks

Jason R. Clark edited this page Apr 23, 2015 · 1 revision

Performance is a feature, so on the Shoes project we have a number of different tools that can be used for figuring out why things are slow.

Profiling

When you find an area of a Shoes app that's slow, here are a few tools to help you pin down what's slow.

jruby --profile

JRuby ships with a builtin profiler. It's got some good documentation but for the basics you just have to pass either --profile or --profile.graph to your jruby invocation and on app exit you'll get the results.

How do you do that with Shoes, though, since you aren't calling jruby yourself? Luckily, JRuby supports an ENV variable that can be set with options just as if they'd been passed on the command-line. So to profile your Shoes app, try this on for size:

JRUBY_OPTS='--profile' bin/shoes samples/simple-face.rb

--profile provides a broad summary of the various method times that were called. This can be useful for getting a high-level picture and finding super-egregious perf problems.

--profile.graph gives a more details summary with individual call trees. Be prepared, the output of this is large and sometimes hard to wade through, but look for big exclusive times and percentages, and those will point you to who's calling them.

newrelic-shoes

Sometimes the output of jruby --profile can be overwhelming and hard to tally up, and that's where newrelic-shoes comes into the picture. This does specific tracing around key points in Shoes applications, has toggling built in (so you don't start tracing until you're ready), and should be easy to extend.

To use newrelic-shoes, just add the following in your Gemfile:

gem 'newrelic-shoes'

You should see a message on the command-line after starting up indicating New Relic Shoes is available. Press Ctrl+Alt+N to start tracing, and on exit you'll see metrics for the specific methods that newrelic-shoes traces.

If newrelic-shoes isn't tracing what you need, look into the code and submit a PR--instrumenting new things is just a line or two of code.

VisualVM

The new version of Shoes is based on JRuby, and with that comes all the power of the JVM. One great tool in that space is http://visualvm.java.net/. You can attach it to a JRuby process and then monitor with all the JVM goodness.

The one downside to this tool is that it doesn't know anything about JRuby, so you won't see Ruby methods, but instead how they're implemented in Java. But some of the other memory and CPU stats can be very useful to monitor and get a broad picture of how an app's behaving.

Benchmarks

Perf issues often creep up in real apps, but they can also be hard to pin down there. That's where benchmarks come into the picture. In Shoes we have a /benchmark directory which contains a variety of different benchmarks based around scenarios that we've needed to test before.

There are two flavors of benchmarks you can write: microbenchmarks and app benchmarks.

Microbenchmarks will focus on individual small classes or methods, and often can be run to completion without human intervention. Standard practice in these cases is to use the benchmark-ips gem for getting out statistics on how different cases are performing. https://github.com/shoes/shoes4/blob/master/benchmark/dimension.rb is an example of a microbenchmark.

App benchmarks pick up where microbenchmarks can't go. These are often necessary for things like painting and event response code. Keep the app as simple as possible, with a clear action to trigger (often a button click), and a clear indication of when the action is done so things can be timed. One example is https://github.com/shoes/shoes4/blob/master/benchmark/paras.rb. Sometimes these can be timed with benchmark-ips, others might be more appropriate to just benchmark, or sometimes you can use newrelic-shoes to get your timing data after a run.

If you encounter a performance issue, logging a new benchmark that reveals the problem and can be used to demonstrate whether it's fixed or not is a huge help!