我正在做一个项目,我的代码吞吐量非常重要,经过一番考虑,我选择让我的程序线程化。
主线程和子线程都从两个共享字典中添加和删除。考虑到python中锁定的性能,我一直在浏览互联网上的一些输入,它是一个缓慢的操作等等。
所以我得到了什么,因为python实际上根本没有线程化(考虑到GIL只在一个核心上工作)如果我需要在我的应用程序中获得高性能,除了处理IO之外,我有什么可以通过使其线程化来赢得的?
编辑
实际问题是(在有见地的评论之后)
既然有 GIL,多线程在 python 中有意义吗?
我正在做一个项目,我的代码吞吐量非常重要,经过一番考虑,我选择让我的程序线程化。
主线程和子线程都从两个共享字典中添加和删除。考虑到python中锁定的性能,我一直在浏览互联网上的一些输入,它是一个缓慢的操作等等。
所以我得到了什么,因为python实际上根本没有线程化(考虑到GIL只在一个核心上工作)如果我需要在我的应用程序中获得高性能,除了处理IO之外,我有什么可以通过使其线程化来赢得的?
编辑
实际问题是(在有见地的评论之后)
既然有 GIL,多线程在 python 中有意义吗?
IMO,锁定解决方案对性能的影响很大,主要是在多线程真正等待它时。
获取和释放非竞争锁的成本应该是微不足道的。
这个线程显示了一个关于那个的测试。
好的,这是在 Linux 下使用 Python 3.2 获取和释放非竞争锁的成本:
$ 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以下是调用虚拟 Python 函数的成本:
$ python3 -m timeit -s "def a(): pass" "a(); a()" 1000000 loops, best of 3: 0.221 usec per loop这是调用一个普通的 C 函数(返回 False 单例)的成本:
$ python3 -m timeit -s "a=bool" "a(); a()" 10000000 loops, best of 3: 0.164 usec per loop另外,请注意,使用锁作为上下文管理器实际上更慢,而不是你想象的更快:
$ python3 -m timeit -s "from threading import Lock; l=Lock()" \ "with l: pass" 1000000 loops, best of 3: 0.242 usec per loop至少在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
首先,任何语言的锁定都是性能瓶颈。尽可能减少锁定;例如,不要使用共享目录,而是创建一棵树,并让每个线程在该树的不同分支中工作。
由于您将执行大量 I/O,因此您的性能问题将存在,并且线程不一定会改善问题。首先研究事件驱动的架构:
GIL 在这里不太可能是您的问题;例如,只要线程进入 C 代码(几乎可以肯定在任何 I/O 调用期间),它就会被释放。如果它确实成为瓶颈,请转移到多个流程。例如,在我管理的一个大型 Intranet 集群上,我们运行 6 个进程,每 2 个线程,以充分利用所有 CPU 内核(其中 2 个进程负载非常轻)。
如果您觉得需要多个进程,请使用该multiprocessing模块或轻松启动服务器的多个实例(每个实例侦听不同的端口)并使用负载平衡器(如 haproxy)将流量引导到每个服务器。