There is a very good free tool, and you already have it. It's only disadvantage is that it may not be intuitive, to begin with.
When the program is acting slow, pause it under the IDE. Examine the call stack. (I turn off the display of arguments; I'm only interested in the specific lines of code. I copy the whole stack out to a text editor, like notepad.) Do this several times. The slower it is, the fewer samples you're going to need before you see the problem.
If you see one or more statements that are suspiciously popular, like they appear on a healthy fraction of samples (at least two), you should pay attention to those. What I do is take a few more samples until they show up, because I want to understand why they are being executed. That's important, because if I could replace them by something that took a lot less time, I would save a large fraction.
I'll try to explain why it works.
First, the common concept of "bottleneck" is seriously misleading.
Software isn't slow because it has constrictions or "hot" places.
Of course it can have cache misses and so on, but the dominant reason
it is slow is that it is doing more than it needs to - often a lot more.
It goes off on wild nested function call junkets,
with justifications more and more remote.
This shows up as a call tree that is far more bushy than necessary.
All you have to do is find big branches that you can prune off.
That is what the pausing technique does.
So while you're rummaging around for the tool that will help you play detective to locate the elusive "bottleneck", be a tree surgeon, and prune the heaviest branches you can from the call tree, as found by pausing, and keep doing it until you can't.
It's good to be skeptical, but you may be surprised how well it works.