[Netatalk] XFSとEXT4、速度比較

netatalk パフォーマンスチューニング
http://blog.keshi.org/hogememo/2013/01/03/netatalk-performance-tuning

WD30EFRX を買った話 の続き。今回は netatalk のパフォーマンスチューニングです。

簡単に済ませるつもりだったのですが、バックエンドのファイルシステムの比較にまで手を出したらえらく時間がかかってしまいました。まだまだ試したいことがあるのですがきりがないので、このあたりでまとめておこうと思います。

なお netatalk はバージョン 3.0.1 が最新版ですが Debian パッケージ を使っている都合で 2.2.2 による検証となっています。

問題

これまで HP MicroServer で運用してきた netatalk 2.2.2 の AFP ボリュームでは、 iPhoto や Aperture のフォトライブラリを置いて使うととにかく遅くて話にならないということが問題になっており、今回のストレージ更新ではこれの改善が目標のひとつです。

調べてみると netatalk の cnid_dbd というデーモンプロセスがボトルネックとなっているらしいことがわかります。このデーモンは AFP ボリュームの全ファイル・ディレクトリに CNID という一意の数値を割り当てるため、 Berkeley DB の環境を各 AFP ボリュームの .AppleDB というディレクトリに作り、ファイル・ディレクトリの更新があると同時にこの DB も更新しているのでした。

小さなファイル・ディレクトリが多くメタデータの更新が大量にあるようなワークロードでは、本来のファイル・ディレクトリ更新の間に cnid_dbd の fdatasync() が挟まることになります。 AFP ボリュームと CNID DB が同じデバイスに存在する場合、これはひどいパフォーマンスの低下をもたらします。そこでこれらを異なるデバイスに分離するだけで、相当な速度改善が望めるのではと考え、実験してみました。

またついでなので、ファイルシステムについても従来の XFS と EXT4 でどれだけの違いが出るかテストしてみることにしました。
システム

今回の実験に使った OSX マシンは次のようなものです。

Hardware: MacBook Pro (13-inch, Mid 2009)
CPU: 2.53GHz Intel Core 2 Duo
Memory: 8GB 1333MHz DDR3
NIC: NVIDIA MCP79 Ethernet (1000BASE-T) MTU:1500
OS: OSX 10.8.2 (Mountain Lion)

netatalk のサーバはいつもの microserver で OpenVZ コンテナとして動かします。

Hardware: HP ProLiant MicroServer
CPU: 1.3GHz AMD Athlon™ II Neo N36L Dual-Core Processor
Memory: 3GB ECC 1333MHz DDR3
NIC: Broadcom BCM5723 (1000BASE-T) MTU:1500
HDD: HGST HDP725050GLA360 (/dev/sda)
HDD: WDC WD30EFRX-68AX9N0 (/dev/sdd, /dev/sde)
Host OS: Debian 6.0 (squeeze) amd64
linux 2.6.32-5-openvz-amd64
Container OS: Debian 7.0 (wheezy) amd64
netatalk 2.2.2-1

準備

まず microserver に 2 台の WD30EFRX を接続し mdadm で最初からデバイスがひとつ欠けた RAID1 ボリュームを 2 つ作成しました。それぞれを XFS と EXT4 で mkfs してマウントします。

microserver# mdadm -C /dev/md/m00 -n2 -l1 /dev/sdd missing
microserver# mdadm -C /dev/md/m01 -n2 -l1 /dev/sde missing
microserver# cat /proc/mdstat
Personalities : [raid1]
md125 : active raid1 sdd[0]
2930265424 blocks super 1.2 [2/1] [U_]

md126 : active raid1 sde[0]
2930265424 blocks super 1.2 [2/1] [U_]

microserver# mkfs -t xfs -s size=4096 /dev/md/m00
microserver# mkfs -t ext4 /dev/md/m01
microserver# mkdir -p /vol/m00 /vol/m01
microserver# mount /dev/md/m00 /vol/m00
microserver# mount /dev/md/m01 /vol/m01 -o user_xattr

それぞれのボリュームに従来の環境から移行予定のデータ 1.5TB ほどを事前にコピーしておきます。パフォーマンスが悪いほうのボリュームを初期化しもう片方の RAID1 に追加する計画です。

Debian wheezy amd64 の OpenVZ コンテナを用意し netatalk 2.2.2-1 をインストールします。 mkfs したふたつのボリュームを bind mount により /vol/m00 (XFS) および /vol/m01 (EXT4) としてコンテナ内から直接アクセスできるようにしました。

netatalk コンテナ内で cnid_dbd が使う CNID DB 用のディレクトリを用意し /tmp/CNID/ には tmpfs をマウントしておきます。

netatalk# mkdir -p /var/lib/netatalk/CNID /tmp/CNID
netatalk# mount -t tmpfs tmpfs /tmp/CNID

最終的には次のような状況となりました。システムの simfs は OpenVZ ホストのシステム HDD (HGST HDP725050GLA360) が割り当てられています。

netatalk# cat /proc/mounts

/dev/simfs / simfs rw,relatime 0 0
/dev/md126 /vol/m00 xfs rw,relatime,attr2,noquota 0 0
/dev/md125 /vol/m01 ext4 rw,relatime,errors=remount-ro,user_xattr,barrier=1,nodelalloc,data=ordered 0 0
tmpfs /tmp/CNID tmpfs rw,relatime 0 0

netatalk は次のような AppleVolumes でテストしました。

:DEFAULT: options:upriv,usedots dperm:2770 fperm:0660 umask:007
/vol/m00/afp-xfs-default “afp-xfs-default”
/vol/m00/afp-xfs-var “afp-xfs-var” dbpath:/var/lib/netatalk/CNID/$v
/vol/m00/afp-xfs-tmp “afp-xfs-tmp” dbpath:/tmp/CNID/$v
/vol/m01/afp-ext4-default “afp-ext4-default”
/vol/m01/afp-ext4-var “afp-ext4-var” dbpath:/var/lib/netatalk/CNID/$v
/vol/m01/afp-ext4-tmp “afp-ext4-tmp” dbpath:/tmp/CNID/$v

ファイルシステム 2 種類 (xfs, ext4) と CNID DB 設定 (dbpath) 3 種類の組み合わせで計 6 つの AFP ボリュームを設定しています。 CNID DB 設定の説明は次のとおりです。

-default は dbpath 設定なし。 CNID DB を AFP ボリューム内に作成します。
-tmp は tmpfs (RAM ディスク) の /tmp/CNID/ に DB を作成してみます。
-var は AFP ボリュームとは異なる HDD の /var/lib/netatalk/CNID/ に DB を作成してみます。

これらのボリュームのためのディレクトリを作成しパーミッションを適切に設定しておきます。

netatalk# mkdir -p /vol/m00/afp-xfs-default
netatalk# mkdir -p /vol/m00/afp-xfs-var
netatalk# mkdir -p /vol/m00/afp-xfs-tmp
netatalk# mkdir -p /vol/m01/afp-ext4-default
netatalk# mkdir -p /vol/m01/afp-ext4-var
netatalk# mkdir -p /vol/m01/afp-ext4-tmp
netatalk# chown yaegashi.yaegashi /vol/m0*/afp-*
netatalk# chmod 2775 /vol/m0*/afp-*

netatalk をスタートしたあとに OSX 側からマウントしてみて、それぞれのボリュームに対する CNID DB の Berkeley DB 環境が .AppleDB ディレクトリで適切に初期化されていることを確認します。

netatalk# /etc/init.d/netatalk start
Starting Netatalk services (this will take a while): cnid_metad afpd.
netatalk# ls -l /tmp/CNID/afp-xfs-tmp/.AppleDB/
合計 6396
-rw-r—– 1 root root 24576 1月 2 23:15 __db.001
-rw-r—– 1 root root 647168 1月 2 23:15 __db.002
-rw-r—– 1 root root 10493952 1月 2 23:15 __db.003
-rw-r—– 1 root root 163840 1月 2 23:15 __db.004
-rw-r—– 1 root root 9158656 1月 2 23:15 __db.005
-rw-r—– 1 root root 40960 1月 2 23:15 __db.006
-rw-r–r– 1 root root 16384 1月 2 23:15 cnid2.db
-rw-r–r– 1 root root 19 1月 2 23:15 db_errlog
-rw-r–r– 1 root root 0 1月 2 23:15 lock
-rw-r—– 1 root root 10485760 1月 2 23:15 log.0000000001

OSX 側で df するとこのようになりました。

osx% df
Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on

//yaegashi@netatalk._afpovertcp._tcp.local/afp-ext4-default 5475541352 2689097752 2786443600 50% 336137217 348305450 49% /Volumes/afp-ext4-default
//yaegashi@netatalk._afpovertcp._tcp.local/afp-ext4-tmp 5475541352 2689097752 2786443600 50% 336137217 348305450 49% /Volumes/afp-ext4-tmp
//yaegashi@netatalk._afpovertcp._tcp.local/afp-ext4-var 5475541352 2689097752 2786443600 50% 336137217 348305450 49% /Volumes/afp-ext4-var
//yaegashi@netatalk._afpovertcp._tcp.local/afp-xfs-default 5857669264 2738758232 3118911032 47% 342344777 389863879 47% /Volumes/afp-xfs-default
//yaegashi@netatalk._afpovertcp._tcp.local/afp-xfs-tmp 5857669264 2738758232 3118911032 47% 342344777 389863879 47% /Volumes/afp-xfs-tmp
//yaegashi@netatalk._afpovertcp._tcp.local/afp-xfs-var 5857669264 2738758232 3118911032 47% 342344777 389863879 47% /Volumes/afp-xfs-var

bonnie++ on netatalk

最初に XFS と EXT4 の基本的な性能差を見るため netatalk コンテナで bonnie++ を走らせてみました。

bonnie++

Sequential Output: XFS の性能が優れているようです。
Sequential Input: あまり性能の差がないようです。
Sequential/Random Create: EXT4 のほうがだんとつに速くなっています。 XFS は mkfs のオプション 次第ではこれよりさらに性能が劣化します。

マウントオプションをいじるともう少し速度を向上させることができるのですが、今回のテストはこれをベースに行いました。
ファイルコピー(小)

最初に OSX マシンからのファイル・ディレクトリコピーのテストをします。

テストに使うのは RX100.aplibrary という Aperture のフォトライブラリです。総容量 8GB でファイル・ディレクトリの数が約 10,000 あり、サイズの小さなファイルもかなり多いツリーになっています。

osx% du -hs RX100.aplibrary
7.9G RX100.aplibrary
osx% find RX100.aplibrary | wc -l
10027

これを順番に各 AFP ボリュームのマウントポイントに rsync してかかる時間を計測します。次のようなスクリプトを走らせました。

#!/bin/sh -x
for i in xfs ext4; do
for j in default tmp var; do
time rsync -avP RX100.aplibrary /Volumes/afp-$i-$j
done
done

結果:
ファイルコピー(小) 経過時間(s) 速度(MB/s)
afp-xfs-default 1566.561 5.485
afp-xfs-tmp 673.519 13.964
afp-xfs-var 911.855 9.548
afp-ext4-default 1069.797 7.980
afp-ext4-tmp 347.289 25.583
afp-ext4-var 696.824 12.334

CNID DB: 予想通り dbpath を AFP ボリュームとは異なるデバイスに置くと大きく性能が改善することがわかりました。特に default と tmpfs とでは 2 倍から 3 倍の差がついています。
ファイルシステム: EXT4 が XFS に比べてかなり速いことがわかりました。

ファイルコピー(大)

今度は次のようにして作った 100MB から 1GB まで 10 個のファイルを rsync でコピーしてみます。

osx% mkdir images
osx% for i in $(seq 10); do dd if=/dev/urandom of=images/$i.img bs=100000000 count=$i; done
osx% du -h images
5.1G images

結果:
ファイルコピー(大) 経過時間(s) 速度(MB/s)
afp-xfs-default 107.161 50.697
afp-xfs-tmp 103.374 53.147
afp-xfs-var 104.323 52.638
afp-ext4-default 115.430 47.216
afp-ext4-tmp 119.226 46.030
afp-ext4-var 200.626 45.273

CNID DB: メタデータ操作が少ないため差はほとんどありませんでした。
ファイルシステム: XFS が 52MB/s 程度に対して EXT4 が 46MB/s 程度と bonnie++ の計測結果に一致する性能の違いが出ています。

ファイル削除

最後に、これまでコピーしたファイルを OSX から削除してみます。これも単純に次のようなスクリプトを走らせて rm -rf にかかる時間を計測します。

#!/bin/sh -x
for i in xfs ext4; do
for j in default tmp var; do
time rm -rf /Volumes/afp-$i-$j/*
done
done

結果:
ファイル削除 経過時間(s)
afp-xfs-default 632.086
afp-xfs-tmp 129.763
afp-xfs-var 229.681
afp-ext4-default 298.121
afp-ext4-tmp 47.351
afp-ext4-var 202.275

CNID DB: tmp とそれ以外との性能の差がさらに顕著に出ています。メタデータ操作のみでデータ転送をほとんど伴わないからでしょう。
ファイルシステム: XFS と EXT4 の差も広がっています。

bonnie++ 1.96

OSX 側のベンチマークソフトとして bonnie++ を走らせてみたかったのですが、 OSX の bonnie++ 1.96 は AFP ボリュームでは途中でこけて動きませんでした。

osx% bonnie++ -d /Volumes/afp-xfs-default
Writing a byte at a time…done
Writing intelligently…done
Rewriting…done
Reading a byte at a time…done
Reading intelligently…done
start ‘em…done…done…done…done…done…
Create files in sequential order…done.
Stat files in sequential order…done.
Delete files in sequential order…Bonnie: drastic I/O error (rmdir): Directory not empty
Cleaning up test directory after error.

検索すると似たような報告がちらほら見つかるので bonnie++ のバグかもしれませんが、今回は深追いせずあきらめました。
PostMark 1.51

PostMark は小さなファイル・ディレクトリを大量に作成・削除するフリーなベンチマークソフトで、これは Web サーバとかメールサーバなどのワークロードを再現しているそうです。 Homebrew でインストールできます。

次のようなファイル postmark.cfg を用意して実行してみました。

set number 5000
set transactions 5000
set buffering false
set location /Volumes/afp-ext4-default
show
run
set location /Volumes/afp-ext4-tmp
show
run
set location /Volumes/afp-ext4-var
show
run
set location /Volumes/afp-xfs-default
show
run
set location /Volumes/afp-xfs-tmp
show
run
set location /Volumes/afp-xfs-var
show
run

osx% postmark postmark.cfg
PostMark v1.51 : 8/14/01
Reading configuration from file ‘postmark.cfg’
Current configuration is:
The base number of files is 5000
Transactions: 5000
Files range between 500 bytes and 9.77 kilobytes in size
Working directory:
/Volumes/afp-ext4-default (weight=1)
Block sizes are: read=512 bytes, write=512 bytes
Biases are: read/append=5, create/delete=5
Not using Unix buffered file I/O
Random number generator seed is 42
Report format is verbose.
Creating files…Done
Performing transactions……….Done
Deleting files…Done
Time:
508 seconds total
193 seconds of transactions (25 per second)

Files:
7454 created (14 per second)
Creation alone: 5000 files (27 per second)
Mixed with transactions: 2454 files (12 per second)
2524 read (13 per second)
2476 appended (12 per second)
7454 deleted (14 per second)
Deletion alone: 4908 files (37 per second)
Mixed with transactions: 2546 files (13 per second)

Data:
13.52 megabytes read (27.26 kilobytes per second)
42.12 megabytes written (84.91 kilobytes per second)

結果:
PostMark 1.51 txn(/s) create(/s) read(/s) append(/s) delete(/s)
afp-xfs-default 10 6 5 5 6
afp-xfs-tmp 33 16 16 16 16
afp-xfs-var 20 12 10 10 12
afp-ext4-default 25 14 13 12 14
afp-ext4-tmp 119 82 60 58 82
afp-ext4-var 40 25 20 20 25

ファイルコピー(小)およびファイル削除と同じ傾向が出ています。

Blackmagic Disk Speed Test 2.2

Blackmagic Disk Speed Test は映像系のストレージ性能の計測に特化した無料のベンチマークソフトで、 AFP ボリュームで 1000BASE-T のワイヤースピードに迫る値が出せるありがたいソフトです。 Mac App Store からインストールできます。

結果:
Disk Speed Test 2.2 WRITE (MB/s) READ (MB/s)
afp-xfs-default 103.5 109.7
afp-xfs-tmp 105.1 109.6
afp-xfs-var 105.5 110.0
afp-ext4-default 88.5 108.0
afp-ext4-tmp 88.4 108.3
afp-ext4-var 87.3 107.6

ファイルコピー(大)と同様の傾向が出ているように見えます。
CNID DB: メタデータ操作がないため差が見られませんでした。
ファイルシステム: EXT4 の WRITE でファイルシステムのスループットと見られる 88MB/s という値が出ています。それ以外では 1000BASE-T の通信速度に達してしまっているようで、ファイルシステム本来のスループットは計測できませんでした。

まとめ

netatalk において AFP ボリュームと CNID DB (.AppleDB ディレクトリ) を別デバイスに分けることでメタデータ更新性能が大きく向上することがわかりました。

CNID DB を tmpfs (RAM ディスク) に置くと非常に高速になりますが、システムが再起動したときに消えてしまうので、現実的には /var のような普通のストレージに割り当てることになるでしょう。ここを SSD にするといいかもしれまえせん。

netatalk 2.2 までではデフォルトで AFP ボリュームと同じ場所に CNID DB を作ってしまいます。 マニュアル の例にもありますが AppleVolumes のデフォルト設定として次のように dbpath を指定するのがよいでしょう。

:DEFAULT: options:upriv,usedots dbpath:/var/lib/netatalk/CNID/$v dperm:0775 fperm:0664

netatalk 3.0 以降のデフォルトでは CNID DB を :STATEDIR:/netatalk/CNID/$v/ に作成する設定 (vol dbpath) になっていますので、特になにもする必要はないようです。バイナリパッケージではビルドの設定を確認してください。

バックエンドのファイルシステムとして XFS と EXT4 を試しましたが、それぞれが評判通りの特性を示す結果となりました。
I/O WRITE I/O READ メタデータ更新性能
XFS 高い 高い 非常に低い
EXT4 そこそこ 高い 非常に高い

どちらを使うべきかはなかなか悩ましい選択といえます。動画など 10MB 単位のファイルのみであれば迷わず XFS ですが、大量の小さなファイルを大量に扱う必要があるならば、多少の I/O スループットを犠牲にしてでも EXT4 のメタデータ更新性能をとるべきかもしれません。

OSX ではアプリケーションがパッケージやバンドルのようなデータ形式 (実体はただのディレクトリとファイル) をよく作るため、そのようなケースに該当することもあるのではないでしょうか。

2013/01/03 17:52:00 JST
Copyright © 2010-2015 YAEGASHI Takeshi
Powered by Jekyll & Bootstrap

コメント