世界を動かす技術を、日本語で。

lsr: io_uringを用いたls

2025年7月18日原文(rockorager.dev)

概要

lsr は、独自のIOライブラリ ourioio_uring を活用した超高速lsコマンド実装。 従来のlsや他の代替ツールと比較して システムコール数が桁違いに少ないZig言語StackFallbackAllocator を用いて更なる最適化を実現。 ベンチマーク で示される圧倒的な性能とコンパクトなバイナリサイズ。 tangled.sh で開発・公開、フィードバックやアイコンリクエスト歓迎。

lsr: 超高速lsコマンドの誕生

  • lsr は、ls(1)コマンドの機能を ourio ライブラリで再実装した高速版ツール。
  • io_uring を徹底活用し、I/O処理のほとんどを カーネル空間で非同期化
  • 既存のlsやeza、lsd、uutils lsより 圧倒的に高速・低オーバーヘッド を実現。

ベンチマーク結果

  • hyperfine を用いたディレクトリ内ファイル数nごとの測定。

    • n=10, n=100, n=1,000, n=10,000で比較。
  • lsr の実行時間は他ツールの 1/2〜1/10 程度。

  • strace -c によるシステムコール数も 桁違いに少ない

    • 例: n=10,000でlsrは 848回、lsは 30,396回

lsrの内部構造

  • プログラムは 3段階構成
    • 引数解析
    • データ収集( I/Oのほぼ全て
    • データ表示
  • ディレクトリオープン、stat、lstat、各種ファイル読み出し を全て io_uring経由 で実施。
  • stat呼び出しをバッチ化 し、システムコール回数を大幅削減。

メモリアロケーションと最適化

  • Zig stdlib StackFallbackAllocator を利用。
    • 1MBの固定メモリ を先行確保、不足時のみ他アロケータへフォールバック。
    • mmap等のシステムコールも削減
  • libc非依存、動的リンク不要 の静的バイナリ。
    • GNU lsよりも小さい: ReleaseSmallビルドで 138.7KB (lsは 79.3KB)。

他ツールとの比較・考察

  • lsd は各ファイルごとに clock_gettime を5回程度呼び出しており、詳細は不明。
  • uutils ls はsyscall数は少ないが、 ソート処理 がボトルネック。
    • lsrも 30%程度の時間をソート に費やすが、それでも高速。
  • io_uringの威力 を実感できる好例。
    • サーバー用途など、他分野でも 大幅な効率化の可能性

開発・コントリビュート情報

  • tangled.sh を利用して開発・公開。
    • バグ報告やアイコンリクエストは atprotoアカウント+appパスワード で誰でも可能。
  • リポジトリ や詳細は下記リンク参照。
    • https://tangled.sh/@rockorager.dev/lsr

まとめ

  • lsr はls互換の超高速ツールで、 io_uringourio による徹底的な最適化が特徴。
  • システムコール削減・高速処理・小型バイナリ の三拍子。
  • 今後のサーバーや高性能I/Oツール開発への示唆 を与えるプロジェクト。

Hackerたちの意見

いいね!なんで全てのコマンドラインツールがio_uringを使わないのか理解したいな。例えば、USB 3.2 Gen 2のNVMeはピーク740MB/sしか出ないけど、aioやio_uringを使うと1005MB/s出るんだよね。毎回たくさんのファイルを同時にコピーしてるわけじゃないけど、キューの長さの戦略やロックが少ないのも助けになってると思う。

一つの理由は、最近の最先端のインストールだけじゃなくて、全てのLinux環境で動くようにするためだね。

おそらく、ポータビリティを重視する歴史的な好みがあって、#ifdefがたくさんあるとプラットフォームやバージョン特有のものが採用されるのが遅くなるんだろうね。でも、今の時点では、さまざまなPOSIX系プラットフォーム間のポータビリティの利点はかなり低くなってる。

ポーの法則がまたやってきた。

確か、io_uringは初期にかなり重大なセキュリティ問題があったんだよね(数年前)。今は修正されてるはずだけど、それが普及を妨げたかもしれない。

それは素晴らしいスピードアップだね。これってどのツールなの?

io_uringはセキュリティの悪夢だよ。

io_uringは非同期インターフェースで、効果的に使うにはイベントベースのアーキテクチャが必要なんだ。でも、多くのコマンドラインツールはまだシンプルな直列スタイルで書かれてる。もしCに非同期やそれに似たメカニズムがあったら、非同期プログラミングを直列でやってるふりができて、移植が楽になるんだけどね。そうじゃないと、かなりのリファクタリングが必要になるよ。それに、io_uringはまだ安定してないし、10年後にはもっと新しいハードウェアを活かすための別のメカニズムに取って代わられるかもしれない。だから、io_uringが定着するのを待つのはかなり現実的な戦略だと思う。10年後には、自動で書き換えをしてくれるツールやAIが出てるかもしれないしね。

なんで全てのコマンドラインツールがio_uringを使わないのか理解しようとしてるんだけど。まだ新しいからね。lsコマンドを含むcoreutilsパッケージ(それを作るために統合された3つのパッケージも含む)は数十年前のものだし、io_uringはその後に登場した。共有リングバッファスタイルのシステムコールが、従来の同期システムコールに取って代わるには時間がかかるだろうね。

io_uringは最近のものだね。

たくさんのファイルがあるNFSサーバーに対してどうパフォーマンスが出るのか気になるな、特にちょっと微妙な接続の上で。信頼性のないネットワークサービスをブロッキングのPOSIXシステムコールの後ろに置くのは、NFSがひどい設計選択である主な理由の一つだよね(壊れたNFSフォルダから読み込んでるアプリをctrl+cしようとしたことがある人なら分かる)。でも、io_uringがその悪い部分を少しでも軽減してくれるのか気になる。

壊れたNFSフォルダから読み込んでるアプリでctrl+cを試したことがある人なら誰でも分かると思うけど、理論的には「intr」マウントがハングしたリモートサーバーを待ってる操作を信号で中断できるようにしてたんだ。でも、Linuxはずいぶん前にそのオプションを削除しちゃったんだよね[1](FreeBSDはまだサポートしてるけど)[2]。「soft」がLinuxでの唯一の回避策かもね。 [1]: https://man7.org/linux/man-pages/man5/nfs.5.html [2]: https://man.freebsd.org/cgi/man.cgi?query=mount_nfs&sektion=...

Hacker Newsで議論の続きを見る