Per-class heap plots with py-jstack

Having to profile a webapp that filled the Java Heap, I wrote a simple python module that plots the size of the heap consumed by each class.

It uses the files generated by #jmap -histo $(pidof java); which tracks the memory per-class consumption.

Once you generate your files with something like:

while sleep 5; do
    jmap -histo $(pidof java) > /tmp/histo.$(date %s)
done

You can load the jplot module included in https://github.com/ioggstream/py-jstack/.
Using ipython makes things even easier!

#git clone https://github.com/ioggstream/py-jstack/ 
#cd py-jstack;
#ipython;
ipython$ import jplot

Once you loaded the module, you have to list the files to parse
and generate a table containing the classes and their memory occupation in time
for the first 30 greedy classes.

ipython$ files = ! ls /tmp/histo.*
ipython$ table = jplot.jhisto(files, limit=30, delta=False)

What does the `table` dictionary contain? A list of #instance and memory size in time

ipython$ cls = 'java.lang.String'
ipython$ print(table[cls][:10]) 
[(452588.0, 18103520.0), # values in 1st file
 (186198.0, 7447920.0), # values in 2nd file
 (229789.0, 9191560.0), # values in 3rd file
...]
ipython$ memory_for_string = zip(*table[cls])[1]
ipython$ max_memory_for_string = max(memory_for_string)

Using matplotlib we can plot too, and have a glimpse of which class is misbehaving…

ipython$ jplot.plot_classes(table, limit=10)

You spin me right round (like an hard disk)

You can get some info about your disk work with bb-iostat

Another nice tool – distributed with the bonnie++ suite – is zcav. zcav measures read thruput in function of the sector number.

As the disk spins at constant angular speed (eg. 7200RPM aka 120Hz), and data is stored on the plates at various distance from the spindle, the speed of the outer part of the disk (first sectors) is higher than the inner one.

Ex. Audio CD reads data at a constant speed. To achieve that, the spindle starts at 3.5Hz at the beginning of the disc (the outer part) to end at ~8Hz at the end.

Ex. On a 2.5inch (63mm) HD @120Hz:
* the outer data speed is 2·π· 63mm · 120Hz ~ 47m/s
* a mean data speed is the half 2 · π · 32mm · 120Hz ~ 24m/s

To get some numbers, run zcav on two distant partitions:

sudo zcav -c1 -lsda1 -f/dev/sda1;
sudo zcav -c1 -lsda8 -f/dev/sda8;

and nicely plot that data with gnuplot:

#gnuplot

unset autoscale x
set autoscale xmax
unset autoscale y
set autoscale ymax
set xlabel “Block offset (GB)”
set ylabel “MB/s”
set key right bottom
plot “sda1” title “/other”, “sda8” title “/home”

And here’s an extract from my sda8 test. The read performance loss is sensible!

#block offset (GiB), MiB/s, time
0.00 63.13 4.055
10.00 61.27 4.178
20.00 57.69 4.438
30.00 60.13 4.257
40.00 54.08 4.733
50.00 56.34 4.544
60.00 55.91 4.579
….
140.00 42.94 5.962
150.00 38.96 6.571
160.00 38.62 6.628
170.00 34.91 7.333