私は最近新しいディスクをインストールし、それにzpoolを作成しました:
/# zpool create morez /dev/sdb
しばらく使った後、かなり遅いことに気づきました:
/morez# fio --name rw --rw rw --size 10G
read: IOPS=19.6k, BW=76.6MiB/s (80.3MB/s)(5120MiB/66834msec)
write: IOPS=19.6k, BW=76.6MiB/s (80.3MB/s)(5120MiB/66834msec)
このテストは、実際の使用例とかなり似ています。ディスクから中程度の数(約10k)の画像(それぞれ約2 MiB)を読み取っています。これらはディスクがほとんど空のときに一度に書き込まれたため、断片化されることはないと思います。
比較のため、ext4をテストしました。
/# gdisk /dev/sdb
...
/# mkfs.ext4 -f /dev/sdb1 && mount /dev/sdb1 /mnt && cd /mnt
/mnt# fio --name rw --rw rw --size 10G
read: IOPS=48.3k, BW=189MiB/s (198MB/s)(5120MiB/27135msec)
write: IOPS=48.3k, BW=189MiB/s (198MB/s)(5120MiB/27135msec)
そしてbtrfs:
/# mkfs.btrfs -f /dev/sdb1 && mount /dev/sdb1 /mnt && cd /mnt
/mnt# fio --name rw --rw rw --size 10G
read: IOPS=51.3k, BW=201MiB/s (210MB/s)(5120MiB/25528msec)
write: IOPS=51.3k, BW=201MiB/s (210MB/s)(5120MiB/25528msec)
ZFSでパフォーマンスの問題を引き起こしている可能性のあるものは何ですか。
また、ディスク( Seagate ST1000DM0 )は4096バイトの物理セクターを使用するため、zpoolのセクターサイズを明示的に設定してみました。
/# zpool create -o ashift=12 morez /dev/sdb
これはパフォーマンスを改善しませんでした:
/morez# fio --name rw --rw rw --size 10G
read: IOPS=21.3k, BW=83.2MiB/s (87.2MB/s)(5120MiB/61573msec)
write: IOPS=21.3k, BW=83.2MiB/s (87.2MB/s)(5120MiB/61573msec)
奇妙なことに、zvolを使用すると優れたパフォーマンスが得られました。
/# zfs create -V 20G morez/vol
/# fio --name rw --filename /dev/zvol/morez/vol --rw rw --size 10G
read: IOPS=52.7k, BW=206MiB/s (216MB/s)(5120MiB/24852msec)
write: IOPS=52.7k, BW=206MiB/s (216MB/s)(5120MiB/24852msec)
なぜこれはZFSファイルシステムにのみ影響し、zvolsには影響しないのですか?
コメントで、違いはキャッシングが原因である可能性があることが示唆されました。さらなるテストの後、私はこれが事実であるとは思わない。私はbtrfsテストのサイズを自分のコンピューターのメモリ量をはるかに超えて増やしましたが、そのパフォーマンスはZFSのパフォーマンスよりもはるかに優れていました。
/# mkfs.btrfs -f /dev/sdb1 && mount /dev/sdb1 /mnt && cd /mnt
/mnt# $ fio --name rw --rw rw --size 500G --runtime 3600 --time_based --ramp_time 900
read: IOPS=41.9k, BW=164MiB/s (172MB/s)(576GiB/3600003msec)
write: IOPS=41.9k, BW=164MiB/s (172MB/s)(576GiB/3600003msec)
以下は、fioを実行する前のZFSプロパティの外観です。これらは、デフォルト設定でzpoolを作成した結果にすぎません。
# zpool get all morez
NAME PROPERTY VALUE SOURCE
morez size 928G -
morez capacity 0% -
morez altroot - default
morez health ONLINE -
morez guid [removed] default
morez version - default
morez bootfs - default
morez delegation on default
morez autoreplace off default
morez cachefile - default
morez failmode wait default
morez listsnapshots off default
morez autoexpand off default
morez dedupditto 0 default
morez dedupratio 1.00x -
morez free 928G -
morez allocated 276K -
morez readonly off -
morez ashift 0 default
morez comment - default
morez expandsize - -
morez freeing 0 default
morez fragmentation 0% -
morez leaked 0 default
morez feature@async_destroy enabled local
morez feature@empty_bpobj enabled local
morez feature@lz4_compress active local
morez feature@spacemap_histogram active local
morez feature@enabled_txg active local
morez feature@hole_birth active local
morez feature@extensible_dataset enabled local
morez feature@embedded_data active local
morez feature@bookmarks enabled local
morez feature@filesystem_limits enabled local
morez feature@large_blocks enabled local
# zfs get all morez
NAME PROPERTY VALUE SOURCE
morez type filesystem -
morez creation Thu Jun 29 19:34 2017 -
morez used 240K -
morez available 899G -
morez referenced 96K -
morez compressratio 1.00x -
morez mounted yes -
morez quota none default
morez reservation none default
morez recordsize 128K default
morez mountpoint /morez default
morez sharenfs off default
morez checksum on default
morez compression off default
morez atime on default
morez devices on default
morez exec on default
morez setuid on default
morez readonly off default
morez zoned off default
morez snapdir hidden default
morez aclinherit restricted default
morez canmount on default
morez xattr on default
morez copies 1 default
morez version 5 -
morez utf8only off -
morez normalization none -
morez casesensitivity sensitive -
morez vscan off default
morez nbmand off default
morez sharesmb off default
morez refquota none default
morez refreservation none default
morez primarycache all default
morez secondarycache all default
morez usedbysnapshots 0 -
morez usedbydataset 96K -
morez usedbychildren 144K -
morez usedbyrefreservation 0 -
morez logbias latency default
morez dedup off default
morez mlslabel none default
morez sync standard default
morez refcompressratio 1.00x -
morez written 96K -
morez logicalused 72.5K -
morez logicalreferenced 40K -
morez filesystem_limit none default
morez snapshot_limit none default
morez filesystem_count none default
morez snapshot_count none default
morez snapdev hidden default
morez acltype off default
morez context none default
morez fscontext none default
morez defcontext none default
morez rootcontext none default
morez relatime off default
morez redundant_metadata all default
morez overlay off default
古い間、私はこの質問が答えに値すると感じます。
fio
問題、デフォルトでは、4KBサイズのIOP。代わりに、ZFSデータセットはデフォルトで128KBのレコード化を使用します。この不一致は、4Kの書き込みごとに128Kレコード全体の読み取り/変更/書き込みが発生することを意味します。
一方、ZVOLはデフォルトで8K volblocksizeを使用します。つまり、4K書き込みでは、8Kレコードの読み取り/変更/書き込みサイクルがはるかに短くなり、運が良ければ、2つの4K書き込みを1つの8K書き込みに結合できます(no読み取り/変更/書き込み)。
ZFSデータセットのレコードサイズはzfs set recordize=8K <dataset>
で変更できます。この場合、ZVOLと同等またはそれ以下の同等のパフォーマンスが得られます。ただし、比較的大きな転送に使用する場合(OPは2 MBのファイルであり、画像であるので、アクセスするたびに完全に読み取る必要があります)large recordsize/volblocksizeを使用することをお勧めします。次にデフォルト設定(128K)。
注:fioジョブにはdirect=1
( http://fio.readthedocs.io/en/latest/fio_doc.html#cmdoption-arg-direct )がないため、I/Oが実行されている(読み取りと書き込みの両方)は、オペレーティングシステムによってキャッシュされ、結果を歪めます(そして、数値を人工的に高くします)。これ自体は、次のことによりさらに複雑になります。
O_DIRECT
をサポートしていない(したがって、オープンが失敗する)か、サポートしている場合は、静かにバッファードI/Oにフォールバックします https://のポイント3を参照) github.com/zfsonlinux/zfs/commit/a584ef26053065f486d46a7335bea222cb03eeea )。O_DIRECT
をバッファI/Oにフォールバックします。LinuxではO_DIRECT
がよりヒントになるため、O_DIRECT
が引き続きバッファI/Oを実行できることに注意してください( https://stackoverflow.com/a/46377629の参照セクションを参照)/2732969 )。
キャッシュを正しくバイパスできない状況では、キャッシュの影響を最小限に抑えるのに十分な大きさの領域で十分なI/Oを実行することが重要です(もちろん、実際にキャッシュをテストする必要がある場合を除きます)...