人気記事

Python S3

Amazon S3に複数ファイルを一括アップロードする方法を3つ比較してみた

投稿日:

オンプレミスのサーバからAmazon S3にファイルをアップロードする処理をPythonで行なっているのですが、現在はboto3のupload_fileによる順次処理のため、ファイル数が多い場合にアップロード時間が長くなっていました。

そこで、複数ファイルを一括アップロードする方法を調査し、アップロード時間を比較しました。

スポンサーリンク

動作環境

  • MacBook Pro 2021  M1
  • macOS Monterey バージョン 12.0

処理内容

アップロードするファイルとしてCIFAR-10画像内の1万ファイルを対象としました。

1枚あたりのサイズは約1KB程度となります。

比較する処理は以下の3つとします。 

  1. Python boto3のs3_uploadをforループで繰り返し
  2. AWS CLIの aws cp s3コマンドで再帰処理
  3. 圧縮後にboto3でアップロード

s3_upload.pyに処理内容を記述し、imageフォルダに画像を格納します。

Python boto3のs3_uploadをforループで繰り返し

まずは、boto3のupload_fileで1ファイルずつアップロードする処理です。

import boto3
import os
import time

filepaths = os.listdir(path='image')

bucket_name = "YOUR_BUCKET_NAME"
s3 = boto3.resource('s3')

start1 = time.time()
for filepath in filepaths:
    filename = 'image/{}'.format(filepath)
    s3.Bucket(bucket_name).upload_file(filename, filename)
print("1.boto3処理時間:{}".format(time.time() - start1))

結果、

1.boto3処理時間:839.406888961792

となり、約14分かかりました。

AWS CLIの aws cp s3コマンドで再帰処理

次に、aws s3 cpコマンドの再帰処理をsubprocess

import boto3
import os
import subprocess
import time

filepaths = os.listdir(path='image')

bucket_name = "YOUR_BUCKET_NAME"
s3 = boto3.resource('s3')

start2 = time.time()
cmd = "".join([
            "aws s3 cp image s3://",
            bucket_name,
            "/image/ --recursive --exclude '*' --include '*.jpg'"])
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
result = process.communicate()
(stdout, stderr) = (result[0], result[1])
print("2.awscli再帰処理時間: {}".format(time.time() - start2))

結果、

2.awscli再帰処理時間: 89.69907402992249

となり、1の処理から10分の1になりました。

処理時間が改善されますが、並列処理により負荷が高くなる点には留意する必要があります。

圧縮後にboto3でアップロード

gzip圧縮後にアップロードします。

import boto3
import os
import tarfile
import time

filepaths = os.listdir(path='image')

bucket_name = "s3-upload-competition"
s3 = boto3.resource('s3')

start3 = time.time()
#圧縮ファイル名
gz_name = 'image.gz'
archive = tarfile.open(gz_name, mode='w:gz')
archive.add('image')

s3.Bucket(bucket_name).upload_file(gz_name, gz_name)
print("3.圧縮アップロード時間: {}".format(time.time() - start3))

結果、

3.圧縮アップロード時間: 5.071188449859619

となりわずか5秒で処理が完了しました。

処理時間は圧倒的に早いですが、S3上には「image.gz」と圧縮されたファイルでアップロードされる点に留意する必要があります。

まとめ

1万枚の画像ファイルをS3にアップロードした際の処理時間は以下となりました。

処理方法の違いによってアップロード時間が大きく異なることが分かりました。

処理に対する負荷の許容量や圧縮可否といった留意点を許容できればアップロード時間短縮に繋げることができそうです。

処理方法 処理時間 留意点

Python boto3のs3_uploadをforループで繰り返し

約14分 -

AWS CLIの aws cp s3コマンドで再帰処理

約1.5分 今回の処理はsubprocessの並列処理のため、処理の負荷が高くなる

圧縮後にboto3でアップロード

約5秒 gzip圧縮されたファイルがアップロードされる

-Python, S3

Copyright© ITエンジニアへの転身 , 2022 All Rights Reserved Powered by STINGER.