banner
amtoaer

晓风残月

叹息似的渺茫,你仍要保存着那真!
github
telegram
email
x
bilibili
steam
nintendo switch

tokio::fs の flush メソッドと標準ライブラリの同名メソッドの違い

Tokio の非同期コンテキストでファイルの読み書きを行う際によく使われるモジュールは tokio::fs で、標準ライブラリのファイル API の同名の非同期バージョンが含まれています。

ほとんどのファイルメソッドは標準ライブラリの同名メソッドと同じ意味を持っていますが、flush メソッドは少し異なります。

tokio::fs ドキュメントの開始#

この記事を書いている時点で、Tokio の最新バージョンは 1.43.0 です。ドキュメントリンクをクリックすると、このモジュールの簡単な紹介が見られます:

image

ドキュメントによれば、ほとんどのオペレーティングシステムが非同期のファイルシステム API を提供していないため、tokio::fs の非同期ファイル操作は実際には一般的な同期ファイル操作を spawn_blocking のスレッドプールで実行することになります。

将来的には io_uring のような非同期ファイルシステム API に切り替える可能性がありますが、少なくとも現在はすべてのプラットフォームでスレッドプールを使用して実装されています。

ドキュメントの flush メソッドに関する特別な説明#

少し下にスクロールすると、次のような説明が見られます:

image

image

ドキュメントは特に Note を使用して、Tokio の File に書き込む際に flush を使用することが重要であるとユーザーに警告しています。なぜなら、write メソッドの呼び出しは書き込みが完了する前に戻り、明示的に flush を呼び出さなければ書き込みが完了するのを待たないからです。

これは標準ライブラリの File とは異なります。これは spawn_blocking の基盤となる実装によるものです。

標準ライブラリの flush#

なぜ Tokio はユーザーに flush を呼び出すように特に注意を促すのでしょうか?標準ライブラリには flush がないのか、または flush を呼び出す必要がないのでしょうか?これについては標準ライブラリのドキュメントを見てみる必要があります。

image

本当にそうです! File 構造体にはバッファが含まれていないため、Unix および Windows 上の flush メソッドは何の操作も行いません。言い換えれば、99.99% のプラットフォームで標準ライブラリの File を使用して書き込みを行い、flush を忘れてもプログラムの論理には影響しません。

image

もちろん、ドキュメントには補足があり、これは理解を助けるために提供された基盤の説明であり、拘束力はなく、今後のバージョンの動作も変更される可能性があることが示されています。

補足説明#

調査中に、Tokio の主要な著者である alice がフォーラムでの返信を見つけました。これが理解を助けるかもしれません。

tokio::fs::File での書き込みが完了したということは、それがスレッドプールに渡されて書き込まれることを意味しますが、それがスレッドプールによってまだ書き込まれたことを意味するわけではありません。flush を呼び出すことで、それが起こるのを待つことができます。

これは変更することはできません。AsyncWrite トレイトのシグネチャが根本的に私たちにこの方法で処理することを強制しています。

tokio::fs::File への書き込み操作が完了したということは、それがスレッドプールに渡されて書き込まれることを意味しますが、それがスレッドプールによって書き込まれたことを意味するわけではありません。flush を呼び出すことで、書き込み操作が実際に完了するのを待つことができます。

これは変更できません。AsyncWrite トレイトのシグネチャが根本的に私たちにこの方法で処理することを強制しています。

まとめ#

細部を省いて、私たちはシンプルな結論を導き出すことができます:

ファイルに書き込む際に flush をしないことは間違いがあるかもしれませんが、flush をすることは確実に間違いではありません!

ファイルを書いた後にバッファをフラッシュすることは良い習慣であり、効果がないかもしれませんが、問題が発生することはありません。😋

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。