19

从我在评论中的问题到对“带有嵌套 Web 请求的 Gevent 池”问题的答案的回答:

假设一个有大量任务,使用 gevent.spawn(...) 同时生成所有任务而不是使用 gevent 池和 pool.spawn(...) 来限制并发数有什么缺点吗?绿叶菜?

表述方式不同:即使要解决的问题不需要“限制并发”,gevent.Pool 是否有任何优势?

知道什么会构成这个问题的“大量”吗?

4

2 回答 2

21

在处理很多事情时,它更干净,也是一种很好的做法。几周前我遇到了这个问题,我正在使用 gevent spawn 来验证一堆针对 DNS 的电子邮件,数量约为 30k :)。

from gevent.pool import Pool
import logging
rows = [ ... a large list of stuff ...]
CONCURRENCY = 200 # run 200 greenlets at once or whatever you want
pool = Pool(CONCURRENCY)
count = 0

def do_work_function(param1,param2):
   print param1 + param2

for row in rows:
  count += 1 # for logging purposes to track progress
  logging.info(count)
  pool.spawn(do_work_function,param1,param2) # blocks here when pool size == CONCURRENCY

pool.join() #blocks here until the last 200 are complete

我在测试中发现,当 CONCURRENCY 约为 200 时,我的机器负载将在 EC2 m1.small 上徘徊在 1 左右。不过我做的有点天真,如果我再做一次,我会运行多个池并在它们之间休眠一段时间,以尝试更均匀地分配 NIC 和 CPU 上的负载。

要记住的最后一件事是密切关注您打开的文件,并在需要时增加:http ://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files 。我正在运行的 greenlet 每个 greenlet 占用大约 5 个文件描述符,所以如果你不小心的话,你可以很快用完。如果您的系统负载高于 1,这可能没有帮助,因为无论如何您都会开始看到收益递减。

于 2013-11-07T02:11:55.920 回答
11

从谷歌来到这里并决定进行一些快速测试以产生越来越多N的绿叶。分享结果,因为它们可能对其他搜索者有用:

# 1 greenlet
real    0m1.032s
user    0m0.017s
sys     0m0.009s

# 100 greenlets
real    0m1.037s
user    0m0.021s
sys     0m0.010s

# 1,000 greenlets
real    0m1.045s
user    0m0.035s
sys     0m0.013s

# 10,000 greenlets
real    0m1.232s
user    0m0.265s
sys     0m0.059s

# 100,000 greenlets
real    0m3.992s
user    0m3.201s
sys     0m0.444s

所以多达 1,000 个 greenlets 并且性能损失很小,但是一旦你开始达到 10,000+ 个 greenlets,一切都会变慢。

测试代码:

import gevent

N = 0

def test():
    gevent.sleep(1)

while N < 1000:
  N += 1
  gevent.spawn(test)

gevent.wait()
于 2014-12-20T23:22:31.287 回答