Solaris11.3でZFSL2ARCキャッシュを準備する良い方法はありますか?
L2ARCは、ファイルから順番に読み取られたブロックを無視するように設計されています。これは進行中の操作には意味がありますが、初期のウォームアップまたはベンチマークのためにキャッシュを準備することは困難です。
さらに、高度に断片化されたファイルは、シーケンシャル読み取りがL2ARCにキャッシュされることで大きなメリットが得られます(ディスク上ではランダム読み取りであるため)が、現在のヒューリスティックでは、L2ARCが10%しか満たされていない場合でも、これらのファイルはキャッシュされません。
Solaris 10および11の以前のリリースでは、各ファイルでdd
を2回続けて使用することに成功しました。最初のdd
はファイルをARCに読み込み、2番目のdd
はバッファをくすぐったように見えたため、L2ARCキャッシングの対象になりました。同じ手法は、Solaris11.3では機能しないようです。
問題のファイルのレコードサイズが8kであることを確認しました。 更新:zfs_prefetch_disable
を設定しようとしましたが、これはL2ARCの動作に影響を与えませんでしたzfs_prefetch_disable
が重要であることが判明しました。以下の私の回答を参照してください。
それを行う良い方法がない場合は、ファイルの100%を超えるランダムな読み取りを生成するツールの使用を検討します。キャッシュが11.3で永続化されていることを考えると、これは時間の価値があるかもしれません。このようなツールはありますか?
少し実験して、4つの可能な解決策を見つけました。
それぞれのアプローチで、ステップを実行してから、さらにデータを読み取り続けてZFS ARCキャッシュをいっぱいにし、ARCからL2ARCへのフィードをトリガーする必要があります。データがすでにメモリにキャッシュされている場合、または各ブロックのディスクの圧縮サイズが32kBを超える場合、これらのメソッドは通常何も実行しないことに注意してください。
1。文書化されたカーネルフラグを設定しますzfs_prefetch_disable
L2ARCはデフォルトで、自動的にプリフェッチされたデータのキャッシュを拒否します。 ZFSプリフェッチ機能を無効にすることでこれを回避できます。とにかく、このフラグはデータベースワークロードに適していることがよくあります。
echo "zfs_prefetch_disable/W0t1" | mdb -kw
..または永続的に設定するには、/etc/system
に以下を追加します。
set zfs:zfs_prefetch_disable = 1
これで、ファイルがdd
を使用して読み取られた場合でも、L2ARCの対象になります。
運用上、この変更により、テストでの読み取りの動作も改善されます。通常、ZFSはシーケンシャル読み取りを検出すると、キャッシュから読み取るだけでなく、データvdevとキャッシュvdevの間でスループットのバランスを取りますが、キャッシュデバイスがデータデバイスよりも大幅に低レイテンシまたは高スループットである場合、パフォーマンスが低下します。
2。データを書き直します
データがZFSファイルシステムに書き込まれると、データはARCにキャッシュされ、(ブロックサイズの基準を満たしている場合)L2ARCにフィードする資格があります。データの書き換えは必ずしも簡単ではありませんが、一部のアプリケーションやデータベースではライブで書き換えることができます。アプリケーションレベルのファイルミラーリングまたはデータファイルの移動を介して。
問題:
。文書化されていないカーネルフラグの設定を解除しますl2arc_noprefetch
これは、OpenSolarisソースコードの読み取りに基づいており、完全にサポートされていないことは間違いありません。自己責任。
l2arc_noprefetch
フラグを無効にします。
echo "l2arc_noprefetch/W0" | mdb -kw
このフラグが無効になっているときにARCに読み込まれたデータは、シーケンシャル読み取りであっても(ブロックがディスク上で最大32kである限り)、L2ARCの対象になります。
ディスクからファイルを読み取ります。
dd if=filename.bin of=/dev/null bs=1024k
l2arc_noprefetch
フラグを再度有効にします。
echo "l2arc_noprefetch/W1" | mdb -kw
4。データをランダムに読み取る
(Perlハッシュの順序に基づいて)疑似ランダムに8kBチャンクのファイルを読み取るPerlスクリプトを作成しました。より大きなチャンクでも機能する可能性がありますが、まだテストしていません。
#!/usr/bin/Perl -W
my $BLOCK_SIZE = 8*2**10;
my $MAX_ERRS = 5;
foreach my $file (@ARGV) {
print "Reading $file...\n";
my $size;
unless($size = (stat($file))[7]) {print STDERR "Unable to stat file $file.\n"; next; }
unless(open(FILE, "<$file")) {print STDERR "Unable to open file $file.\n"; next; }
my $buf;
my %blocks;
for(my $i=0;$i<$size/$BLOCK_SIZE;$i++) { $blocks{"$i"} = 0; }
my $errs = 0;
foreach my $block (keys %blocks) {
unless(sysseek(FILE, $block*$BLOCK_SIZE, 0) && sysread(FILE, $buf, $BLOCK_SIZE)) {
print STDERR "Error reading $BLOCK_SIZE bytes from offset " . $block * $BLOCK_SIZE . "\n";
if(++$errs == $MAX_ERRS) { print STDERR "Giving up on this file.\n"; last; }
next;
}
}
close(FILE);
}
問題:
残りの問題
evict_l2_eligible
kstatが増加し、データがドロップされていることを示します。キャッシュされていないデータのこの残りの塊は、パフォーマンスに不均衡な影響を及ぼします。実際のワークロードを使用し、arcstat
で結果を監視することをお勧めします。
何かのようなもの:
arcstat.py -f "time,read,l2read,hit%,hits,miss%,miss,l2hit%,l2miss%,arcsz,c,l2size" 1
キャッシュを「プライミング」する必要はないと思います。使用しているワークロードがキャッシュに自然に読み込まれない場合、それは代表的なベンチマークワークロードではありません。
例外的なユースケースがあるかもしれません(データセットサイズ、ARCサイズ、ワーキングセットサイズは?)ですが、一般的に、L2ARCへの焦点は強調されすぎています。