My favourite optimisation trick is to just hit 'break' in the debugger. It's more likely to stop where the program's spending more of its time. It seems like you should have to do it multiple times and gather stats or something, but so often it just goes straight to the heart of the matter.
@ancientjames I've used a similar trick to find a memory leak. I'd arranged to log where every object was created and was wondering how to find a leaked one, and then I realised that almost every object on the heap was leaked, so all I needed to do was pick an un-freed object at random.