我基本上在写端口扫描器(不是真的,但它很接近)。一台一台地 ping 机器很慢,所以我肯定需要某种并行处理。瓶颈绝对是网络 I/O,所以我认为线程就足够了(存在 python 的 GIL),它们更容易使用。但是,使用流程会带来显着的性能提升(15%+)吗?
可悲的是,我没有时间尝试这两种方法并根据一些测量或其他东西选择更好的方法:/
谢谢 :)
我基本上在写端口扫描器(不是真的,但它很接近)。一台一台地 ping 机器很慢,所以我肯定需要某种并行处理。瓶颈绝对是网络 I/O,所以我认为线程就足够了(存在 python 的 GIL),它们更容易使用。但是,使用流程会带来显着的性能提升(15%+)吗?
可悲的是,我没有时间尝试这两种方法并根据一些测量或其他东西选择更好的方法:/
谢谢 :)
如果您没有时间等待性能测试,您可能只想猜测。所以:
multiprocessing
在这里可能没有真正的优势threading
。
每个任务的开销有一个缺点multiprocessing
。您可以通过调整批量大小来解决这个问题,但使用threading
,您不必这样做。
所以,我会使用线程。
但是,我会使用concurrent.futures.ThreadPoolExecutor
,所以当您稍后有时间时,您可以尝试单行更改ProcessPoolExecutor
并比较性能。
我想我会把它作为一个潜在的答案发布。
我用过,比如 Gevent,但另一个库也可以。
这取自 Gevent 的网站
import gevent
from gevent import socket
urls = ['www.google.com', 'www.example.com', 'www.python.org']
jobs = [gevent.spawn(socket.gethostbyname, url) for url in urls]
gevent.joinall(jobs, timeout=2)
[job.value for job in jobs]
['74.125.79.106', '208.77.188.166', '82.94.164.162']
这将为您提供一种并发方法,而无需线程/进程的开销 =)
一般来说,您希望多处理模块在处理中利用额外的 CPU 内核。由于每个进程都有自己的 GIL,因此它们可以进行 CPU 密集型调用,而无需考虑任何特定调用是否会在其持续时间内锁定 GIL。
从编程的角度来看,主要的缺点是共享内存要少得多。实际上,您只能使用共享对象(例如multiprocessing.Array
或)发送数据multiprocessing.Value
。而且由于共享的内存太少,每次创建另一个实例时,您的内存占用量就会增加一倍。
线程可能是一个可行的选择,但如果您想要最大效率,您应该使用异步方法。有许多用于异步网络 I/O 的框架,尽管最著名的可能是Twisted。