I already wrote about using SystemTap with Ruby. Today I want to extend the last example I linked at the very end of my article. It's a nice example script of Ruby "top" utility.

Today I was investigating our Katello unit test codebase. We have over 1600 examples and the number is rising every day. The whole run is about seven minutes long. The utility gives very nice first look on the app showing the top Ruby calls. But there is one issue - it covers and shows lot of code. The output is unfiltered. But wait, there is the SystemTap!

I was interested only in files that are in /usr/share/katello directory structure. Well, easy help. One simple if-statement and we only see what we want.

cat ./trace-ruby-rails.stp
#!/usr/bin/stap

global fn_calls;

probe ruby.function.entry
{
if (isinstr(file, "katello")) fn_calls[pid(), file, methodname, line] <<< 1;
}

probe timer.ms(4000) {
ansi_clear_screen()
printf("%6s %80s %6s %25s %6s\n",
"PID", "FILENAME", "LINE", "FUNCTION", "CALLS")
foreach ([pid, filename, funcname, lineno] in fn_calls- limit 15) {
printf("%6d %80s %6d %25s %6d\n",
pid, filename, lineno, funcname,
@count(fn_calls[pid, filename, funcname, lineno]));
}

delete fn_calls;
}
Before you run this, make sure you make your terminal wide enough. Also I highly recommend to set MAXMAPENTRIES value which defaults to 2k which is not enough and you can run into problems. It's a simple:
stap -DMAXMAPENTRIES=10240 ./trace-ruby-rails.stp
After I optimized our codebase I concentrated on Rails stack. Changing one lines shows you top calls from "active*" gems:
...
if (isinstr(file, "/active")) fn_calls[pid(), file, methodname, line] <<< 1;
...
By the way with some help of Ivan Nečas we have found three small issues which gave us 25 % boost. Not bad? I think I love SystemTap.