では、Linux では同期書き込みを保証するのはどちらO_DIRECT
かO_SYNC
ですが、パフォーマンスが優れているのはどちらでしょうか?
少なくとも Linux で@roland-smith が述べたように、データが不揮発性メディアに到達したことを保証O_DIRECT
しないため、このステートメントは正しくありません。特定の環境 (たとえば、バッテリでバックアップされた SCSI コントローラを備えたディスクを表すブロック デバイスへの直接書き込み) でその保証を提供する場合がありますが、一般的なケース (たとえば、ext4 内のファイルへの書き込み) ではこれに頼ることはできません。単一の SATA ハード ディスクによってのみバッキングされるファイル システム) は、少なくとも次の理由によります。
O_DIRECT
ファイルシステム内のファイルで、停電クラッシュ後にデータを取得するために必要なメタデータが書き込まれることを保証しません
- 元の呼び出しが完了する前に、カーネルが I/O をハードウェアに送信しましたが、I/O は揮発性のハードウェアキャッシュにのみ存在します。
上記のシナリオでは、突然の電源喪失は、I/O が成功していないのに、プログラムが成功したと考えていたことを意味します。最近では、Linux の open(2) の man ページに次のように書かれています。
フラグ自体はデータを同期的に転送しようとしますが、データと必要なメタデータが転送されるO_DIRECT
というフラグの保証はありません。O_SYNC
同期 I/O を保証するにO_SYNC
は、 に加えて を使用する必要がありますO_DIRECT
。詳細については、以下の注を参照してください。
与えられたシナリオでは、Linux で同期書き込みですべての書き込みを保証する唯一の方法は、使用するO_SYNC
(速度が低下する) か、fsync()
I/O ごとに実行する (システムコールを 2 回実行したため遅くなる可能性があります) ことです。速度が心配な場合は、使用するO_SYNC
のをやめて、代わりにできるだけ大きなバッチで書き込み、次にfsync()
バッチの後に書き込みます。また、データの整合性が心配な場合は、すべての呼び出し (およびその他)の戻りコードでエラーをチェックする必要があることに注意してください。fsync()
write()
close()
「O_DIRECTの本当の意味は何ですか?」に関するこの回答を参照してください。詳細とリンクについては。
O_DIRECT
FreeBSD では、同期書き込みを保証するために、(1) + fsync()
(2)O_DIRECT | O_SYNC
または (3) O_SYNC
単独で、どのオプションが最高のパフォーマンスを発揮しますか?
あなたは Linux と同様の状況にあります (上記参照) が、3 つの選択肢のうち、3 つ目 (O_SYNC
単独) が最も速いと思います。FreeBSD open(2) の man ページには、次のように書かれていO_DIRECT
ます。
O_DIRECT は、読み取りと書き込みのキャッシュ効果を最小化または排除するために使用できます。システムは、読み取りまたは書き込みデータのキャッシュを回避しようとします。データのキャッシュが避けられない場合は、データがキャッシュに与える影響を最小限に抑えます。注意して使用しないと、このフラグを使用するとパフォーマンスが大幅に低下する可能性があります。
一般的な注意: を使用O_DIRECT
しても、すべての I/O が高速になるとは限りません。これは、ワークロード (I/O サイズ、I/O 頻度、I/O がシーケンシャルかランダムか、同期の頻度など) によって異なります。マージなどへの影響) および I/O の送信方法 (同期対非同期)。