Profiling and optimizing
“We should forget about small efficiencies, say about 97% of the time: Premature optimization is the root of all evil.”—Donald Knuth
Although you should always keep this quote in mind, especially when you discover yourself on the slippery slope of premature optimization, sometimes you do need to determine where your program is spending all its time, to see if you can improve the performance of those sections.
A profiler gathers information that allows you to see which parts of the program consume memory and which methods consume maximum time. Some profilers even allow you to disable the garbage collector to help determine patterns of memory allocation.
A profiler can also be a useful tool in detecting threading deadlock in your program.