锁定与性能的Python成本,(多线程是否有意义?)

Dan*_*roa 4 python performance multithreading gil

我正在开发一个项目,我的代码吞吐量非常重要,经过一些考虑,我选择使我的程序具有线程.

主线程和子线程都添加和删除两个共享字典.考虑到python中的锁定性能,我是否一直在寻找关于某些输入的互联网,这是一个缓慢的操作,等等.

所以我得到的是因为python实际上实际上根本没有线程(考虑到GIL只能在一个核心上运行)如果我需要在我的应用程序中获得高性能我是否有任何东西可以通过使其成为线程而不是处理IO ?

编辑

实际的问题是(经过深刻的评论后)

多线程在python中是否有意义,因为有GIL?

Jcy*_*rss 11

IMO,锁定解决方案对性能影响很大,主要是当多线程真正等待它时.

获取和释放无竞争锁的成本应该是微不足道的.

该主题显示了对此的测试.

好的,这是使用Python 3.2在Linux下获取和发布无竞争锁的成本:

$ python3 -m timeit \
  -s "from threading import Lock; l=Lock(); a=l.acquire; r=l.release" \
  "a(); r()"

10000000 loops, best of 3: 0.127 usec per loop
Run Code Online (Sandbox Code Playgroud)

以下是调用虚拟Python函数的成本:

$ python3 -m timeit -s "def a(): pass" "a(); a()"

1000000 loops, best of 3: 0.221 usec per loop
Run Code Online (Sandbox Code Playgroud)

这是调用一个简单的C函数(返回False单例)的代价:

$ python3 -m timeit -s "a=bool" "a(); a()"

10000000 loops, best of 3: 0.164 usec per loop
Run Code Online (Sandbox Code Playgroud)

另外,请注意,使用锁作为上下文管理器实际上更慢,而不是您想象的更快:

$ python3 -m timeit -s "from threading import Lock; l=Lock()" \
  "with l: pass"

1000000 loops, best of 3: 0.242 usec per loop
Run Code Online (Sandbox Code Playgroud)

至少在Linux下,至少可以说锁定性能似乎没有太大的提升空间.

PS:RLock现在和Lock一样快:

$ python3 -m timeit \
  -s "from threading import RLock; l=RLock(); a=l.acquire; r=l.release" \
  "a(); r()"

10000000 loops, best of 3: 0.114 usec per loop
Run Code Online (Sandbox Code Playgroud)


Mar*_*ers 6

首先,任何语言的锁定都是性能瓶颈。尽可能减少锁定;例如,不要使用共享目录,而是创建一棵树,并让每个线程在该树的不同分支中工作。

由于您将进行大量 I/O,您的性能问题将存在并且线程不一定会改善问题。首先查看事件驱动架构:

GIL 在这里不太可能是你的问题;例如,每当一个线程输入 C 代码时,它就会被释放(几乎可以肯定在任何 I/O 调用期间)。如果它确实成为瓶颈,请转向多个流程。例如,在我管理的一个大型内网集群上,我们运行 6 个进程,每 2 个线程,以充分利用所有 CPU 内核(其中 2 个进程负载非常轻)。

如果您觉得需要多个进程,请使用该multiprocessing模块或轻松启动服务器的多个实例(每个实例都侦听不同的端口)并使用负载均衡器(例如 haproxy)将流量定向到每个服务器。