通过Boto和Multiprocessing从S3下载文件的性能不可靠。
问题内容:
我想从S3下载数千个文件。为了加快此过程,我尝试了Python的multiprocessing.Pool
,但是我的性能非常不可靠。有时它可以工作,并且比单核版本快得多,但是通常某些文件要花费几秒钟,因此多处理运行所花的时间比单进程要长。几次我甚至得到一个ssl.SSLError: The read operation timed out
。
这可能是什么原因?
from time import time
from boto.s3.connection import S3Connection
from boto.s3.key import Key
from multiprocessing import Pool
import pickle
access_key=xxx
secret_key=xxx
bucket_name=xxx
path_list = pickle.load(open('filelist.pickle','r'))
conn = S3Connection(access_key, secret_key)
bucket = conn.get_bucket(bucket_name)
pool = Pool(32)
def read_file_from_s3(path):
starttime = time()
k = Key(bucket)
k.key = path
content = k.get_contents_as_string()
print int((time()-starttime)*1000)
return content
results = pool.map(read_file_from_s3, path_list)
# or results = map(read_file_from_s3, path_list) for a single process comparison
pool.close()
pool.join()
[更新] 我最终只在我的多处理代码中添加了带有重试(imap
+
.next(timeout)
)的超时,但这仅仅是因为我现在不想改变太多。如果您想做对,请使用gevent使用Jan-Philip的方法。
问题答案:
“这可能是什么原因?”
没有足够的细节。原因之一可能是您的私人Internet连接因太多并发连接而饥饿。但是由于您没有指定在哪个环境中执行这段代码,所以这纯粹是推测。
但是,没有人猜测您解决该问题的方法效率很低。multiprocessing
用于解决CPU受限的问题。一次通过多个TCP连接检索数据不是CPU限制的问题。每个TCP连接产生一个进程会浪费资源。
之所以这么慢,是因为在您的情况下,一个进程花费大量时间 等待 系统调用返回(另一方面,操作系统花费大量时间 等待
网络模块执行所告诉的操作(并且网络组件花费大量时间 等待 数据包通过网络到达)。
您不需要多个进程即可使您的计算机花在等待上的时间更少。您甚至不需要多个线程。您可以使用协作调度从单个OS级线程中的许多TCP连接中提取数据。在Python中,通常使用greenlet完成此操作。利用greenlets的高级模块是gevent。
网络上到处都是基于gevent的示例,这些示例可以 同时
发出许多HTTP请求。给定适当的Internet连接,单个OS级线程可以同时处理成百上千个并发的上万个并发连接。在这些数量级上,根据应用程序的确切目的,问题可能演变为受I
/ O约束 或受 CPU约束的问题。也就是说,网络连接,CPU内存总线 或 单个CPU内核都会限制您的应用程序。
关于ssl.SSLError: The read operation timed out
类似的错误:在网络世界中,您必须考虑不时发生的事情,并决定(取决于应用程序的详细信息)如何处理这些情况。通常,简单的重试尝试是一个很好的解决方案。