aws s3 コマンドの並列数を調整してファイルアップロードはどこまで改善できるのか検証してみた
はじめに
先日、s5cmd と AWS CLI の aws s3 コマンドの転送速度を比較検証したところ、AWS CLI の転送速度が予想以上に遅いという結果が出ました。
この結果を受けて、AWS CLI のパラメータを調整することで改善できるか検証しました。具体的には並列度とキューサイズの 2 つのパラメータを変更し、小さなファイルを大量転送するシナリオでの最適化を試みました。
検証結果サマリ
- 最適な並列数:32(今回の検証環境において)
- キューサイズの影響:なし(1,000 → 10,000 に変更しても性能変化なし)
- 転送時間: 60 秒から 21 秒へ改善
パフォーマンス改善の結果
並列数 | 実行時間(キューサイズ 1,000) | 実行時間(キューサイズ 10,000) | 改善率 |
---|---|---|---|
10 | 59.27 秒 | 60.13 秒 | ベースライン |
16 | 37.84 秒 | 38.76 秒 | 36% 短縮 |
32 | 21.51 秒 | 22.68 秒 | 64% 短縮 |
64 | 21.10 秒 | 20.94 秒 | 65% 短縮 |
128 | 20.95 秒 | 21.06 秒 | 65% 短縮 |
256 | 21.05 秒 | 21.00 秒 | 65% 短縮 |
512 | 20.95 秒 | 21.11 秒 | 65% 短縮 |
検証環境
構成図
S3 バケットへの転送経路のネットワークを安定させるために、EC2 から VPC エンドポイント経由して S3 バケットアクセスする構成としました。
EC2 インスタンス
s5cmd コマンドの検証時に用いたインスタンスと同じインスタンスタイプを利用します。
項目 | 仕様 |
---|---|
インスタンスタイプ | m8gd.8xlarge |
vCPU | 32(物理コア数) |
メモリ | 128 GiB |
プロセッサ | AWS Graviton4 |
ネットワーク帯域幅 | 15 Gbps |
Amazon EBS 帯域幅 | 10 Gbps |
インスタンスストレージ | あり(NVMe SSD) |
OS | Ubuntu 24.04 LTS ARM64 |
アップロード対象のテストファイルについて
小さなサイズのファイルが大量にあるパターンで検証します。インスタンスストアに保存して S3 バケットへアップロードした時間を計測します。
- 500KB ファイル × 10,000 個(合計約 4.8GB)
事前準備
Graviton(ARM)マシン用の基本的な準備手順を載せておきます。
インスタンスストアのマウント
# インスタンスストアをマウント
sudo mkfs.ext4 /dev/nvme1n1
sudo mkdir -p /scratch
sudo mount /dev/nvme1n1 /scratch
sudo chown ubuntu:ubuntu /scratch
$ df -h /scratch
Filesystem Size Used Avail Use% Mounted on
/dev/nvme1n1 1.7T 4.8G 1.7T 1% /scratch
AWS CLI インストール
# AWS CLI v2 インストール
curl "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" -o "awscliv2.zip"
unzip -q awscliv2.zip
sudo ./aws/install
$ aws --version
aws-cli/2.27.50 Python/3.13.4 Linux/6.8.0-1031-aws exe/aarch64.ubuntu.24
テストファイル作成
テストファイルを作成し、インスタンスストアをマウントしたディレクトリ(/scratch
)配下に保存しました。
# 小さなファイルを大量に作成(500KB × 10,000個)
for i in $(seq 1 10000); do
dd if=/dev/zero of=/scratch/small-files/small_file_${i}.dat bs=1K count=500
done
データ転送計測の条件
計測対象
- ファイル構成:500KB × 10,000 個(合計約 4.8GB)
- 転送方向:EC2 インスタンス → S3 バケット(VPC エンドポイント経由)
AWS CLI のパラメータ設定
以下 2 つのパラメータを組み合わせて性能を測定します。
並列度(max_concurrent_requests)
同時に実行する転送リクエストの数を指定します。
パターン | 並列数 | 説明 |
---|---|---|
1 | 10 | AWS CLI デフォルト値 |
2 | 16 | |
3 | 32 | |
4 | 64 | |
5 | 128 | |
6 | 256 | |
7 | 512 | s5cmd と同等レベル |
キューサイズ(max_queue_size)
転送待ちのリクエストを保持するキューの最大サイズです。
パターン | キュー数 | 説明 |
---|---|---|
A | 1,000 | AWS CLI デフォルト値 |
B | 10,000 | 転送ファイル数と同数を指定 |
計測方法
- 計測パターン:7 × 2 = 14 パターン
- 各パターンを 3 回実行し平均値を算出
# 並列度とキューサイズを設定
aws configure set default.s3.max_concurrent_requests 16
aws configure set max_queue_size 10000
# 転送時間を計測
for i in {1..3}; do
echo "=== test${i} ===" >> time_results.txt
{ time -p aws s3 cp /scratch/small-files/ s3://devio-bucket-for-mountpoint/small-files-test${i}/ --recursive --quiet; } 2>> time_results.txt
echo "" >> time_results.txt
done
検証結果
aws s3 コマンドの並列数を上げることで転送時間を約 3 分の 1 に短縮できました。
キューサイズデフォルト(1,000)
並列数 | 1回目(秒) | 2回目(秒) | 3回目(秒) | 平均(秒) |
---|---|---|---|---|
10 | 58.53 | 59.03 | 60.25 | 59.27 |
16 | 37.92 | 37.85 | 37.76 | 37.84 |
32 | 21.39 | 21.35 | 21.79 | 21.51 |
64 | 21.15 | 21.15 | 20.99 | 21.10 |
128 | 20.86 | 20.95 | 21.03 | 20.95 |
256 | 21.03 | 21.01 | 21.12 | 21.05 |
512 | 20.89 | 20.98 | 20.99 | 20.95 |
キューサイズ10倍に変更(10,000)
並列数 | 1回目(秒) | 2回目(秒) | 3回目(秒) | 平均(秒) |
---|---|---|---|---|
10 | 59.9 | 60.23 | 60.26 | 60.13 |
16 | 38.82 | 39.24 | 38.21 | 38.76 |
32 | 22.27 | 23.72 | 22.05 | 22.68 |
64 | 21.08 | 20.89 | 20.85 | 20.94 |
128 | 21.14 | 20.93 | 21.11 | 21.06 |
256 | 21.05 | 21.01 | 20.94 | 21.00 |
512 | 20.93 | 20.88 | 21.53 | 21.11 |
考察
並列数 32 で性能が頭打ちし、キューサイズは影響しない
検証結果から並列数を 32 以上に増やしても性能向上は見られず、約 21 秒で収束することがわかりました。また、キューサイズを 1,000 から 10,000 に変更しても実行時間への影響はほぼありませんでした。
並列数による性能の頭打ち
並列数を 10 → 16 → 32 と増やす過程では順調に性能が向上しました。32 を超えると実行時間は約 21 秒で収束し、512 まで増やしても改善されません。処理の並列化できない部分や、他の箇所がボトルネックとなっているためでしょう。
キューサイズの変更による影響はほぼなし
タスクキューのサイズを 10 倍に増やしても性能の頭打ちが発生する点は変わりませんでした。キューサイズがボトルネックではなかったことを確認できました。
おわりに
オンプレミスのサーバーや、ワークステーションから S3 に大量にファイルをアップロードすることがあり最近検証していました。実際に利用する環境は SINET6 経由でオンプレミスから AWS 間は 100GB の帯域幅があり、サーバや、ワークステーションなどは 10GB の NIC を積んでいるため通信経路は屈強です。
aws s3 コマンドでも並列数を調整することでパフォーマンスを改善できることはわかりました。とはいえ、s5cmd は何も考えなくても相変わらず早かったです。Python 製の AWSCLI と比べると、s5cmd は Golang 製でこれが Concurrency の実力なのでしょうか。並列数は同じ 512 にしても結果は大きく異なり、圧倒的に早い。
$ time -p s5cmd cp "/scratch/small-files/*" s3://devio-bucket-for-mountpoint/small-files-s5cmd-test3/
--- 省略 ---
real 3.14
user 22.78
sys 4.73