There are a few different ways to tackle this problem. cProfile
is great and comes with Python, however many people see multi-threaded profiling as an issue. One way of getting around this is by running separate instances of cProfile for each thread and then combining the results using Stats.add
.
Should that not be as useful as you'd hoped, another alternative could be to use Yappi, which I've had success using for a few special multi-threaded cases. It's got great documentation so you shouldn't have too much trouble setting it up.
For memory specific profiling, check out Heapy. But be warned, it may create some of the largest log files you've ever seen if your code is bad!