Haskellで非常に大きなバイナリファイルを処理する最も効率的な方法は何ですか?
標準的な答えは、ファイル全体を遅延 ByteString として読み取り、バイナリ パケットのようなものを使用してその上にパーサーを書き込むことです。それにはいくつかの問題があります...
まず、Binary のようなライブラリは解析の失敗を実際には処理しません。
第 2 に、ファイルの内容全体を解析しているわけではありません。私はそれの大部分をスキップするつもりです。また、ディスクから RAM に数ギガバイトのデータを読み込んで、ガベージ コレクターに再び破棄させるのは、かなり効率が悪いように思われます。
それに関連して、実行したいスキップがファイルの末尾から外れるかどうかを判断できる必要があります (そうであればエラーになります)。
また、 backwardsをシークする必要がある場合や、ファイル内の特定のバイト オフセットまでシークする必要がある場合もありますが、これは遅延 ByteString アプローチでは十分にサポートされていないようです。(最終的にファイル全体が RAM に保持されるという深刻な危険があります。)
もちろん、別の方法として、個々のバイトをコマンドでインターリーブして 1 つずつ読み取ることもできhSeek
ます。しかし、問題は、一度に 1 バイトずつファイルを読み取るのがどれほど効率的かということです。それはまた、かなり遅くなる可能性があるように聞こえます。これに影響があるかどうかはわかりませんhSetBuffering
。(?)
それからもちろんありmmap
ます。しかし、大きなファイルで使用すると、仮想メモリシステムが狂ってしまうようです。(それが存在するすべての目的であることを考えると、これは奇妙です...)
皆さん、どう思いますか?I/O パフォーマンスとコードの保守性の観点から、これにアプローチする最善の方法は何ですか?