Gevent: недостаток в нерестах большого количества зеленых?

Следуя моему вопросу в комментарии к этому ответу на вопрос "Пул Gevent с вложенными веб-запросами" :

Предполагая, что у одного есть большое количество задач, есть ли недостаток в использовании gevent.spawn(...), чтобы порождать все из них одновременно, а не использовать пул gevent и pool.spawn(...), чтобы ограничить количество параллельных зеленых зон?

Сформулировано по-другому: существует ли какое-либо преимущество для "ограничения concurrency" с помощью gevent.Pool, даже если это не требуется для решения проблемы?

Любая идея, которая будет составлять "большое количество" для этой проблемы?

Ответы

Ответ 1

Это просто чистая и хорошая практика, когда вы имеете дело со множеством вещей. Я столкнулся с этим несколько недель назад, когда использовал 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, когда моя загрузка машины зависает около 1 на EC2 m1.small. Я сделал это немного наивно, хотя, если бы я снова это сделал, я бы запускал несколько пулов и некоторое время находился между ними, чтобы попытаться распределить нагрузку на NIC и CPU более равномерно.

Последнее, что нужно иметь в виду - следить за открытыми файлами и увеличивать это, если нужно: http://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files. Зелёные звёзды, которые я запускал, занимали около 5 дескрипторов файлов на каждую зелени, поэтому вы можете быстро закончиться, если не будете осторожны. Это может быть не очень полезно, если ваша загрузка системы выше единицы, поскольку вы начнете видеть уменьшающиеся возвраты независимо.

Ответ 2

Пришел сюда из Google и решил запустить несколько быстрых тестов, чтобы увеличивать зеленые зелья 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

Таким образом, до 1000 зелий и потеря производительности крошечная, но как только вы начнете наносить 10 000+ зеленых, все замедляется.

Тестовый код:

import gevent

N = 0

def test():
    gevent.sleep(1)

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

gevent.wait()