我有一个非常简单的python函数:
def list_blobs(bucket, project)
storage_client = storage.Client(project=project)
bucket = storage_client.get_bucket(bucket)
blobs = bucket.list_blobs(prefix='basepath/', max_results=999999,
fields='items(name,md5Hash),nextPageToken')
r = [(b.name, b.md5_hash) for b in blobs]
blob列表包含14599项,此代码需要7秒才能运行。大部分时间的分析是从服务器上浪费读取的(有16次调用page_iterator._next_page。
那么,我怎么能在这里改进?迭代代码在库中很深,每个页面的指针都来自上一页,所以我看不出如何并行获取16页,所以我可以减少7秒。
我在python 3.6.8上,
google-api-core==1.7.0
google-auth==1.6.2
google-cloud-core==0.29.1
google-cloud-storage==1.14.0
google-resumable-media==0.3.2
googleapis-common-protos==1.5.6
protobuf==3.6.1
您的max_results=999999
大于14599 - 对象的数量,将所有结果强制转换为单个页面。来自Bucket.list_blobs()
:
参数:
max_results(int) - (可选)此请求的每个结果页中的最大blob数。非正值会被忽略。默认为API设置的合理值。
我的猜测是代码花费了大量时间来等待服务器提供迭代结果所需的信息。
所以我尝试的第一件事就是实际迭代多个页面,使用小于blob数量的max_results
。可能是1000或2000,看看对整体持续时间的影响?
也许甚至尝试使用blobs.pages
明确地使用多个页面,如弃用的page_token
属性doc(强调我的)中所建议的:
page_token(str) - (可选)如果存在,则使用值返回下一批blob,该值必须对应于上一个响应中返回的
nextPageToken
值。不推荐使用:使用返回迭代器的pages
属性,而不是手动传递令牌。
但我不太确定如何强制同时拉出多个页面。也许是这样的?
[(b.name, b.md5_hash) for page in blobs.pages for b in page]