
The XDebug/KCachegrind combo is pretty much the bees knees as far as fixing performance bugs are concerned, but a (fairly) recent tightening of the rules regarding the cachegrind format can sometimes lead to a fragmented call graph.
The problem happens with a recent KCachegrind, and XDebug before version 2.1.1. In this case, XDebug doesn’t fill in the called file name when recording a function call, expecting KCachegrind to be smart and pick it up from the functions name.
This assumes that you’ll never have 2 functions with the same signature declared in 2 different places.
In PHP this is a valid assumption, PHP will break if you try to re-declare a function. In other languages though, scoping can make this doable (C/C++ in particular handle this case). As a result, KCachegrind stopped trying to be smart, and insisted on having the called file specified to it, creating duplicate calls if it couldn’t find them, fixing the C/C++ case, but needing an update from XDebug. This update came with 2.1.1, but some distributions still out there (ubuntu 10.04 in particular) don’t carry this version. These distributions will still give you invalid cachegrind data.
To fix this, I’ve written a small script that provides the missing metadata, allowing a more fluid analysing of the graph.
With out more waiting, here’s the script:
#!/bin/bash
file=$1
symboles_file=${file}.symboles
grep -E '(^fn|^fl)' $file | awk -F '=' '/^fl/{fl=$2;} /^fn/ {if (fl!="") {print $2 "=" fl; fl=""}}' | sort | uniq > $symboles_file
awk -F '=' 'FNR==NR{map[$1]=$2;} /^cfn/{print "cfl=" map[$2]} FNR!=NR{print} ' $symboles_file $file
rm $symboles_file
Here’s all you need to know about usage:
$./trace_fixer.sh cachegrind.out.myId > cachegrind.out.fixed.myId