Mountpoint for Amazon S3 のメモリ使用量を絞るとスループットがどの程度落ちるのか確認してみた
はじめに
Mountpoint for Amazon S3 は、S3 バケットをファイルシステムとしてマウントできるクライアントです。1.24.0 で --memory-target が追加され、Mountpoint が使うメモリの目標値(メモリターゲット)を指定できるようになりました。
私は AWS ParallelCluster で Mountpoint を使ったクラスターを運用しています。ゲノム解析にはメモリを大量に使うソフトウェアもあり、ときには Mountpoint とメモリを取り合うことになります。クラスターにこの設定を入れる前に、メモリを制限すると読み取りスループットがどれだけ落ちるのかを確認しました。
確認結果
c7i.8xlarge に Mountpoint 1.24.0 を入れ、S3 上の 4 GiB と 40 GiB のオブジェクトを fio で 1 ジョブずつシーケンシャルに読みました。ランダム読み取りと複数ジョブは測っていません。
- メモリターゲットを 4096 MiB にすると、40 GiB の読み取りでデフォルトと同じスループットが出た
- 読み取り中の RSS(物理メモリ上に載せている量)はデフォルトでも 1.6 GiB 程度だった
- 512 MiB まで絞ると 40 GiB の読み取りは 1.6 倍遅くなり、平均レイテンシも 1.6 倍に伸びた
デフォルトでは総メモリの 95 % がメモリターゲットになる
--memory-target を渡さない場合、Mountpoint は総メモリの 95 % をメモリターゲットにします。
--memory-targetdefaults to 95% of total (or cgroup-limited) memory. A portion of the target,max(128 MiB, memory_target / 8), is held back for Mountpoint's own overhead such as metadata and file handles; the rest is the budget for data buffers.出典: mountpoint-s3/doc/CONFIGURATION.md at mountpoint-s3-1.24.0 · awslabs/mountpoint-s3
今回のインスタンスは free -m の total が 63254 MiB です。--memory-target を渡さずにマウントすると、Mountpoint は起動ログに memory target 60091 MiB と出力しました。63254 MiB の 95 % にあたります。指定しなければ、Mountpoint はノードのメモリのほぼ全部をメモリターゲットとして使えます。
メモリを大量に使う解析ソフトウェアと同居させるなら、--memory-target で Mountpoint の取り分を先に決め、残りをジョブの処理に回したいところです。知りたいのは、絞ったときに読み取りスループットがどれだけ落ちるのかです。
検証環境
| 項目 | 値 |
|---|---|
| インスタンスタイプ | c7i.8xlarge(32 vCPU) |
総メモリ(free -m の total) |
63,254 MiB |
| OS | Amazon Linux 2023 |
| Mountpoint | 1.24.0 |
| 測定ツール | fio 3.32 |
| リージョン | ap-northeast-1 |
| テストデータ | S3 の bench/ に置いた 4 GiB の obj1.bin と 40 GiB の big40.bin |
測定はクラスターではなく、単体の EC2 インスタンスで行っています。
Mountpoint はパッケージリポジトリ経由ではなく、1.24.0 の RPM を直接入れています。バケット名は $BUCKET に入れてあります。
curl -fsSL -o /tmp/mount-s3.rpm \
https://s3.amazonaws.com/mountpoint-s3-release/1.24.0/x86_64/mount-s3-1.24.0-x86_64.rpm
dnf install -y /tmp/mount-s3.rpm
テストデータはマウント越しに dd で作りました。中身はゼロ埋めです。
mkdir -p /mnt/s3
chown ec2-user:ec2-user /mnt/s3
runuser -l ec2-user -c "mount-s3 \$BUCKET /mnt/s3"
runuser -l ec2-user -c 'mkdir -p /mnt/s3/bench
dd if=/dev/zero of=/mnt/s3/bench/obj1.bin bs=1M count=4096
dd if=/dev/zero of=/mnt/s3/bench/big40.bin bs=1M count=40960'
S3 側から見たテストデータです。コンソールの表示は 40.0 GB と 4.0 GB ですが、dd で作成した 40 GiB と 4 GiB です。

測定の手順
測定には fio を使いました。ジョブファイルは Mountpoint 公式リポジトリの scripts/fio/read/seq_read.fio をベースにしています。
[global]
name=fs_bench
bs=256k
group_reporting
[sequential_read]
filename=/mnt/s3/bench/big40.bin
size=42949672960
rw=read
ioengine=sync
fallocate=none
numjobs=1
公式から変えたのは 1 箇所だけで、runtime=30s と time_based を外してファイル全体を 1 回で読み切る形にしました。time_based を指定すると、fio はファイルの末尾まで読み終えても先頭に戻り、指定した時間が経つまで同じファイルを繰り返し読み直します。4 GiB のファイルは数秒で読み終わるため、30 秒のあいだに何度もロードすることになります。インスタンスのメモリは 62 GiB あって 4 GiB は丸ごとページキャッシュに載るので、2 回目以降は S3 ではなくメモリから返ってしまいます。
条件ごとにアンマウントしてマウントし直し起動ログからメモリターゲットを読み取ります。sync; echo 3 > /proc/sys/vm/drop_caches でページキャッシュを落としてから fio を実行します。
読み取りスループット比較
メモリターゲットを 512 MiB、4096 MiB、デフォルトの 3 通りで測りました。512 MiB は指定できる最小値、4096 MiB はノードに割り当てても惜しくない量として選びました。
--memory-target |
4 GiB 読み取り | 40 GiB 読み取り |
|---|---|---|
| 512 MiB | 845 MB/s | 922 MB/s |
| 4096 MiB | 1117 MB/s | 1483 MB/s |
| デフォルト(60091 MiB) | 1183 MB/s | 1484 MB/s |
40 GiB のオブジェクトでは、4096 MiB の 1483 MB/s とデフォルトの 1484 MB/s の差が 1 MB/s しかありません。ノードのメモリを Mountpoint に 60 GiB 割り当てなくても、4096 MiB で同じ速度が出ました。
40 GiB を読んだ 3 条件の出力です。起動ログのメモリターゲットと所要時間に注目してください。
----- big40-mt512 -----
起動ログ : max files concurrently open for write: 47 (memory target 512 MiB, write part size 8 MiB)
所要 : 46.5 秒
スループット : 922 MB/s
RSS 最大 : 310344 kB
----- big40-mt4096 -----
起動ログ : max files concurrently open for write: 447 (memory target 4096 MiB, write part size 8 MiB)
所要 : 28.9 秒
スループット : 1483 MB/s
RSS 最大 : 1386008 kB
----- big40-default -----
起動ログ : max files concurrently open for write: 6571 (memory target 60091 MiB, write part size 8 MiB)
所要 : 28.9 秒
スループット : 1484 MB/s
RSS 最大 : 1607224 kB
512 MiB まで絞るとレイテンシが 1.6 倍まで増える
fio はスループットと一緒にレイテンシと IOPS も出します。
| 条件 | 平均レイテンシ | IOPS |
|---|---|---|
| 40 GiB / 512 MiB | 283 us | 3520 |
| 40 GiB / 4096 MiB | 176 us | 5657 |
| 40 GiB / デフォルト | 176 us | 5661 |
| 4 GiB / 512 MiB | 307 us | 3227 |
| 4 GiB / 4096 MiB | 232 us | 4263 |
| 4 GiB / デフォルト | 220 us | 4513 |
40 GiB では 4096 MiB とデフォルトのレイテンシと IOPS が一致しており、スループットが同じになるのもわかります。512 MiB ではレイテンシが 283 us まで伸びました。スループットの落ち込みと同じ 1.6 倍です。
読み取り中の RSS を確認してみる
同じ条件で mount-s3 プロセスの RSS の最大値を採りました。メモリターゲットは目標値であって確保量ではないので、実際にどれだけ使うかは RSS で見ます。/proc/<pid>/status の VmRSS は kB と表示されますが、実体は KiB です。表は MiB に換算した値です。
--memory-target |
4 GiB 読み取り | 40 GiB 読み取り |
|---|---|---|
| 512 MiB | 300 MiB | 303 MiB |
| 4096 MiB | 1510 MiB | 1354 MiB |
| デフォルト(60091 MiB) | 1590 MiB | 1570 MiB |
デフォルトでも実際に使われるのは 1.6 GiB 程度で、メモリターゲットの 60 GiB にはほど遠い。メモリターゲットを大きくしても、その分のメモリを先に確保するわけではないのでここはよいでしょう。
マウント直後の RSS はどの条件でも 17.2 MiB から 17.4 MiB で、読み取り負荷をかけたときだけ増えました。
メモリを絞ると書き込み用に同時オープンできるファイル数の上限も下がるので注意
上限はメモリターゲットとパートサイズから決まります。計算式と目標値ごとの計測した検証はこちらの記事にまとまっています。
まとめ
Mountpoint for Amazon S3 1.24.0 の --memory-target を 512 MiB、4096 MiB、デフォルトの 3 通りで測りました。40 GiB のオブジェクトを 1 ジョブでシーケンシャルに読む条件では、4096 MiB でデフォルトと同じスループットが出ています。512 MiB まで絞ると 1.6 倍遅くなり、レイテンシも同じだけ伸びました。読み取り中の RSS はデフォルトでも 1.6 GiB 程度で、今回の条件だとたいしてメモリを消費していませんでした。
おわりに
計算処理前に S3 からデータをローカルへコピーする事が多いので杞憂ではあったのですが、一応把握しておこうと確認してみました。







