「fio」コマンドを用いてEBS, EFS, FSx for OpenZFSの性能を実測して比較してみた
はじめに
みなさんこんにちは、クラウド事業本部コンサルティング部の浅野です。
EC2インスタンス上でNFSベースのファイルサーバーを運用しており、Amazon EFSやAmazon FSx for OpenZFSへの移行を検討することもあるかと思います。
その際に気になるのがそれぞれのサービスにおいて「実際のパフォーマンスはどの程度違うのか?」という点です。カタログスペックだけでは分かりにくい部分もあるため、今回はfioコマンドを使って、「EBS」、「EFS」、「FSx for OpenZFS」の3つのストレージを同一条件で比べてみました。
本記事では、LinuxベースのWebアプリケーションがファイルシステムにアクセスする典型的なユースケースを想定し、2つのパターンでベンチマークを実施しました。
fioコマンドとは
fio(Flexible I/O Tester)は、ストレージの性能を測定するためのベンチマークツールです。スループット、IOPS、レイテンシなどを測定でき、ランダムアクセスやシーケンシャルアクセス、読み書きの比率など様々なワークロードをデータセットの用意なしに再現できます。実際のアプリケーションの使用パターンを模倣したテストができるため、本番環境に近い性能評価ができます。
今回はこのコマンドを使用して実際のベンチマークを測定してみます。
それぞれのストレージサービスの違い
ストレージサービスの特徴として以下の違いがありますので、以下にまとめました。コストに関しては考慮していません。
「EBS」はローカルにアタッチできるブロックストレージで、「EFS」、「FSx for OpenZFS」はネットワークを通してアクセスできるファイルストレージです。アクセスの形式が前提として異なることに注意が必要です。
構成
CDKを用いて以下の単一VPC・サブネットにて以下の構成を用意しました。

CDKスタック
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as fsx from 'aws-cdk-lib/aws-fsx';
import * as efs from 'aws-cdk-lib/aws-efs';
import * as iam from 'aws-cdk-lib/aws-iam';
/**
* ストレージ性能比較検証用スタック
* EBS / EFS / FSx for OpenZFS をfioでベンチマーク比較
*/
export class DemoFsxOpenzfsEfsStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// VPC
const vpc = new ec2.Vpc(this, 'Vpc', {
maxAzs: 1,
natGateways: 0,
subnetConfiguration: [
{
cidrMask: 24,
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
},
],
});
// EC2用セキュリティグループ
const ec2Sg = new ec2.SecurityGroup(this, 'Ec2Sg', {
vpc,
description: 'Security group for EC2 instance',
allowAllOutbound: true,
});
// FSx用セキュリティグループ
const fsxSg = new ec2.SecurityGroup(this, 'FsxSg', {
vpc,
description: 'Security group for FSx for OpenZFS',
allowAllOutbound: true,
});
fsxSg.addIngressRule(ec2Sg, ec2.Port.tcp(2049), 'NFS Server');
fsxSg.addIngressRule(ec2Sg, ec2.Port.tcp(111), 'NFS RPC');
fsxSg.addIngressRule(ec2Sg, ec2.Port.tcpRange(20001, 20003), 'NFS Mount');
// EFS用セキュリティグループ
const efsSg = new ec2.SecurityGroup(this, 'EfsSg', {
vpc,
description: 'Security group for EFS',
allowAllOutbound: true,
});
efsSg.addIngressRule(ec2Sg, ec2.Port.tcp(2049), 'NFS from EC2');
// FSx for OpenZFS
const fsxFileSystem = new fsx.CfnFileSystem(this, 'FsxFileSystem', {
fileSystemType: 'OPENZFS',
subnetIds: [vpc.publicSubnets[0].subnetId],
securityGroupIds: [fsxSg.securityGroupId],
storageCapacity: 64,
openZfsConfiguration: {
deploymentType: 'SINGLE_AZ_1',
throughputCapacity: 512,
diskIopsConfiguration: {
mode: 'USER_PROVISIONED',
iops: 5000,
},
rootVolumeConfiguration: {
dataCompressionType: 'ZSTD',
nfsExports: [
{
clientConfigurations: [
{
clients: '*',
options: ['rw', 'crossmnt', 'no_root_squash'],
},
],
},
],
},
},
});
// EFS
const efsFileSystem = new efs.FileSystem(this, 'EfsFileSystem', {
vpc,
vpcSubnets: {
subnetType: ec2.SubnetType.PUBLIC,
},
securityGroup: efsSg,
performanceMode: efs.PerformanceMode.GENERAL_PURPOSE,
throughputMode: efs.ThroughputMode.PROVISIONED,
provisionedThroughputPerSecond: cdk.Size.mebibytes(512),
removalPolicy: cdk.RemovalPolicy.DESTROY,
allowAnonymousAccess: true,
});
// EC2用IAMロール (SSM用)
const ec2Role = new iam.Role(this, 'Ec2Role', {
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'),
],
});
// EC2インスタンス (t3.micro, Amazon Linux 2023)
const instance = new ec2.Instance(this, 'Instance', {
vpc,
vpcSubnets: {
subnetType: ec2.SubnetType.PUBLIC,
},
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO),
machineImage: ec2.MachineImage.latestAmazonLinux2023({
cpuType: ec2.AmazonLinuxCpuType.X86_64,
}),
securityGroup: ec2Sg,
role: ec2Role,
// ルートボリューム
blockDevices: [
{
deviceName: '/dev/xvda',
volume: ec2.BlockDeviceVolume.ebs(100, {
volumeType: ec2.EbsDeviceVolumeType.GP3,
iops: 5000,
}),
},
],
});
}
}
CDKにおいてできるだけ各ストレージサービスの性能を近づけるため、それぞれのファイルシステムとブロックストレージを本番に近い形で以下のIOPSとスループットの性能に固定しています。
| ストレージ | IOPS | スループット |
|---|---|---|
| EBS gp3 | 5,000 | 512 MB/s |
| FSx for OpenZFS | 5,000 | 512 MB/s |
| EFS Provisioned | - | 512 MB/s |
「EFS」はパフォーマンスモードごとにIOPSの上限が決まっており、ユーザーが明示的にIOPS値を指定することはできません。よってスループットのみの指定としています。
また、「EBS」は起動テンプレートの設定を行わないとCDKからではスループットの指定が反映されなかったので、上記のスタックをデプロイ後、CLIコマンドでスループットを更新しました。
デプロイ後の「EBS」スループットの確認

以下のコマンドでデフォルト「128MB/s」→「512MB/s」に変更済み
※Volume IDは事前に確認済み
aws ec2 modify-volume --volume-id vol-058a87d44e452ff41 --throughput 512
{
"VolumeModification": {
"VolumeId": "vol-058a87d44e452ff41",
"ModificationState": "modifying",
"TargetSize": 100,
"TargetIops": 5000,
"TargetVolumeType": "gp3",
"TargetThroughput": 512,
"TargetMultiAttachEnabled": false,
"OriginalSize": 100,
"OriginalIops": 5000,
"OriginalVolumeType": "gp3",
"OriginalThroughput": 125,
"OriginalMultiAttachEnabled": false,
"Progress": 0,
"StartTime": "2026-01-31T08:42:40+00:00"
}
}
「EFS」と「FSx for OpenZFS」はともにNFS v4.1を使用して、TLSを用いた暗号化通信は無しにしています。
「EFS」においてアクセスのIAM認証を設定すると必ずTLS経由での設定が強制されるため、今回は匿名アクセス設定allowAnonymousAccess: true,を入れてどこからでも「EFS」にマウントできるようにしています。TLS処理のオーバーヘッドをなくして「EFS」と「FSx for OpenZFS」のアクセス時の処理に差を出さないことが狙いです。
参考:
検証シチュエーション
今回の検証シチュエーションとしては、Webアプリケーションがファイルシステムにアクセスする典型的なユースケースを想定し、「EBS」、「EFS」、「FSx for OpenZFS」の3つのストレージを以下の同一条件でfioコマンドを実行し比較しました。
検証パターン1: キャッシュ/セッション
Webアプリケーションがセッションファイルやキャッシュファイルにアクセスする状況を想定しています。セッションやキャッシュは数百バイト〜数KBの小さなデータで、ユーザーごとに異なるファイルへランダムにアクセスします。16人のユーザーが同時にアクセスし、読み取り70%・書き込み30%の比率で60秒間テストするようにfioコマンドを実行しました。
sudo fio \
--name=cache \
--directory=/mnt/efs \
--rw=randrw \
--rwmixread=70 \
--bs=4k \
--size=100M \
--numjobs=16 \
--runtime=60 \
--time_based \
--group_reporting
各オプションの意味はこちらです。
| オプション | 値 | 意味 |
|---|---|---|
| --name | cache | テスト名 |
| --directory | /mnt/efs など | テスト対象のディレクトリ |
| --rw | randrw | ランダム読み書き |
| --rwmixread | 70 | 読み取り 70%、書き込み 30% |
| --bs | 4k | 1回の I/O サイズ |
| --size | 100M | 各ジョブのファイルサイズ |
| --numjobs | 16 | 同時実行ジョブ数 |
| --runtime | 60 | テスト時間(秒) |
| --time_based | - | 時間までループ継続 |
| --group_reporting | - | 結果をまとめて表示 |
検証パターン2: ファイルアップロード
ユーザーが画像やPDFなどのファイルをアップロードする状況を想定しています。アップロードは書き込み処理のみで、1MB単位のチャンクで順次書き込みを行います。4人のユーザーが同時にファイルをアップロードし、60秒間書き込み続けることを想定しています。
sudo fio \
--name=upload \
--directory=/mnt/efs \
--rw=write \
--bs=1M \
--size=50M \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting
各オプションの意味はこちらです。
| オプション | 値 | 意味 |
|---|---|---|
| --name | upload | テスト名 |
| --directory | /mnt/efs など | テスト対象のディレクトリ |
| --rw | write | 順次書き込み |
| --bs | 1M | 1回の I/O サイズ |
| --size | 50M | 各ジョブのファイルサイズ |
| --numjobs | 4 | 同時実行ジョブ数 |
| --runtime | 60 | テスト時間(秒) |
| --time_based | - | 時間までループ継続 |
| --group_reporting | - | 結果をまとめて表示 |
やってみた
CDKをデプロイ後、まず「「EFS」、「FSx for OpenZFS」の各ファイルシステムへEC2からマウントします。
EC2にSSM接続を行い以下のコマンドを実行しました。
※ 各ファイルシステムの{DNS名}はあらかじめ確認済みです。
# マウントポイント作成
sudo mkdir -p /mnt/{efs,fsx}
# EFS
# デフォルトで NFS v4.1 を使用
# TLS 強制のため IAM 認証は使わず
sudo mount -t nfs4 -o nfsvers=4.1 \
fs-00bc54ce35b6770f2.efs.ap-northeast-1.amazonaws.com:/ \
/mnt/efs
# FSx for OpenZFS (NFS v4.1を使用するように明示的に設定)
sudo mount -t nfs -o nfsvers=4.1 \
fs-0689a8c647dcf2197.fsx.ap-northeast-1.amazonaws.com:/fsx \
/mnt/fsx
# 確認
mount | grep efs
tracefs on /sys/kernel/tracing type tracefs (rw,nosuid,nodev,noexec,relatime,seclabel)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)
fs-00bc54ce35b6770f2.efs.ap-northeast-1.amazonaws.com:/ on /mnt/efs type nfs4 \
(rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,\
timeo=600,retrans=2,sec=sys,clientaddr=10.0.0.221,local_lock=none,addr=10.0.0.178)
mount | grep fsx
fs-0689a8c647dcf2197.fsx.ap-northeast-1.amazonaws.com:/fsx on /mnt/fsx type nfs4 \
(rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,\
timeo=600,retrans=2,sec=sys,clientaddr=10.0.0.221,local_lock=none,addr=10.0.0.76)
# ディスク使用量確認
df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs 459M 0 459M 0% /dev/shm
tmpfs 184M 408K 183M 1% /run
/dev/nvme0n1p1 100G 1.8G 99G 2% /
tmpfs 459M 0 459M 0% /tmp
/dev/nvme0n1p128 10M 1.3M 8.7M 13% /boot/efi
fs-00bc54ce35b6770f2.efs.ap-northeast-1.amazonaws.com:/ 8.0E 1.8G 8.0E 1% /mnt/efs
fs-0689a8c647dcf2197.fsx.ap-northeast-1.amazonaws.com:/fsx 64G 1.8G 63G 3% /mnt/fsx
「EFS」、「FSx for OpenZFS」のマウントに成功しました。「EBS」はルートボリュームとして元々アタッチされているので特別な操作は不要です。
検証パターン1の結果
それぞれのファイルシステムのマウントが成功したので実際にfioコマンドを実行してパターン1の検証を行います。
「EBS」の結果
sudo fio \
--name=cache \
--directory=/ \
--rw=randrw \
--rwmixread=70 \
--bs=4k \
--size=100M \
--numjobs=16 \
--runtime=60 \
--time_based \
--group_reporting
cache: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=psync, iodepth=1
...
fio-3.32
Starting 16 processes
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
cache: Laying out IO file (1 file / 100MiB)
Jobs: 16 (f=16): [m(16)][100.0%][r=14.4MiB/s,w=6254KiB/s][r=3698,w=1563 IOPS][eta 00m:00s]
cache: (groupid=0, jobs=16): err= 0: pid=26196: Sat Jan 31 08:51:49 2026
read: IOPS=3871, BW=15.1MiB/s (15.9MB/s)(907MiB/60005msec)
clat (usec): min=332, max=37149, avg=4123.32, stdev=1240.49
lat (usec): min=332, max=37149, avg=4123.51, stdev=1240.50
clat percentiles (usec):
| 1.00th=[ 570], 5.00th=[ 2089], 10.00th=[ 2769], 20.00th=[ 3326],
| 30.00th=[ 3818], 40.00th=[ 4080], 50.00th=[ 4228], 60.00th=[ 4424],
| 70.00th=[ 4555], 80.00th=[ 4883], 90.00th=[ 5407], 95.00th=[ 5800],
| 99.00th=[ 6587], 99.50th=[ 6980], 99.90th=[11207], 99.95th=[15664],
| 99.99th=[28181]
bw ( KiB/s): min=13672, max=60061, per=100.00%, avg=15502.74, stdev=272.90, samples=1904
iops : min= 3418, max=15007, avg=3875.51, stdev=68.17, samples=1904
write: IOPS=1667, BW=6669KiB/s (6829kB/s)(391MiB/60005msec); 0 zone resets
clat (usec): min=2, max=9820, avg=11.75, stdev=73.97
lat (usec): min=2, max=9820, avg=12.03, stdev=74.36
clat percentiles (usec):
| 1.00th=[ 3], 5.00th=[ 3], 10.00th=[ 3], 20.00th=[ 4],
| 30.00th=[ 6], 40.00th=[ 8], 50.00th=[ 10], 60.00th=[ 12],
| 70.00th=[ 13], 80.00th=[ 14], 90.00th=[ 16], 95.00th=[ 20],
| 99.00th=[ 36], 99.50th=[ 85], 99.90th=[ 433], 99.95th=[ 791],
| 99.99th=[ 2900]
bw ( KiB/s): min= 3960, max=26255, per=100.00%, avg=6676.13, stdev=136.86, samples=1904
iops : min= 990, max= 6556, avg=1668.86, stdev=34.17, samples=1904
lat (usec) : 4=7.62%, 10=8.27%, 20=12.92%, 50=1.09%, 100=0.08%
lat (usec) : 250=0.08%, 500=0.14%, 750=1.88%, 1000=0.20%
lat (msec) : 2=1.03%, 4=22.36%, 10=44.24%, 20=0.08%, 50=0.02%
cpu : usr=0.23%, sys=0.51%, ctx=232911, majf=0, minf=157
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=232311,100040,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
READ: bw=15.1MiB/s (15.9MB/s), 15.1MiB/s-15.1MiB/s (15.9MB/s-15.9MB/s), io=907MiB (952MB), run=60005-60005msec
WRITE: bw=6669KiB/s (6829kB/s), 6669KiB/s-6669KiB/s (6829kB/s-6829kB/s), io=391MiB (410MB), run=60005-60005msec
Disk stats (read/write):
nvme0n1: ios=231916/72584, merge=0/76, ticks=944585/316730, in_queue=1261314, util=87.30%
上記の出力からスループットとIOPS(1秒あたりのI/O操作回数)は以下の箇所で確認できます。
- 読みとり →
read: IOPS=3871, BW=15.1MiB/s (15.9MB/s)(907MiB/60005msec) - 書き込み →
write: IOPS=1667, BW=6669KiB/s (6829kB/s)(391MiB/60005msec); 0 zone resetsIOPS
合計IOPSは「読み取りIOPS + 書き込みIOPS」で算出します。
3871(READ) + 1667(WRITE) = 5,538 IOPS
実行結果
実行結果を表にまとめると以下のようになりました。
| 項目 | 実行結果 |
|---|---|
| ジョブ数 | 16 processes |
| ファイルサイズ | 100MiB × 16 |
| 実行時間 | 60005msec |
| ブロックサイズ | 4096B |
| 読み書き比率 | 907MB:391MB(約70:30) |
| READ | 15.9MB/s, 3871 IOPS |
| WRITE | 6.7MB/s, 1667 IOPS |
| 合計IOPS | 約5,538 |
「EFS」の結果
sudo fio \
--name=cache \
--directory=/mnt/efs \
--rw=randrw \
--rwmixread=70 \
--bs=4k \
--size=100M \
--numjobs=16 \
--runtime=60 \
--time_based \
--group_reporting
cache: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=psync, iodepth=1
...
fio-3.32
Starting 16 processes
Jobs: 2 (f=2): [_(11),f(1),_(2),f(1),_(1)][100.0%][eta 00m:00s]
cache: (groupid=0, jobs=16): err= 0: pid=26282: Sat Jan 31 08:53:53 2026
read: IOPS=3374, BW=13.2MiB/s (13.8MB/s)(791MiB/60015msec)
clat (usec): min=587, max=73813, avg=4730.76, stdev=2505.30
lat (usec): min=587, max=73814, avg=4730.98, stdev=2505.34
clat percentiles (usec):
| 1.00th=[ 750], 5.00th=[ 1139], 10.00th=[ 2040], 20.00th=[ 3589],
| 30.00th=[ 3949], 40.00th=[ 4228], 50.00th=[ 4555], 60.00th=[ 4883],
| 70.00th=[ 5276], 80.00th=[ 5735], 90.00th=[ 6587], 95.00th=[ 7504],
| 99.00th=[15270], 99.50th=[20055], 99.90th=[27132], 99.95th=[33162],
| 99.99th=[43779]
bw ( KiB/s): min= 3280, max=22512, per=100.00%, avg=13512.40, stdev=184.04, samples=1904
iops : min= 820, max= 5628, avg=3377.61, stdev=46.01, samples=1904
write: IOPS=1451, BW=5805KiB/s (5944kB/s)(340MiB/60015msec); 0 zone resets
clat (usec): min=2, max=25695, avg=10.66, stdev=125.76
lat (usec): min=2, max=25695, avg=10.95, stdev=125.81
clat percentiles (usec):
| 1.00th=[ 3], 5.00th=[ 3], 10.00th=[ 4], 20.00th=[ 4],
| 30.00th=[ 6], 40.00th=[ 8], 50.00th=[ 9], 60.00th=[ 10],
| 70.00th=[ 10], 80.00th=[ 12], 90.00th=[ 15], 95.00th=[ 19],
| 99.00th=[ 41], 99.50th=[ 77], 99.90th=[ 293], 99.95th=[ 529],
| 99.99th=[ 2376]
bw ( KiB/s): min= 1184, max=11155, per=100.00%, avg=5808.69, stdev=103.15, samples=1904
iops : min= 296, max= 2788, avg=1451.60, stdev=25.79, samples=1904
lat (usec) : 4=6.73%, 10=14.43%, 20=7.68%, 50=1.02%, 100=0.12%
lat (usec) : 250=0.07%, 500=0.02%, 750=0.71%, 1000=2.14%
lat (msec) : 2=4.02%, 4=15.12%, 10=46.62%, 20=0.99%, 50=0.35%
lat (msec) : 100=0.01%
cpu : usr=0.19%, sys=0.49%, ctx=217379, majf=60, minf=275
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=202530,87099,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
READ: bw=13.2MiB/s (13.8MB/s), 13.2MiB/s-13.2MiB/s (13.8MB/s-13.8MB/s), io=791MiB (830MB), run=60015-60015msec
WRITE: bw=5805KiB/s (5944kB/s), 5805KiB/s-5805KiB/s (5944kB/s-5944kB/s), io=340MiB (357MB), run=60015-60015msec
実行結果
| 項目 | 実行結果 |
|---|---|
| ジョブ数 | 16 processes |
| ファイルサイズ | 100MiB × 16 |
| 実行時間 | 60015msec |
| ブロックサイズ | 4096B |
| 読み書き比率 | 791MB:340MB(約70:30) |
| READ | 13.8MB/s, 3374 IOPS |
| WRITE | 5.8MB/s, 1451 IOPS |
| 合計IOPS | 約4,825 |
「FSx for OpenZFS」の結果
sudo fio \
--name=cache \
--directory=/mnt/fsx \
--rw=randrw \
--rwmixread=70 \
--bs=4k \
--size=100M \
--numjobs=16 \
--runtime=60 \
--time_based \
--group_reporting
cache: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=psync, iodepth=1
...
fio-3.32
Starting 16 processes
Jobs: 11 (f=11): [f(3),_(2),f(1),_(1),f(4),_(1),f(3),_(1)][100.0%][r=2432KiB/s,w=1100KiB/s][r=608,w=275 IOPS][eta 00m:00s]
cache: (groupid=0, jobs=16): err= 0: pid=27303: Sat Jan 31 09:19:02 2026
read: IOPS=20.6k, BW=80.3MiB/s (84.2MB/s)(4818MiB/60004msec)
clat (nsec): min=1338, max=550972k, avg=763137.89, stdev=1766541.57
lat (nsec): min=1376, max=550972k, avg=763436.29, stdev=1766836.55
clat percentiles (usec):
| 1.00th=[ 159], 5.00th=[ 235], 10.00th=[ 269], 20.00th=[ 314],
| 30.00th=[ 367], 40.00th=[ 424], 50.00th=[ 494], 60.00th=[ 578],
| 70.00th=[ 709], 80.00th=[ 898], 90.00th=[ 1270], 95.00th=[ 1827],
| 99.00th=[ 4948], 99.50th=[ 7570], 99.90th=[19268], 99.95th=[23200],
| 99.99th=[52691]
bw ( KiB/s): min=18548, max=168703, per=100.00%, avg=82389.65, stdev=1632.14, samples=1904
iops : min= 4637, max=42172, avg=20596.92, stdev=408.06, samples=1904
write: IOPS=8823, BW=34.5MiB/s (36.1MB/s)(2068MiB/60004msec); 0 zone resets
clat (usec): min=2, max=304298, avg=20.40, stdev=1020.98
lat (usec): min=2, max=304298, avg=20.86, stdev=1021.28
clat percentiles (usec):
| 1.00th=[ 3], 5.00th=[ 3], 10.00th=[ 4], 20.00th=[ 4],
| 30.00th=[ 5], 40.00th=[ 5], 50.00th=[ 6], 60.00th=[ 6],
| 70.00th=[ 7], 80.00th=[ 8], 90.00th=[ 16], 95.00th=[ 26],
| 99.00th=[ 229], 99.50th=[ 478], 99.90th=[ 1303], 99.95th=[ 2147],
| 99.99th=[ 7308]
bw ( KiB/s): min= 7511, max=73603, per=100.00%, avg=35363.34, stdev=715.86, samples=1904
iops : min= 1875, max=18397, avg=8840.42, stdev=178.98, samples=1904
lat (usec) : 2=0.11%, 4=7.86%, 10=18.43%, 20=1.99%, 50=1.45%
lat (usec) : 100=0.25%, 250=4.65%, 500=30.65%, 750=15.55%, 1000=7.63%
lat (msec) : 2=8.44%, 4=2.00%, 10=0.78%, 20=0.15%, 50=0.06%
lat (msec) : 100=0.01%, 250=0.01%, 500=0.01%, 750=0.01%
cpu : usr=0.51%, sys=2.18%, ctx=1336635, majf=123, minf=323
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=1233521,529469,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
READ: bw=80.3MiB/s (84.2MB/s), 80.3MiB/s-80.3MiB/s (84.2MB/s-84.2MB/s), io=4818MiB (5053MB), run=60004-60004msec
WRITE: bw=34.5MiB/s (36.1MB/s), 34.5MiB/s-34.5MiB/s (36.1MB/s-36.1MB/s), io=2068MiB (2169MB), run=60004-60004msec
実行結果
| 項目 | 実行結果 |
|---|---|
| ジョブ数 | 16 processes |
| ファイルサイズ | 100MiB × 16 |
| 実行時間 | 60004msec |
| ブロックサイズ | 4096B |
| 読み書き比率 | 4818MB:2068MB(約70:30) |
| READ | 84.2MB/s, 20,600 IOPS |
| WRITE | 36.1MB/s, 8,823 IOPS |
| 合計IOPS | 約29,423 |
パターン1 まとめ
| ストレージ | READ スループット | READ IOPS | WRITE スループット | WRITE IOPS | 合計 IOPS | 順位 |
|---|---|---|---|---|---|---|
| 「FSx for OpenZFS」 | 84.2 MB/s | 20,600 | 36.1 MB/s | 8,823 | 29,423 | 1位 |
| 「EBS」 | 15.9 MB/s | 3,871 | 6.7 MB/s | 1,667 | 5,538 | 2位 |
| 「EFS」 | 13.8 MB/s | 3,374 | 5.8 MB/s | 1,451 | 4,825 | 3位 |
「FSx for OpenZFS」は設定IOPS 5,000に対して約29,000 IOPSでした。「クラウドで利用可能な中でも最高レベルの、ファイルストレージ向けの低レイテンシーを提供します」と謳われているだけあって他のストレージサービスと比較して圧倒的な結果を記録しました。
「EBS」は設定IOPS 5,000に対して約5,500 IOPS、「EFS」は約4,800 IOPSでした。
「FSx for OpenZFS」が設定値を大きく超えた結果となったのは、ZFSのキャッシュ機能が関係しているのでしょうか。ZFSには頻繁にアクセスされるデータをメモリ上にキャッシュする仕組みがあるようで、今回のように同じファイルに対して繰り返しランダムアクセスを行うワークロードでは、ディスクI/Oを経由せずメモリから直接データを返すことで高速化されるようです。「EFS」が「EBS」より約13%低い結果となったのは、ネットワーク経由のオーバーヘッドが影響しているのではないかと考察しました。この検証にて同じ小ファイルの大量読み取りの場合「FSx for OpenZFS」が圧倒的に高パフォーマンスを誇るということを実感しました。
参考:
検証パターン2の結果
続いて検証パターン2のコマンドを実行してそれぞれ比較しました。
「EBS」の結果
sudo fio \
--name=upload \
--directory=/ \
--rw=write \
--bs=1M \
--size=50M \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting
upload: (g=0): rw=write, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=psync, iodepth=1
...
fio-3.32
Starting 4 processes
upload: Laying out IO file (1 file / 50MiB)
upload: Laying out IO file (1 file / 50MiB)
upload: Laying out IO file (1 file / 50MiB)
upload: Laying out IO file (1 file / 50MiB)
Jobs: 4 (f=4): [W(4)][100.0%][w=235MiB/s][w=235 IOPS][eta 00m:00s]
upload: (groupid=0, jobs=4): err= 0: pid=26619: Sat Jan 31 09:01:59 2026
write: IOPS=253, BW=254MiB/s (266MB/s)(14.9GiB/60048msec); 0 zone resets
clat (usec): min=260, max=350011, avg=10927.14, stdev=21747.18
lat (usec): min=275, max=350073, avg=10975.63, stdev=21755.01
clat percentiles (usec):
| 1.00th=[ 326], 5.00th=[ 363], 10.00th=[ 371], 20.00th=[ 383],
| 30.00th=[ 408], 40.00th=[ 437], 50.00th=[ 486], 60.00th=[ 586],
| 70.00th=[ 1909], 80.00th=[ 28967], 90.00th=[ 29754], 95.00th=[ 39584],
| 99.00th=[113771], 99.50th=[139461], 99.90th=[191890], 99.95th=[219153],
| 99.99th=[283116]
bw ( KiB/s): min=57344, max=788767, per=100.00%, avg=260695.15, stdev=22832.98, samples=475
iops : min= 56, max= 770, avg=254.36, stdev=22.30, samples=475
lat (usec) : 500=51.73%, 750=15.09%, 1000=1.81%
lat (msec) : 2=1.43%, 4=0.79%, 10=0.68%, 20=3.99%, 50=21.60%
lat (msec) : 100=1.66%, 250=1.21%, 500=0.01%
cpu : usr=0.12%, sys=4.29%, ctx=49856, majf=20, minf=67
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=0,15251,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
WRITE: bw=254MiB/s (266MB/s), 254MiB/s-254MiB/s (266MB/s-266MB/s), io=14.9GiB (16.0GB), run=60048-60048msec
Disk stats (read/write):
nvme0n1: ios=25/89304, merge=0/32, ticks=36/429337, in_queue=429373, util=96.56%
実行結果
| 項目 | 実行結果 |
|---|---|
| ジョブ数 | 4 processes |
| ファイルサイズ | 50MiB × 4 |
| 実行時間 | 60048msec |
| ブロックサイズ | 1024KiB |
| 読み書き | write only |
| WRITE | 266MB/s, 253 IOPS |
| 総書き込み量 | 14.9GB |
「EFS」の結果
sudo fio \
--name=upload \
--directory=/mnt/efs \
--rw=write \
--bs=1M \
--size=50M \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting
upload: (g=0): rw=write, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=psync, iodepth=1
...
fio-3.32
Starting 4 processes
Jobs: 4 (f=4): [W(4)][100.0%][w=468MiB/s][w=468 IOPS][eta 00m:00s]
upload: (groupid=0, jobs=4): err= 0: pid=26746: Sat Jan 31 09:04:28 2026
write: IOPS=488, BW=489MiB/s (512MB/s)(28.6GiB/60027msec); 0 zone resets
clat (usec): min=279, max=148688, avg=7958.91, stdev=13201.47
lat (usec): min=290, max=148750, avg=8017.70, stdev=13217.55
clat percentiles (usec):
| 1.00th=[ 293], 5.00th=[ 306], 10.00th=[ 326], 20.00th=[ 367],
| 30.00th=[ 412], 40.00th=[ 465], 50.00th=[ 523], 60.00th=[ 635],
| 70.00th=[ 1778], 80.00th=[ 24511], 90.00th=[ 29230], 95.00th=[ 33162],
| 99.00th=[ 40109], 99.50th=[ 46400], 99.90th=[ 85459], 99.95th=[108528],
| 99.99th=[132645]
bw ( KiB/s): min=186442, max=2093056, per=100.00%, avg=501507.23, stdev=64799.40, samples=476
iops : min= 181, max= 2044, avg=489.47, stdev=63.30, samples=476
lat (usec) : 500=47.14%, 750=17.55%, 1000=3.11%
lat (msec) : 2=2.51%, 4=2.16%, 10=1.66%, 20=4.03%, 50=21.46%
lat (msec) : 100=0.32%, 250=0.06%
cpu : usr=0.34%, sys=7.37%, ctx=30728, majf=0, minf=42
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=0,29332,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
WRITE: bw=489MiB/s (512MB/s), 489MiB/s-489MiB/s (512MB/s-512MB/s), io=28.6GiB (30.8GB), run=60027-60027msec
実行結果
| 項目 | 実行結果 |
|---|---|
| ジョブ数 | 4 processes |
| ファイルサイズ | 50MiB × 4 |
| 実行時間 | 60027msec |
| ブロックサイズ | 1024KiB |
| 読み書き | write only |
| WRITE | 512MB/s, 488 IOPS |
| 総書き込み量 | 28.6GB |
「FSx for OpenZFS」の結果
sudo fio \
--name=upload \
--directory=/mnt/fsx \
--rw=write \
--bs=1M \
--size=50M \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting
upload: (g=0): rw=write, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=psync, iodepth=1
...
fio-3.32
Starting 4 processes
Jobs: 4 (f=4): [W(4)][100.0%][w=256MiB/s][w=256 IOPS][eta 00m:00s]
upload: (groupid=0, jobs=4): err= 0: pid=27777: Sat Jan 31 09:30:01 2026
write: IOPS=255, BW=256MiB/s (268MB/s)(15.0GiB/60033msec); 0 zone resets
clat (usec): min=288, max=630253, avg=15289.68, stdev=38180.10
lat (usec): min=300, max=630308, avg=15340.11, stdev=38184.37
clat percentiles (usec):
| 1.00th=[ 330], 5.00th=[ 343], 10.00th=[ 359], 20.00th=[ 420],
| 30.00th=[ 453], 40.00th=[ 498], 50.00th=[ 586], 60.00th=[ 709],
| 70.00th=[ 3556], 80.00th=[ 29492], 90.00th=[ 39584], 95.00th=[ 50070],
| 99.00th=[214959], 99.50th=[261096], 99.90th=[400557], 99.95th=[467665],
| 99.99th=[509608]
bw ( KiB/s): min=51200, max=908858, per=99.93%, avg=261550.23, stdev=37789.51, samples=476
iops : min= 50, max= 887, avg=255.13, stdev=36.91, samples=476
lat (usec) : 500=40.28%, 750=21.03%, 1000=3.84%
lat (msec) : 2=3.17%, 4=1.96%, 10=1.36%, 20=1.51%, 50=21.73%
lat (msec) : 100=2.48%, 250=2.02%, 500=0.59%, 750=0.03%
cpu : usr=0.14%, sys=4.41%, ctx=18587, majf=18, minf=70
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=0,15345,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
WRITE: bw=256MiB/s (268MB/s), 256MiB/s-256MiB/s (268MB/s-268MB/s), io=15.0GiB (16.1GB), run=60033-60033msec
実行結果
| 項目 | 実行結果 |
|---|---|
| ジョブ数 | 4 processes |
| ファイルサイズ | 50MiB × 4 |
| 実行時間 | 60033msec |
| ブロックサイズ | 1024KiB |
| 読み書き | write only |
| WRITE | 268MB/s, 255 IOPS |
| 総書き込み量 | 15.0GB |
パターン2 まとめ
| ストレージ | WRITE スループット | WRITE IOPS | 総書き込み量 | 順位 |
|---|---|---|---|---|
| 「EFS」 | 512 MB/s | 488 | 28.6 GB | 1位 |
| 「FSx for OpenZFS」 | 268 MB/s | 255 | 15.0 GB | 2位 |
| 「EBS」 gp3 | 266 MB/s | 253 | 14.9 GB | 3位 |
「EFS」は設定スループット512 MB/sに対して設定値そのままの512 MB/sを記録しました。「FSx for OpenZFS」は設定スループット512 MB/sに対して268 MB/s、「EBS」は設定スループット512 MB/sに対して266 MB/sでした。
「EFS」が設定値どおりの性能を発揮したのに対し、「EBS」と「FSx for OpenZFS」が約半分にとどまったのは、IOPS指定(5,000 IOPS)がボトルネックになっているのではないでしょうか。
1MBブロックで5,000 IOPSの場合、理論上の上限は約5,000 MB/sですが、実際にはレイテンシやオーバーヘッドにより256〜268 MB/s程度になったと推測しました。
逆に「EFS」はパフォーマンスモードごとにIOPSの上限はあるものの、ユーザー側で明示的に指定できずAWS側でスケーリングされる仕様なので、今回の書き込み量に合わせてIOPSを自動でスケーリングしたためこのような結果になったと思われます。
このようなに容量順次書き込みのワークロードでは、EFSの自動スケーリング機能が有効に機能することが確認できました。
一方で「FSx for OpenZFS」はあらかじめプロビジョニングする必要があるためこのような柔軟なスケーリングができません。
最後に
本記事では、fioコマンドを使用して「EBS」gp3、「EFS」、「FSx for OpenZFS」の3つのストレージサービスを同一条件でベンチマーク比較しました。
検証パターン1(4KBランダム読み書き)では、「FSx for OpenZFS」がZFSのキャッシュ機能により他のストレージを大きく上回る結果となりました。
検証パターン2(1MB順次書き込み)では、「EFS」のみが設定スループットどおりの性能を発揮し、最も高い書き込み性能を記録しました。
今回の検証が、各ストレージの特性をそのまま表現しているとは言えませんが、1ケースとして参考になるのではないでしょうか。
実際のストレージサービスの選定はワークロードの特性によって異なってくるので、本番ワークロードに寄せたシチュエーションを検討し、実測値ベースで比較することが重要だと思います。
この記事がどなたかの参考になれば幸いです。今回は以上です。







