Thursday Nov 01, 2007

Visualizing callgraphs via dtrace and ruby

The allfrom.d dscript can be used to display all function entry/exits caused by a function call. When call graphs are deep, or long, a visual representation is very helpful to understand the flow as well as how much time each function consumed. The output displayed is inspired by Roch's CallStackAnalyzer which was in turn inspired by the work on vftrace by Jan Boerhout.

I wrote a simple ruby script to post process the allfrom.d output and generate a SVG image. The advantage of using SVG is that you can use javascript to provide added functionality. For example, you can hover your mouse over any block to see the name of the function and its elapsed time. Similarly, you could add support for Zoom and Pan

Unfortunately, I am having problems with blogs.sun.com serving svg files with the right mime type. So I have included a png image below. You can save the svg files somewhere on your computer and view them using Firefox.

A sample for the connect(3socket) is shown below. The input file used to generate it is available here. The width of each box indicates how long the function took. Y axis indicates call depth.


If you are interested, you can also check out


To use the scripts to generate your own call stacks, download the following two [ 1, 2] ruby source files. For example, to generate the above callgraph, you can use

dtrace -s allfromkernel.d acccept > accept.log
ruby function_call_graph.rb accept.log > accept.svg

Note that the script does not work reliably for asynchronous function calls, or cases where the thread changes CPU. If there is sufficient interest, I might be tempted to add those in :-)

Thursday Oct 18, 2007

Marshalling trouble with JRuby/Rails?

If you are getting exceptions like the one below with JRuby and Rails, read on for the solution
Rendering /tmp/neel/jruby-1.0.1/lib/ruby/gems/1.8/gems/actionpack-1.13.5/lib/
   action_controller/templates/rescues/layout.rhtml (500 Internal Error)
no marshal_dump is defined for class Java::JavaObject
/tmp/neel/jruby-1.0.1/lib/ruby/1.8/pstore.rb:349:in `dump'
/tmp/neel/jruby-1.0.1/lib/ruby/1.8/pstore.rb:327:in `transaction'
/tmp/neel/jruby-1.0.1/lib/ruby/1.8/cgi/session/pstore.rb:81:in `update'
/tmp/neel/jruby-1.0.1/lib/ruby/1.8/cgi/session/pstore.rb:88:in `close'
/tmp/neel/jruby-1.0.1/lib/ruby/1.8/cgi/session.rb:324:in `close'
The problem is that Rails is trying to store the Java object in the session store. The default session store is the filesystem, and it fails since it cannot marshal a Java Object. Setting the session store to use memory instead of the filesystem solves the problem.

In config/environment.rb set

config.action_controller.session_store = :memory_store

Sunday Oct 14, 2007

Ruby lovers rejoice!

My friend Prashant is working on delivering Ruby into Solaris! I am sure all Ruby lovers really appreciate your efforts Prashant! I no longer have to download and compile Ruby (or alternatively, install CoolStack) for every machine I use. If you are interested, checkout and contribute to the ARC case.

Wednesday Mar 07, 2007

ASCII Bar graph using Ruby

I am a big Ruby fan. In the spirit of sharing, here is a small ruby script that draws ASCII bar graphs.

#!/bin/env ruby -w
# Given an array, print it as a bar graph
# Use it at your own risk

class HorizBar
  WIDTH = 72
  HEIGHT = 16
  def initialize(array)
    @values = array
  end
  def draw
    #Adjust X axis when there are more than WIDTH cols
    if @values.length > WIDTH then
      old_values = @values;
      @values = []
      0.upto(WIDTH - 1){ |i| @values << old_values[i\*old_values.length/WIDTH]}
    end
    max = @values.max
    # initialize display with blanks
    display = Array.new(HEIGHT).collect { Array.new(WIDTH, ' ') }
    @values.each_with_index do |e, i|
      num= e\*HEIGHT/max
      (HEIGHT - 1).downto(HEIGHT - 1 - num){|j| display[j][i] = '|'}
    end    
    display.each{|ar| ar.each{|e| putc e}; puts "\\n"} #now print
  end
end

# Sample usage 1
sample = [28829, 29095, 29301, 31827, 43478, 52937,62969]
HorizBar.new(sample).draw

# Another Sample usage
a = []
100.times { a << rand(100)}
HorizBar.new(a).draw

It produces output similar to



 |  |  |             |               |                |      |
 |  |  |             |      |   |    |     |   |      |     ||
 |  |  |             |      ||  |    |    ||   |  |   |     ||
 |  |  |           | |      ||  |    | |  ||   |  |   |   | ||
|| ||  |           | |      ||| |    | |  |||  || |   |   | ||       |
|| ||  |      |   || |      ||| |    | |  |||  || |   |   | ||    |  |
|| ||  |   |  |   || ||   | ||| |    | |  |||  || |   |   | ||    |  |
|| ||  |   |  |   || ||   | ||| | |  | |  |||  || |   |   | ||    |  |
|||||  |   |  |   || |||  | ||| | |  |||  |||  || |   |   | ||    | ||
|||||  |   |  |   || |||  | ||| | | |||||||||  || |  ||   | ||    | ||
|||||  || ||  | | || ||| || ||| ||| |||||||||  || |  ||   ||||    | ||
|||||  || ||  | | || ||| || ||| ||| |||||||||| || || || | ||||    | |||
||||| |||||| || | || |||||| ||| ||| |||||||||| || || || |||||| | ||||||
||||| |||||| ||||||| |||||| ||| |||||||||||||| |||||||| |||||| | ||||||
||||| |||||||||||||||||||||||||||||||||||||||||||||||||||||||| ||||||||
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

Rudimentary, but quite useful if you want to look at some data quickly.

About

realneel

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today