这是有问题的代码(一个非常简单的抓取工具),该文件是一个网址列表,通常是> 1000。
import sys, gevent
from gevent import monkey
from gevent.pool import Pool
import httplib, socket
from urlparse import urlparse
from time import time
pool = Pool(100)
monkey.patch_all(thread=False)
count = 0
size = 0
failures = 0
global_timeout = 5
socket.setdefaulttimeout(global_timeout)
def process(ourl, mode = 'GET'):
global size, failures, global_timeout, count
try:
url = urlparse(ourl)
start = time()
conn = httplib.HTTPConnection(url.netloc, timeout = global_timeout)
conn.request(mode, ourl)
res = conn.getresponse()
req = res.read()
end = time()
bytes = len(req)
took = end - start
print mode, ourl, bytes, took
size = size + len(req)
count += 1
except Exception, e:
failures += 1
start = time()
gevent.core.dns_init()
print "spawning..."
for url in open('domains'):
pool.spawn(process, url.rstrip())
print "done...joining..."
pool.join()
print "complete"
end = time()
took = end - start
rate = size / took
print "It took %.2f seconds to process %d urls." % (took, count)
print rate, " bytes/sec"
print rate/1024, " KB/sec"
print rate/1048576, " MB/sec"
print "--- summary ---"
print "total:", count, "failures:", failures
当我改变游泳池大小时,我得到了许多不同的速度变化: -
pool = Pool(100)
我一直在考虑编写一个算法来计算理想的游泳池大小,而不是跳进去我想知道是否有一些我忽略的东西?
答案 0 :(得分:4)
任何并行处理都将受CPU限制或IO限制。根据代码的性质,它看起来像池的较小尺寸,它将是IO绑定的。具体来说,它将受到你的接口带宽的限制,也可能受到系统可以支持的并发打开套接字的数量的限制(在这里思考某些版本的Windows,我已经设法在不止一次的情况下用完了可用的套接字)。当您增加池大小时,该过程可能会开始倾向于受CPU限制(特别是,如果此处没有显示更多数据处理)。要将池大小保持在最佳值,您需要监视所有这些变量的使用(打开套接字的数量,进程的带宽利用率,CPU利用率等)。您可以通过在运行爬网程序时对指标进行概要分析并对池大小进行必要的调整来手动执行此操作,也可以尝试自动执行此操作。在Python中是否可以使用这样的东西是另一回事。