Valgrind is a nifty too to do code instrumentation – tell you how much time gets spent in different parts of your code tree. KCachegrind is a visualisation tool for valgrind outputs. They are two separate tools that together can provide useful insight into where you code is slow or doing too much work. To set them up on ubuntu is simple:
sudo apt-get install kcachegrind valgrind
After installation, you can lauch QGIS under valgrind like this:
cd /tmp
valgrind --tool=callgrind --dump-instr=yes --simulate-cache=yes \
--collect-jumps=yes /usr/local/bin/qgis
Note that everything you do in QGIS will take 10x longer because of the overhead valgrind places on it. Now load up a project or do something that you feel is taking longer that it should in QGIS. Then exit QGIS. You will be left with a nice big unintelligible xml file in your /tmp directory. Not to worry though, kcachegrind can open it an make sense of it for you. The file will be called something like:
callgrind.out.18364
So to open it with kcachegrind you can simply do:
kcachegrind callgrind.out.18364
KCacheGrind will take a few moments to digest it and then show you something like the screenshot below:

Application call graph for QGIS in KCacheGrind (click for larger image)
The callgraph can be displayed in a number of different ways and provides extremely useful information if you are trying to identify bottlenecks. In the image above, you can see that when QGIS starts, almost 50% of startup time is spent loading python plugins. There are also views that show how many times a given function is called which can provide some helpful hints as to what to optimise.
Valgrind can also be used to detect memory leaks, but unfortunately for GUI lovers, there isn’t a nice GUI environment to explore the leak report data. Don’t let that put you off though – you can get extremely useful feedback from the tool. Here is the syntax to do a leak check on QGIS:
valgrind --tool=memcheck -v --error-limit=no --leak-check=full /usr/local/bin/qgis
When it finishes running QGIS you will get an extremely verbose report (printed to stdout) that lists all the potential issues. Here is a short snippet of what you might see:
==3144== 627 errors in context 151 of 997:
==3144== Invalid read of size 1
==3144== at 0x4C2A06A: __GI_strcmp (mc_replace_strmem.c:540)
==3144== by 0xA3080BA: _nl_load_locale_from_archive (loadarchive.c:161)
==3144== by 0xA30750D: _nl_find_locale (findlocale.c:107)
==3144== by 0xA306B38: setlocale (setlocale.c:379)
==3144== by 0x680F13F: QgsCoordinateReferenceSystem::setProj4String(QString) (qgscoordinatereferencesystem.cpp:753)
==3144== by 0x680C262: QgsCoordinateReferenceSystem::loadFromDb(QString, QString, QString) (qgscoordinatereferencesystem.cpp:271)
==3144== by 0x680B9B3: QgsCoordinateReferenceSystem::createFromSrsId(long) (qgscoordinatereferencesystem.cpp:213)
==3144== by 0x6776E2B: QgsDistanceArea::setSourceCrs(long) (qgsdistancearea.cpp:64)
==3144== by 0x6776CF9: QgsDistanceArea::QgsDistanceArea() (qgsdistancearea.cpp:45)
==3144== by 0x67C06DE: QgsMapRenderer::QgsMapRenderer() (qgsmaprenderer.cpp:46)
==3144== by 0x71B8D7B: QgsMapCanvas::QgsMapCanvas(QWidget*, char const*) (qgsmapcanvas.cpp:115)
==3144== by 0x5314EC: QgisApp::QgisApp(QSplashScreen*, bool, QWidget*, QFlags<Qt::WindowType>) (qgisapp.cpp:419)
==3144== Address 0x144ed1f1 is 1 bytes inside a block of size 12 free'd
==3144== at 0x4C282ED: free (vg_replace_malloc.c:366)
==3144== by 0xA306BC8: setlocale (setlocale.c:173)
==3144== by 0x680F0B0: QgsCoordinateReferenceSystem::setProj4String(QString) (qgscoordinatereferencesystem.cpp:743)
==3144== by 0x680C262: QgsCoordinateReferenceSystem::loadFromDb(QString, QString, QString) (qgscoordinatereferencesystem.cpp:271)
==3144== by 0x680B9B3: QgsCoordinateReferenceSystem::createFromSrsId(long) (qgscoordinatereferencesystem.cpp:213)
==3144== by 0x6776E2B: QgsDistanceArea::setSourceCrs(long) (qgsdistancearea.cpp:64)
==3144== by 0x6776CF9: QgsDistanceArea::QgsDistanceArea() (qgsdistancearea.cpp:45)
==3144== by 0x67C06DE: QgsMapRenderer::QgsMapRenderer() (qgsmaprenderer.cpp:46)
==3144== by 0x71B8D7B: QgsMapCanvas::QgsMapCanvas(QWidget*, char const*) (qgsmapcanvas.cpp:115)
==3144== by 0x5314EC: QgisApp::QgisApp(QSplashScreen*, bool, QWidget*, QFlags<Qt::WindowType>) (qgisapp.cpp:419)
==3144== by 0x52DFBE: main (main.cpp:607)
Just from starting QGIS and then immediately shutting it down, you will see a rather large list of errors – some of which originate from QGIS itself, and others which originate from some of the underlying libraries we use. The leak detection tool is a hand way to debug when you are getting application crashes and when it seems to be using more memory than you think reasonable. One of these days lets hope that it returns a big fat nothing when we run QGIS on it