在多线程Python中查找CPU占用过高的插件

8
我有一个用Python编写的系统,使用多个开发人员编写的插件处理大量数据,这些开发人员的经验水平不同。
基本上,应用程序启动几个工作线程,然后提供数据。每个线程确定要为项目使用哪个插件,并要求其处理该项目。插件只是具有特定函数定义的Python模块。处理通常涉及正则表达式,不应超过一秒钟左右。
偶尔,其中一个插件需要数分钟才能完成,将CPU占用率保持在100%。这通常是由于子优化的正则表达式与暴露该低效性的数据项配对导致的。
这就是事情变得棘手的地方。如果我怀疑是谁干的,我可以检查它的代码并找到问题。但是,有时我就没有那么幸运。
  • 我不能使用单线程。如果这样做,可能需要数周时间才能重现该问题。
  • 在插件上放置计时器没有帮助,因为当它冻结时,它会带走GIL,并且所有其他插件也需要几分钟才能完成。
  • (如果你想知道,SRE引擎不释放GIL)。
  • 据我所知,分析 在多线程时几乎没什么用。

除了将整个架构重写成多进程外,我有什么办法可以找出谁在占用我的CPU?

补充:回答一些评论:

  1. 在Python中对多线程代码进行剖析并没有什么用,因为剖析器测量的是总函数时间而不是活跃CPU时间。尝试cProfile.run('time.sleep(3)')以了解我的意思。(参考rog [最后一条评论])。

  2. 之所以单线程处理比较棘手,是因为20,000个项目中只有1个项目引起了问题,我不知道是哪一个。多线程运行可以在大约一个小时内处理完20,000个项目,而单线程处理可能需要更长时间(涉及很多网络延迟)。这里还有一些更复杂的情况,我现在不想深入讨论。

话虽如此,尝试串行化调用插件的特定代码也不失为一个好主意,这样一个插件的时间不会影响其他插件的时间。我会尝试并回报结果。


在多线程中,哪部分性能分析信息出现了问题? - Hank Gay
请问您能否解释一下为什么单线程不起作用?如果插件从未释放GIL,那么您将无法进行任何并行处理,而使用多线程也无济于事。 - Michael Kuhn
1
“我不能使用单线程。如果我这样做,要复现问题可能需要数周时间。” 这是错误的。也许使用单线程会比多线程更快得到结果。 - nosklo
4个回答

3

你显然不需要多线程,只需要并发,因为你的线程不共享任何状态:

尝试使用 multiprocessing 代替多线程

单线程 / N 个子进程。在这里,你可以计时每个请求,因为没有 GIL 被持有。

另一种可能性是摆脱多个执行线程,并使用基于事件的网络编程(即使用 Twisted)。


多进程的另一个优点是你可以“看到”进程并获取其pid。 - monkut

0

正如你所说,由于GIL的存在,无法在同一进程内完成。

我建议启动第二个监视进程,该进程监听来自原始应用程序中另一个线程的生命信号。一旦指定时间内缺少了时间信号,监视器就可以关闭并重新启动您的应用程序。


0
如果您控制框架,建议禁用除一个插件外的所有插件并查看。 基本上,如果您有P1、P2...Pn插件, 在第一次运行中禁用P1,在第二次运行中禁用P2等等, 这样会比您的多线程运行快得多,因为没有GIL阻塞,并且您很快就会知道哪个插件是罪魁祸首。

0

我仍然会看nosklo的建议。您可以在单个线程上进行分析以找到该项,并在非常长的运行时间内获取转储,可能会发现罪魁祸首。是的,我知道有20,000个项目需要很长时间,但有时您必须忍受并找到该死的东西,以使自己相信问题已被捕获和处理。运行脚本,然后去做其他有意义的事情。回来分析结果。这就是有时区分男人和男孩的方法;-)

或/和,添加记录信息以跟踪从每个插件处理的每个项目的执行时间。在程序运行结束时查看日志数据,并查看哪个与其他项目相比运行时间过长。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接