コンテンツにスキップ

ベンチマーク

起動〜最初のクエリテストごとの複製インデックス SELECT20万行ソートDB と計測プロセスのメモリダウンロード
pgmem(Go ライブラリ)70 ms14 ms (フォーク)34 µs10 µs プロセス内接続120 ms110 MiB計測プロセスの増分 110 MiB37.9 MB (テストバイナリへのリンク増分)
pgmem バイナリ(Python / Java / Node.js)218 ms14 ms (フォーク)34 µs120 ms105 MiB16.8 MB (wheel / jar / npm の中身)
docker run1.65 s61 ms (CREATE DATABASE … TEMPLATE)93 µs259 ms77 MiBコンテナ使用量 76 MiB, 計測プロセスの増分 1 MiB, VM の差分 433 MiB, VM 絶対値 1335 MiB118 MB (イメージレイヤ)
Testcontainers(Go)1.09 s21 ms (Snapshot / Restore)102 µs258 ms137 MiBコンテナ使用量 134 MiB, 計測プロセスの増分 2 MiB, VM の差分 295 MiB, VM 絶対値 1192 MiB120 MB (イメージレイヤ + Ryuk)
devbox(nix の PostgreSQL)411 ms83 ms (CREATE DATABASE … TEMPLATE)28 µs228 ms36 MiBPostgreSQL プロセス合計113 MB (nix closure)

2026-09-14 計測、5 回の中央値。Apple M3、8 コア、16 GB、Darwin 27.0.0。OrbStack 2.2.3(Docker 29.4.0)、arm64。メモリ列は DB 使用量と計測プロセスの増分を比べます。Testcontainers は PostgreSQL と Ryuk のコンテナ使用量を含みます。VM の差分と絶対値は参考値として分けており、OrbStack がメモリを解放すると差分は小さくなります。

ベンチマーク中の DB と計測プロセスのメモリ

ベンチマーク中の DB と計測プロセスのメモリ棒は中央値、ひげは各回の最小値から最大値です。Docker と Testcontainers はコンテナ使用量と計測プロセスの増分を合算します。Testcontainers には PostgreSQL と Ryuk が含まれます。OrbStack VM は負荷中にメモリを解放することがあるため、VM の差分は別に示します。スキーマ準備後query・分離計測後0100200300400500pgmem(Go ライブラリ)110 MiB (110–140)445 MiB (417–478)pgmem バイナリ105 MiB (105–107)docker run77 MiB (76–77)92 MiB (92–93)Testcontainers(Go)137 MiB (136–137)180 MiB (177–180)devbox36 MiB (36–36)54 MiB (50–54)DB と計測プロセスのメモリ (MiB)
棒は中央値、ひげは各回の最小値から最大値です。Docker と Testcontainers はコンテナ使用量と計測プロセスの増分を合算します。Testcontainers には PostgreSQL と Ryuk が含まれます。OrbStack VM は負荷中にメモリを解放することがあるため、VM の差分は別に示します。

どの計測も、新しいプロセスでサーバーを 1 つ起動し、同じスキーマを流し込んでから測ります。ハーネスは bench/alternatives にあります。

  • 起動〜最初のクエリ:起動処理を呼び出してから、TCP 経由の SELECT 1 が成功するまで。docker pulldevbox install は計測前に実行し、Devbox 環境の解決も計測外の準備で済ませます。docker run は新規コンテナと DB クラスタの初期化を含みます。Devbox は初期化済みの永続クラスタと app DB を計測前に準備し、devbox services up -b の実行から SQL ready までを計ります。Testcontainers は新しいテストプロセスが起動する Ryuk コンテナも含みます。pgmem バイナリは ready 行が出るまでを計り、Python、Java、Node.js のラッパーはその行を待ちます。
  • テストごとの複製:準備済みデータベース(ユーザー 1,000 件、注文 10,000 件)の独立した複製を 20 回作り、そのたびに接続して結合クエリを 1 本流したときの中央値です。pgmem はスナップショットからフォークします。docker run と devbox は CREATE DATABASE … TEMPLATEDROP DATABASE、Testcontainers は PostgreSQL モジュールの SnapshotRestore を使います。後者も内部ではテンプレートデータベースで同じことをしています。
  • インデックス SELECT:pgx で SELECT v FROM bench WHERE id = $1 をウォームアップ後に 3,000 回。pgmem の 2 つ目の値は、TCP の代わりにプロセス内ダイヤラ(Server.Dial)を使ったものです。
  • 20万行ソートSELECT count(*) FROM (SELECT md5(i::text) AS h FROM generate_series(1, 200000) i ORDER BY h) t を、ウォームアップ 1 回の後に 3 回流した中央値です。
  • メモリ:負荷中に OrbStack VM がメモリを返すと、コンテナの使用量が多くても Testcontainers の値が docker run より小さく見えることがあります。そこでグラフは VM の差分を使わず、DB 側の使用量と計測プロセスの増分を比べます。pgmem はプロセスの phys_footprint 増分、バイナリは単独の pgmem プロセスを使います。Docker と Testcontainers は各コンテナの Docker 使用量に Go の計測プロセスの増分を足します。Testcontainers には PostgreSQL と Ryuk が含まれ、メモリ値には docker stats の表示を使います(Linux CLI はキャッシュを差し引きます)。devbox は PostgreSQL のポストマスターと子プロセスを合算します。OrbStack VM の差分と絶対値は表に分けて載せています。
  • ダウンロード:初回に取得するもの。Go ライブラリとしての pgmem は、strip したテストバイナリがリンクによって増える量です。バイナリの行は wheel、jar、npm パッケージが同梱する圧縮済みバイナリの大きさです。イメージは計測したアーキテクチャの圧縮レイヤ、nix closure は devbox が cache.nixos.org から取得する量です。
  • 既定値が違います。 サーバーは PostgreSQL の既定値(shared_buffers=128MB)を使います。Testcontainers の計測では PostgreSQL 18 のデータディレクトリ(/var/lib/postgresql/18/docker)を tmpfs にマウントし、docker run と devbox はディスクを使います。pgmem は shared_buffers=32MB でファイルシステムもメモリ上にあるため、一時ファイルにあふれるソートでもディスクに触れません。
  • グラフは DB と計測プロセスのメモリを比べます。 スキーマ準備後とクエリ・分離計測後の中央値および計測回ごとの範囲を示します。Testcontainers は PostgreSQL と Ryuk のコンテナ使用量を含みます。Linux の docker stats CLI は表示値からキャッシュを差し引きます。
  • OrbStack VM の差分は別の参考値です。 コンテナの計測ごとに VM を再起動し、アイドル時を記録します。VM は実行中にメモリを解放することがあり、コンテナ使用量が増えても VM の差分が下がる場合があります。表では差分と VM の絶対値を分けています。
  • pgmem のメモリは負荷で増えます。 WebAssembly のリニアメモリはサーバー稼働中は OS に返らず、生きているフォークはそれぞれ自分の複製を持ちます。生きているフォーク 1 つあたりアイドル時の値程度を見込み、MaxForks で数を抑えてください。
  • コンテナ方式の差には実行条件も含まれます。 docker run はディスク上に保存しますが、Testcontainers は PGDATA を tmpfs に置き、Ryuk も起動します。そのため、差には保存先と起動方式の違いが含まれます。
ターミナルウィンドウ
cd bench/alternatives
RUNS=5 MEM_RUNS=3 ./run.sh

OrbStack と devbox が必要です。メモリ計測のパスでは OrbStack を再起動しますが、ほかのコンテナが動いているときは再起動せずに止まります。生の計測値を results/raw.jsonl、中央値を results/summary.json に書き、要約を website/src/data/benchmarks.json にコピーします。このサイトの表はそのファイルを描画しています。