Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
扫描AWS S3时Python线程池比Go例程更快?_Python_Go_Amazon S3_Concurrency - Fatal编程技术网

扫描AWS S3时Python线程池比Go例程更快?

扫描AWS S3时Python线程池比Go例程更快?,python,go,amazon-s3,concurrency,Python,Go,Amazon S3,Concurrency,我最近一直在深入了解Golang并发,特别是通道和工作池的使用。我想比较Go和Python之间的性能(正如许多人所做的那样),因为我主要读到Go在并发性方面优于Python。因此,我编写了两个程序来扫描AWS帐户的S3存储桶,并报告总大小。我在一个帐户上执行了这个操作,该帐户的75个桶总数超过了几TB的数据 我惊讶地发现我的Python实现比我的Go实现快了近2倍。基于我读过的所有基准和文献,这让我感到困惑。这让我相信我没有正确地实现我的Go代码。在观看这两个程序运行时,我注意到Go实现只使用了

我最近一直在深入了解Golang并发,特别是通道和工作池的使用。我想比较Go和Python之间的性能(正如许多人所做的那样),因为我主要读到Go在并发性方面优于Python。因此,我编写了两个程序来扫描AWS帐户的S3存储桶,并报告总大小。我在一个帐户上执行了这个操作,该帐户的75个桶总数超过了几TB的数据

我惊讶地发现我的Python实现比我的Go实现快了近2倍。基于我读过的所有基准和文献,这让我感到困惑。这让我相信我没有正确地实现我的Go代码。在观看这两个程序运行时,我注意到Go实现只使用了我的CPU的15%,而Python使用了>85%。我是否错过了Go的一个重要步骤,或者在实施过程中遗漏了什么?提前谢谢

Python代码:

“”
获取S3中所有bucket中所有对象的大小
'''
导入操作系统
导入系统
进口boto3
进口期货
def get_s3_bucket_大小(aws_访问_密钥_id、aws_机密_访问_密钥、aws_会话_令牌=无):
s3client=boto3.client('s3')
#创建将由bucket的
#名称并将S3Bucket对象作为其内容
bucket={}
总尺寸=0.0
#
#开始收集数据。。。
#
#获取帐户中的所有存储桶
_bucket=s3client.list_bucket()
cnt=1
以concurrent.futures.ThreadPoolExecutor(max_workers=50)作为执行器:
future_bucket_to_scan={executor.submit(获取_bucket_对象,s3client,bucket):bucket for bucket in_bucket[“bucket”]}
对于并发的future.futures.as_完成(future_bucket_至_扫描):
bucket\u object=future\u bucket\u to\u scan[未来]
尝试:
ret=future.result()
除作为exc的例外情况外:
打印('错误:%s'(str(exc)))
其他:
总尺寸+=ret
打印(总尺寸)
def get_bucket_对象(s3client,bucket):
name=bucket[“name”]
#获取桶中的所有对象
lsbucket=s3client.list_对象(Bucket=name)
大小=0
尽管如此:
如果“内容”不在lsbucket.keys()中:
打破
对于lsbucket[“Contents”]中的内容:
大小+=内容[“大小”]
打破
返回大小
#
#主要
#
如果“名称”=“\uuuuuuuu主要”:
get\u s3\u bucket\u大小(os.environ.get(“AWS\u访问\u密钥\u ID”)、os.environ.get(“AWS\u秘密\u访问\u密钥”))
Go代码:

主程序包
进口(
“fmt”
“同步”
“github.com/aws/aws sdk go/aws”
“github.com/aws/aws sdk go/aws/awserr”
“github.com/aws/aws sdk go/aws/session”
“github.com/aws/aws sdk go/service/s3”
)
类型S3\u Bucket\u响应结构{
桶串
计数int64
尺寸int64
错误
}
类型S3\u Bucket\u请求结构{
桶串
区域字符串
}
func get_bucket_objects_async(wg*sync.WaitGroup,请求chan S3_bucket_请求,响应chan S3_bucket_响应){
变量大小int64
变量计数int64
对于请求:=范围请求{
bucket:=request.bucket
区域:=请求区域
//创建新的响应
响应:=新(S3\U桶\U响应)
response.bucket=bucket
sess,err:=session.NewSession(&aws.Config){
区域:aws.String(区域),
})
s3conn:=s3.新(sess)
resp,err:=s3conn.ListObjectsV2(&s3.ListObjectsV2Input){
桶:aws.字符串(桶),
})
如果错误!=零{
如果awsErr,ok:=错误(awsErr.Error);ok{
开关awsErr.Code(){
案例“NoSuchBucket”:
response.err=fmt.Errorf(“Bucket:(%s)是NoSuchBucket。必须正在删除。”,Bucket)
“拒绝访问”案例:
response.err=fmt.Errorf(“Bucket:(%s)是AccessDenied。您真的应该使用完全的管理员权限来运行它”,Bucket)
}
}否则{
response.err=fmt.Errorf(“列出未处理的对象错误:%s”,err)
}

回复抱歉,我没有机会全面回顾这一点,但我的回答是:这些解决方案在并发性方面似乎并不相同。.3件事突然出现:

  • boto s3客户端的线程安全。这是线程安全的吗?你能确认吗?表明它不是线程安全的
  • Python使用的工作池大小为50,但go是无限制的。(向当前代码添加50的上限)
  • 我对boto不太熟悉,但与python相比,go似乎在为每个bucket在主线程上执行额外的IO调用(
    GetBucketLocation
我的下一个问题是:

  • 每个解决方案都是正确的吗?您能证明它吗?(两个解决方案的字节总数是否相同,并且它们是否与s3控制台匹配?)
  • 您确定并发结构是相同的吗, i、 e.在主线程上求和,相同的池大小,相同的IO工作量 每个工人
  • 客户端的默认值是否相等?例如,python是否有默认的连接池大小?(我上周刚刚遇到这个问题)

对我来说,这可能不是你提问的好地方。也许你会问,goroutines和thread pool之间的问题不大可能是这里的问题,因为访问云中的存储桶要比Go或OS为线程所做的任何本地调度慢得多。你有没有试着比较一下在一块钱内列出/扫描对象的性能et?例如,您曾经做过什么,但根本没有并发性?可能是由于某些原因,S3 Go API速度慢,或者您没有正确使用它。@EliBendersky我第一次尝试时没有使用co