如何在 Python 中分析多线程程序?
我正在用 Python 开发一个本质上的多线程模块,我想知道它把时间花在哪里了。 cProfile 似乎只分析主线程。 有没有办法分析计算中涉及的所有线程?
I'm developing an inherently multithreaded module in Python, and I'd like to find out where it's spending its time. cProfile only seems to profile the main thread. Is there any way of profiling all threads involved in the calculation?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
查看 Dask 项目中的
mtprof
:https://github.com/dask/mtprof
它是
cProfile
的直接替代品,如果您的线程以通常的方式启动并在主线程之前完成,则会将其统计数据汇总到相同的报告统计数据中。 对我来说就像一个魅力。Check out
mtprof
from the Dask project:https://github.com/dask/mtprof
It's a drop-in replacement for
cProfile
that, if your threads are launched in the usual way and complete before your main thread, will roll-up their stats into the same reporting stats. Worked like a charm for me.从 2019 年开始:我喜欢 vartec 的建议,但真的很喜欢代码示例。 因此我建立了一个 - 实施起来并不困难,但你确实需要考虑一些事情。 这是一个工作示例(Python 3.6):
您可以看到结果考虑了 Thread1 和 Thread1 所花费的时间。 thread2 调用 thread_func()。
您需要在代码中进行的唯一更改是子类化 threading.Thread,重写其 run() 方法。 只需进行最少的更改即可轻松地分析螺纹。
From 2019: I liked vartec's suggestion but would have really liked a code exemple. Therefore I built one - it is not crazy hard to implement but you do need to take a few things into account. Here's a working sample (Python 3.6):
You can see that the results take into account the time spent by Thread1 & thread2 calls to the thread_func().
The only changes you need in your code is to subclass threading.Thread, override its run() method. Minimal changes for an easy way to profile threads.
我不知道有任何分析应用程序支持 python 的此类功能 - 但您可以编写一个 Trace 类来写入日志文件,在其中放入操作何时开始、何时结束以及操作时间的信息消耗了。
这是解决您问题的简单而快速的解决方案。
I don't know any profiling-application that supports such thing for python - but You could write a Trace-class that writes log-files where you put in the information of when an operation is started and when it ended and how much time it consumed.
It's a simple and quick solution for your problem.
请参阅 yappi(另一个 Python 分析器)。
Please see yappi (Yet Another Python Profiler).
您可以在每个线程中运行单独的
cProfile
实例,然后合并统计信息,而不是运行一个cProfile
。Stats.add()
自动执行此操作。Instead of running one
cProfile
, you could run separatecProfile
instance in each thread, then combine the stats.Stats.add()
does this automatically.如果您愿意做一些额外的工作,您可以编写自己的分析类来实现
profile(self, frame, event, arg)
。 每当调用函数时都会调用它,并且您可以相当轻松地设置一个结构来从中收集统计信息。然后,您可以使用
threading.setprofile
在每个线程上注册该函数。 调用该函数时,您可以使用 threading.currentThread() 来查看它在哪个线程上运行。 更多信息(和准备运行的配方)在这里:http://code.activestate.com/ Recipes/465831/
http://docs.python.org/库/threading.html#threading.setprofile
If you're okay with doing a bit of extra work, you can write your own profiling class that implements
profile(self, frame, event, arg)
. That gets called whenever a function is called, and you can fairly easily set up a structure to gather statistics from that.You can then use
threading.setprofile
to register that function on every thread. When the function is called you can usethreading.currentThread()
to see which it's running on. More information (and ready-to-run recipe) here:http://code.activestate.com/recipes/465831/
http://docs.python.org/library/threading.html#threading.setprofile
鉴于不同线程的主要功能不同,您可以使用 此处。
Given that your different threads' main functions differ, you can use the very helpful
profile_func()
decorator from here.