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

OpenBSDは非常に高速なので、自己測定するためにプログラムを少し修正する必要がありました

概要

  • LinuxOpenBSD での簡単なスレッド+ソケット作成ベンチマークの比較
  • OpenBSD の方が 圧倒的に高速 な結果
  • ソースコードの要点:2スレッドでそれぞれ256ソケット生成
  • Linux は0.017〜0.026秒、 OpenBSD は0.002〜0.006秒
  • 背景や詳細な理由はリンク先スレッドで解説

LinuxとOpenBSDにおけるスレッド&ソケット生成ベンチマーク比較

  • Jann Horn 提供のベンチマークプログラム紹介
    • 2スレッドで各256個のソケットを生成するCコード
    • ソケット生成失敗時はエラー出力
  • Linux での実行結果
    • 平均 0.017〜0.026秒 の実行時間
    • ソケット生成自体は問題なく完了
  • OpenBSD での実行結果
    • 初回は「 Too many open files」エラー(ulimit設定不足)
    • ulimit調整(例:ulimit -n 1024)後は 0.002〜0.006秒 の高速実行
  • 機械構成 は完全一致しないが、ほぼ同等スペック
  • OpenBSD がLinuxより 約5〜10倍高速 な結果
  • 一般的にはOpenBSDが遅いベンチマークが多いが、本件は逆パターン

ベンチマークのポイントと補足

  • プログラムの主な処理内容
    • 1つの追加スレッドを生成
    • 両スレッドで 256個のソケット を作成
    • 実行時間を gettimeofday で計測
  • timeコマンド の精度が足りないため、プログラム内で自計測
  • ネットワークスタック自体の違いではなく、他の要因が影響
  • 詳細な理由やヒントは スレッド元の議論 参照推奨
  • Linuxで本ベンチマークを上回る環境があれば興味深い

所感とまとめ

  • 通常はOpenBSDが極端に遅いベンチマークが多い
  • 今回のような例は 珍しくコレクション入り
  • 比較的小規模なスレッド・ソケット生成 ではOpenBSDの実装が有利な場合あり
  • 性能評価時は 単純な先入観に頼らず、実測値と考察が重要

Hackerたちの意見

いや、一般的にLinuxはOpenBSDより少なくとも3倍は速いよ。最適化にあんまり気を使ってないからね。

特定のケースについて話してるんだよね: https://infosec.exchange/@jann/115022521451508325

かなり広い主張だね。

でもOpenBSDは特定の分野ではかなり速いよ。例えば、/dev/urandomからの乱数生成とかね。大学にいた頃(2010年くらい)、OpenBSDのノートパソコンで/dev/urandomを読み取って、友達のLinuxノートパソコンにイーサネットでパイプする方が、彼のノートパソコンで直接cat /dev/urandom > /dev/sdaを実行するより速かったんだ。ほんの少しじゃなくて、10MB/sと100MB/sの違いがあったよ。

むしろ、彼らはセキュリティを重視してるんだ。Linuxの同じ対策だと、もっと遅くなる可能性が高いよ。

面白いね。リンク先のスレッドの議論を追おうとしたけど、得られたのは「RCUに関係してる」ってことだけだった。簡単に説明するとどういうこと?

2つのスレッドがソケットを順番に割り当てると、ロックを争うことになるよ。最初にfd 666を作って大きなテーブルを事前に割り当てると、ロックの競合がなくなるんだ。

Linuxでは、プロセスのファイルディスクリプタテーブル(fdtable)は最低256スロットから始まるんだ。2つのスレッドがそれぞれ256ソケットを作ると、合計で512のfdを使うことになるから、標準入力、標準出力、標準エラーの3つに加えて、256から512に容量が倍増する際にfdtableを半分くらい拡張する必要があるんだ。そして、512から1024にリサイズする際にもまた拡張が必要になる。これはカーネル内のexpand_fdtable()によって行われるよ。以下のコードが含まれてる:if (atomic_read(&files->count) > 1) synchronize_rcu(); files->countは参照カウンタなんだ。2つのスレッドがオープンファイルのセットを共有しているから、この値は2になる。つまり、fdtableの拡張中にsynchronize_rcu()が呼ばれるってこと。これによって、現在作成中のソケットのために新しいfdを取得するのが遅れるんだ。もし新しいスレッドを作成する前にfdtableを拡張すると、テストプログラムがコマンドライン引数を与えられた場合にdup(0, 666)を呼び出すことでこれを避けられる。そうすると、files->count == 1になるからsynchronize_rcu()の呼び出しがなくなるんだ。だから、これをやれば、fdtableが十分な容量を持っているから、すべてのソケットを作成する際に遅れがなくなるよ。一方で、OpenBSDのカーネルにはRCUのようなものはなくて、プロセスのファイルディスクリプタテーブルが変更されるときにrwlockを使うだけだから、Linuxで見られるような拡張時の長い遅延を避けられるんだ。

つまり、ファイルディスクリプタの割り当てオーバーヘッドをテストしてるってことだね。

まあ、そうだね。fdテーブルのサイズは、fdsとはちょっと違うし(ulimitに達したら、サイズを大きくする必要はないし)、マルチスレッドプログラムでのみの話。

そうそう、君のウェブサイトを読みやすくするために修正しなきゃいけなかったよ。なんで人はこんなことするんだろう?

モバイルではいい感じに見えるよ。コントラストも高いし、ラインも長すぎないし。何か問題あったの?

Hacker Newsで議論の続きを見る