mcpField
H
hyperfine

hyperfine

公式Agent-ready
github.com開発ツール29.2khyperfine2 週間前に更新
リポジトリ公式サイト

hyperfine について

hyperfine はコマンドラインプログラムのパフォーマンスを統計的にベンチマークします。ウォームアップ実行と複数回の実行をサポートしており、詳細なパフォーマンスレポートを生成して、開発者がボトルネックと最適化の機会を特定するのに役立ちます。

主な機能

  1. 01コマンドを複数回実行して実行時間の統計を計算
  2. 02ウォームアップ実行でコールドスタート影響を排除
  3. 03複数のコマンドのパフォーマンスを並列または順次比較
  4. 04時間分布、平均値、標準偏差などの詳細指標を出力

活用シーン

  1. 01異なる実装またはアルゴリズムの実行時パフォーマンスを比較
  2. 02コード最適化が測定可能な改善をもたらすことを検証
  3. 03CI 環境でパフォーマンス低下を追跡

インストール

OS またはパッケージマネージャーを選び、コマンドをターミナルで実行します。

$
brew install hyperfine

インストール後にhyperfine --versionを実行して確認します。

コマンド例

よく使うコマンドを使う順に並べています。

01
hyperfine "npm run build"
02
hyperfine --warmup 3 "rg TODO"

詳細

hyperfine

コマンドラインのベンチマークツールです。

hyperfine-demo-800

(mypy と ty のベンチマークを実行する hyperfine の例)

特長

  • 複数回の実行にわたる統計分析。
  • さまざまなパフォーマンス指標とハードウェアカウンターに対応。
  • 任意のシェルコマンドに対応。
  • ベンチマークの進行状況と現在の推定値を随時表示。
  • 実際のベンチマーク前にウォームアップ実行が可能。
  • 各ベンチマーク実行の前に、キャッシュをクリアするコマンドを設定可能。
  • 他のプログラムによる干渉やキャッシュの影響を検出する統計的な外れ値検出。
  • 結果をさまざまな形式でエクスポート可能:CSV、JSON、Markdown、AsciiDoc。
  • パラメーター化されたベンチマーク(例:スレッド数の変更)。
  • クロスプラットフォーム

使い方

基本的なベンチマーク

ベンチマークを実行するには、hyperfine <command>... を呼び出すだけです。各引数は実行ファイルとその引数です。コマンドはデフォルトで直接実行されます。パイプ、リダイレクト、ワイルドカードなどのシェル構文を使う場合は、-S を指定してください。たとえば、次のようにします。

hyperfine 'sleep 0.3'

Hyperfine は各コマンドの実行回数を自動的に決定します。デフォルトでは、シェルのオーバーヘッドと準備・終了コマンドを含めて、およそ3秒を目標に実行回数を推定し、少なくとも 10回のベンチマークを実行します。実行回数を正確に指定するには、-r/--runs オプションを使用します。

hyperfine --runs 5 'sleep 0.3'

異なるプログラムを比較する場合は、複数のコマンドを指定できます。

hyperfine 'hexdump file' 'xxd file'

コマンドは入力順に実行され、表示されます。最初のコマンドがすべての比較の基準となり、それ以降の各結果には基準からの変化が示されます。

ウォームアップ実行と準備コマンド

ディスク I/O を大量に行うプログラムでは、ディスクキャッシュの状態(コールドかウォームか)によって、ベンチマークの結果が大きく左右されることがあります。

ウォームキャッシュでベンチマークを実行する場合は、-w/--warmup オプションを使って、実際のベンチマーク前にプログラムを指定回数実行できます。

hyperfine -S --warmup 3 'grep -R TODO *'

反対に、コールドキャッシュでベンチマークを実行する場合は、-p/--prepare オプションを使って、各ベンチマーク実行の前に特別なコマンドを実行できます。たとえば、Linux のファイルシステムキャッシュをクリアするには、次のコマンドを実行します。

sync; echo 3 | sudo tee /proc/sys/vm/drop_caches

このコマンドを hyperfine で使用するには、sudo -v を呼び出して一時的に sudo 権限を取得してから、次のように実行します。

hyperfine -S --prepare 'sync; echo 3 | sudo tee /proc/sys/vm/drop_caches' 'grep -R TODO *'
パラメーター化されたベンチマーク

単一のパラメーター(たとえばスレッド数)を変化させながら、一連のベンチマークを実行する場合は、-P/--parameter-scan オプションを使って、次のように呼び出します。

hyperfine --prepare 'make clean' --parameter-scan num_threads 1 12 'make -j {num_threads}'

これは小数にも対応しています。ステップ幅は -D/--parameter-step-size オプションで設定できます。

hyperfine --parameter-scan delay 0.3 0.7 -D 0.2 'sleep {delay}'

これにより、sleep 0.3、sleep 0.5、sleep 0.7 が実行されます。

数値以外のパラメーターの場合は、-L/--parameter-list オプションを使って値のリストを指定することもできます。

hyperfine -L compiler g++,clang++ '{compiler} -O2 main.cpp'

よくある用途として、複数の Git ブランチ間で同じコマンドを比較するケースがあります。ベンチマーク実行の各セットの前に一度だけブランチを切り替えるには、--setup を使用します。これにより、ブランチの切り替えが測定対象のコマンドに含まれなくなります。

hyperfine \
    --parameter-list branch main,performance-improvements \
    --setup 'git switch {branch}' \
    'python main.py'

ベンチマークコマンドの個々の実行ごとに一意の値が必要な場合、hyperfine はベンチマーク対象のコマンド内で、0から始まる $HYPERFINE_ITERATION 環境変数も提供します。

hyperfine -S 'my-command > output-${HYPERFINE_ITERATION}.log'
中間シェル

デフォルトでは、ウォームアップ実行を含め、ベンチマーク対象のコマンドは中間シェルを介さずに直接実行されます(--shell=none)。 引数はシェル風の引用符ルールに従って分割されるため、スペースを含む引用符付きの引数も使用できます。 パイプ、リダイレクト、環境変数の展開、*、~ などのシェル構文は解釈されません。 これにより、シェルの起動によるオーバーヘッドや、その補正による測定ノイズを避けられます。特に高速なコマンド( 5 ms 未満)で効果があります。

&& や > など、引用符で囲まれていない単独のシェル演算子を含むコマンドでは、明示的な選択が必要です。シェル構文を解釈するには -S / --shell=default を使用し、演算子をリテラル引数として渡すには -N / --shell=none を使用してください。

シェル構文を有効にするには、-S(--shell=default のエイリアス)を使用します。これにより、Unix では sh (PATH 経由で解決)、Windows では cmd.exe が選択されます。

hyperfine -S 'sleep 0.1 && echo done'

--shell <SHELL> を指定して、特定のシェルを選択することもできます。

hyperfine --shell zsh 'for i in {1..10000}; do echo test; done'

--setup、--prepare、--conclude、--cleanup の各コマンドは、常にシェル経由で実行されます。 --shell で選択されたシェルを使用します。--shell が省略されているか none に設定されている場合は、プラットフォームのシェル(Unix では sh、Windows では cmd.exe)を使用します。

ベンチマーク対象のコマンドがシェルを使用する場合、hyperfine は シェルの起動時間を補正します。空のコマンドを指定してシェルを複数回実行して起動時間を測定し、その時間を各測定時間から差し引きます。

シェル関数

bash を使用している場合は、シェル関数をエクスポートして、hyperfine で直接ベンチマークできます。

my_function() { sleep 1; }
export -f my_function
hyperfine --shell=bash my_function

それ以外の場合は、ベンチマーク対象のコマンドに関数をインラインで記述してください。

hyperfine -S 'my_function() { sleep 1; }; my_function'
環境変数

--env を使用すると、ベンチマーク対象のコマンドと、それぞれのセットアップ、準備、終了処理、クリーンアップのコマンドに環境変数を設定できます。代入はスペースで区切り、シェル形式の引用符を使用できますが、 シェルによる展開は行われません。

hyperfine --env 'OMP_NUM_THREADS=8 CFLAGS="-O3 -march=native"' 'my_command'

すべてのコマンドに一度だけ指定することも、ベンチマーク対象のコマンドごとに指定することもできます。

hyperfine \
  --env 'OMP_NUM_THREADS=8' './benchmark-cpp' \
  --env 'RAYON_NUM_THREADS=8' './benchmark-rust'

上書きを行わない場合は、空の --env='' を使用してください。値にはパラメーターのプレースホルダーを含められます。 たとえば、次の例では OMP_NUM_THREADS を 1 から 8 まで変化させて my_command をベンチマークします。

hyperfine -P threads 1 8 --env 'OMP_NUM_THREADS={threads}' 'my_command'
メトリクスと単位の選択

デフォルトでは、hyperfine は実時間とメモリ使用量 (time_wall_clock,memory_peak_resident)を表示します。別のメトリクスのセットを選択するには、カンマ区切りのリストを指定して --metrics を使用します。各メトリクスには、任意で単位を指定できます。

hyperfine \
    --metrics memory_peak_resident:MiB,time_wall_clock:ms,instructions \
    './baseline' './candidate'

以下のメトリクスを使用できます。

  • time_wall_clock:開始から終了までの時間です。待機に費やした時間を含み、単位は秒です。

  • time_user:ユーザーモードでアプリケーションおよびライブラリのコードを実行するのに費やした CPU 時間です。スレッド間で合算され、単位は秒です。

    • Linux/macOS:親プロセスが子プロセスの終了を待つ場合、子プロセスの時間を含みます。
    • Windows:コマンドとその子プロセスを含みます。
  • time_system:ファイルの読み取りなど、プログラムに代わってカーネルコードを実行するのに費やした CPU 時間です。スレッド間で合算され、単位は秒です。

    • Linux/macOS:親プロセスが子プロセスの終了を待つ場合、子プロセスの時間を含みます。
    • Windows:コマンドとその子プロセスを含みます。
  • time_cpu:実行ごとに time_user + time_system として計算される、合計 CPU 時間です。スリープ中や、実行を伴わない待機に費やした時間は含まれません。CPU 時間はスレッド間で合算されるため、実時間を超えることがあります。4 つのコアで 4 つのスレッドを 1 秒間実行した場合、約 4 CPU 秒を消費します。

  • memory_peak_resident:物理 RAM 上で使用されたメモリの最大値です。単位はバイトです。

    • Linux/macOS:最大常駐セットサイズ(RSS)です。コマンドと子プロセス(親プロセスが子プロセスを待つ際に使用量を取得)のプロセスごとのピーク値のうち、最大のものです。プロセスツリー全体の同時点での合計メモリ使用量ではありません。Linux では、非常に小さなピーク RSS(起動時に hyperfine が継承したピーク値を下回る値。数 MiB 程度の場合があります)のコマンドを測定すると、現時点では継承した値が報告されます。
    • Windows:現在はサポートされていません。
  • cpu_cycles:消費された CPU サイクル数です。

    • Linux:スレッドと子プロセスを含みますが、カーネルおよびハイパーバイザーの実行は含みません。
    • macOS:プロセスのスレッドとカーネルの実行を含みますが、子プロセスは含みません。
    • Windows:現在はサポートされていません。
  • instructions:完了した CPU 命令数です。

    • Linux/macOS:cpu_cycles と同じ範囲です。
    • Windows:現在はサポートされていません。
  • cache_references:CPU の汎用キャッシュイベントでカウントされたキャッシュアクセス数です。

    • Linux:cpu_cycles と同じ範囲です。キャッシュイベントの定義は CPU によって異なります。
    • macOS/Windows:現在はサポートされていません。
  • cache_misses:キャッシュミス数です。

    • Linux:cpu_cycles と同じ範囲です。キャッシュイベントの定義は CPU によって異なります。
    • macOS/Windows:現在はサポートされていません。
  • branch_misses:誤予測された分岐数です。

    • Linux:cpu_cycles と同じ範囲です。
    • macOS/Windows:現在はサポートされていません。

シェルが有効(--shell=..)な場合、ハードウェアカウンターは使用できません。

時間の測定では、ns、us、ms、s、min、h の単位を使用できます。メモリの測定では、B、kB、MB、GB、TB、KiB、MiB、GiB、TiB の単位を使用できます。ハードウェアカウンターでは、count(1)、k(千)、M(百万)、B(十億)を使用できます。

プリセットを使って、メトリクスのグループを選択することもできます。

プリセットメトリクス
--metrics=defaulttime_wall_clock,memory_peak_resident
--metrics=timetime_wall_clock,time_cpu,time_user,time_system
--metrics=all使用可能なすべてのメトリクス
結果のエクスポート

Hyperfine は結果を CSV、JSON、Markdown、AsciiDoc、org-mode にエクスポートできます。CSV には選択したすべてのメトリクスが出力されます。一方、Markdown、AsciiDoc、org-mode には、--metrics で最初に選択したメトリクスである主要メトリクスのみが含まれます。

Markdown

--export-markdown <file> オプションを使用すると、次のような表を作成できます。

コマンド平均実行時間 [s]変化倍率
find . -iregex '.*[0-9]\.jpg$'2.275 ± 0.046
find . -iname '*[0-9].jpg'1.427 ± 0.026-37.3%(1.6x faster)
fd -HI '.*[0-9]\.jpg$'0.232 ± 0.002-89.8%(9.8x faster)
JSON

JSON エクスポートには、メトリクスと単位の選択に記載されている利用可能なすべてのメトリクスが、測定した実行ごとに含まれます(ウォームアップ実行を除く)。

JSON 出力は、ベンチマーク結果をより詳細に分析したい場合に便利です。scripts/ フォルダーには、実行時間のヒストグラムや複数のベンチマークを比較する箱ひげ図など、ベンチマーク結果をさらに分析し、有用な可視化を作成するための Python プログラムが多数含まれています。

たとえば、次の2つのコマンドを実行すると、以下のプロットが作成されます。

uvx --from 'git+https://github.com/sharkdp/hyperfine' \
  plot_histogram results.json
uvx --from 'git+https://github.com/sharkdp/hyperfine' \
  plot_whisker results.json
README の画像README の画像
CSV

--export-csv <file> を使用すると、コマンドごとに1行をエクスポートできます。--metrics で選択した各メトリクスについて、選択順に次の列グループが追加されます。<metric>_unit、<metric>_mean、<metric>_stddev、<metric>_median、<metric>_min、<metric>_max。

CSV では、明示的に選択した単位が使用されます。指定がない場合は基本単位(秒、バイト、または回数)が使用されます。

ベンチマーク実行の詳細なフローチャート

次の図は、--warmup、--prepare <cmd>、--setup <cmd>、--cleanup <cmd> などのオプションを使用する場合に、さまざまなベンチマーク実行がどの順序で行われるかを示しています。

README の画像

インストール

パッケージ状況

Ubuntu の場合

Ubuntu では、hyperfine を公式リポジトリからインストールできます。

apt install hyperfine

または、最新バージョンを利用するには、リリースページから適切な .deb パッケージをダウンロードし、dpkg でインストールできます。

wget https://github.com/sharkdp/hyperfine/releases/download/v2.0.0/hyperfine_2.0.0_amd64.deb
sudo dpkg -i hyperfine_2.0.0_amd64.deb
Fedora の場合

Fedora では、hyperfine を公式リポジトリからインストールできます。

dnf install hyperfine
Alpine Linux の場合

Alpine Linux では、hyperfine を公式リポジトリからインストールできます。

apk add hyperfine
Arch Linux の場合

Arch Linux では、hyperfine を公式リポジトリからインストールできます。

pacman -S hyperfine
Debian Linux の場合

Debian Linux では、hyperfine を公式リポジトリからインストールできます。

apt install hyperfine
Exherbo Linux の場合

Exherbo Linux では、hyperfine をrust リポジトリからインストールできます。

cave resolve -x repository/rust
cave resolve -x hyperfine
NixOS の場合

NixOS では、hyperfine を公式リポジトリからインストールできます。

nix-env -i hyperfine
Flox の場合

Flox では、次のように hyperfine をインストールできます。

flox install hyperfine

Flox での Hyperfine のバージョンは、Nix のバージョンに準じます。

openSUSE の場合

openSUSE では、hyperfine を公式リポジトリからインストールできます。

zypper install hyperfine
Void Linux の場合

Hyperfine は xbps でインストールできます。

xbps-install -S hyperfine
macOS の場合

Hyperfine は Homebrew でインストールできます。

brew install hyperfine

または、MacPorts を使用してインストールできます。

sudo port selfupdate
sudo port install hyperfine
FreeBSD の場合

Hyperfine は pkg でインストールできます。

pkg install hyperfine
OpenBSD の場合
doas pkg_add hyperfine
Windows の場合

Hyperfine は、Chocolatey、Scoop、または Winget からインストールできます。

choco install hyperfine
scoop install hyperfine
winget install hyperfine
conda を使用する場合

Hyperfine は、conda-forge チャンネルから conda を使用してインストールできます。

conda install -c conda-forge hyperfine
cargo を使用する場合(Linux、macOS、Windows)

Hyperfine は、cargo を使用してソースからインストールできます。

cargo install --locked hyperfine

Rust 1.97 以降を使用していることを確認してください。

バイナリからインストールする場合(Linux、macOS、Windows)

リリースページから該当するアーカイブをダウンロードしてください。

代替ツール

Hyperfine は bench に着想を得ています。

他のツールとの連携

Chronologer は、hyperfine を使用して、Git の履歴全体にわたるベンチマーク時間の変化を可視化するツールです。

Bencher は、hyperfine に対応した継続的ベンチマークツールで、ベンチマークを追跡し、CI でパフォーマンスの低下を検出できます。

Hyperfine の JSON 出力を Venz のチャートにドロップすると、結果を可視化し、Hyperfine の設定を管理できます。

hyperfine のベンチマーク結果を扱うツール一式については、このリポジトリの scripts フォルダーもご覧ください。

名前の由来

hyperfine という名前は、時間の基本単位の定義(秒)において重要な役割を果たす、セシウム133の超微細準位にちなんで付けられました。

hyperfine の引用

研究で hyperfine の引用をご検討いただき、ありがとうございます。適切な引用方法については、サイドバーの情報をご覧ください。

ライセンス

hyperfine は、MIT License および Apache License 2.0 の条件に基づくデュアルライセンスです。

詳細については、LICENSE-APACHE ファイルと LICENSE-MIT ファイルをご覧ください。

コメント