コンテンツにスキップ

pgmem

テストのための、メモリ上で動く本物の PostgreSQL 18。Docker もディスクも使いません。スキーマを一度だけ準備し、読み取りテストで共有し、書き込みテストにはミリ秒で専用の複製を渡します。

同じテストスイート、2 つの実行モデル

Section titled “同じテストスイート、2 つの実行モデル”

小さなショップのデータ層に 70 本のテスト(参照のみ 50 本、更新 20 本)を書きました。共有の PostgreSQL サーバー 1 台(ここでは Testcontainers で起動)では、更新テストは共有データのリセットを挟んで 1 本ずつ順番に走るしかありません。pgmem ではマイグレーションとシードデータの投入後にスナップショットを 1 回取り、参照テストはそのデータベースを共用し、更新テストだけが自分のコピーをフォークするので、スナップショット以降はすべて並列に走ります。

同じ 70 本のテスト(参照 50、更新 20)を、同じスキーマ・マイグレーション・シードデータで、go test の並列度 8 で実行しました。各タイムラインは Apple M3(8 コア)で 5 回走らせたうち合計時間が中央値だった実行です。バーは各実行モデルのノードで、左に短くまとまっているほど速いことを表します。

スイート全体の実時間

  • pgmem204 ms
    5 回の範囲 196 ms〜219 ms
  • Testcontainers 共有サーバー 1 台1.73 s
    5 回の範囲 1.70 s〜1.81 s
  • PostgreSQL 共有サーバー 1 台646 ms
    5 回の範囲 633 ms〜671 ms
  • docker run 共有サーバー 1 台2.48 s
    5 回の範囲 2.26 s〜3.59 s

テストは go test -parallel の 8 枠に描いています。1 つの枠には、そこで順に走ったテストが並びます。 タイムラインはすべて同じ時間軸です。

  • DB 起動
  • スキーマ投入 + マスタデータ投入
  • スナップショット
  • フォーク(更新テスト専用のコピー)
  • サンプルデータ投入
  • データのリセット
  • 参照テスト
  • 更新テスト
pgmem 204 ms 合計テストプロセス内。参照テストはテンプレートを共用し、更新テストはスナップショットからフォークして、すべて並列に走るフォークは 20 本で、更新テスト(20 本)1 本につき 1 本です。参照テスト 50 本はフォークせず、テンプレートのデータベースをそのまま使います。
pgmem: 代表実行のタイムライン, 204 ms050010001500合計 204 msTestMainTestMain · DB 起動: 39 ms (0.0 → 39 ms)TestMain · スキーマ投入 + マスタデータ投入: 47 ms (39 → 86 ms)TestMain · スナップショット: 3.2 ms (86 → 89 ms)共有データベース(参照テスト)共有データベース(参照テスト) · サンプルデータ投入: 13 ms (122 → 135 ms)並列枠 1CreateOrder/two_lines · フォーク(更新テスト専用のコピー): 13 ms (89 → 102 ms)CreateOrder/two_lines · サンプルデータ投入: 18 ms (103 → 121 ms)CreateOrder/two_lines · 更新テスト: 1.2 ms (121 → 122 ms)TopProducts/top_1 · 参照テスト: 0.5 ms (135 → 135 ms)TopProducts/top_30 · 参照テスト: 0.6 ms (135 → 136 ms)TopProducts/top_8 · 参照テスト: 1.1 ms (136 → 137 ms)TopProducts/top_2 · 参照テスト: 1.0 ms (137 → 138 ms)ApplyDiscount/games_0 · フォーク(更新テスト専用のコピー): 10 ms (138 → 148 ms)ApplyDiscount/games_0 · サンプルデータ投入: 13 ms (148 → 161 ms)ApplyDiscount/games_0 · 更新テスト: 0.4 ms (161 → 161 ms)ListOrders/user_71 · 参照テスト: 0.1 ms (161 → 161 ms)ListOrders/user_64 · 参照テスト: 0.1 ms (161 → 161 ms)ListOrders/user_57 · 参照テスト: 0.5 ms (161 → 162 ms)ListOrders/user_22 · 参照テスト: 0.8 ms (162 → 163 ms)ListOrders/user_29 · 参照テスト: 0.5 ms (163 → 163 ms)SearchProducts/product_1 · 参照テスト: 1.0 ms (163 → 164 ms)SearchProducts/product_8 · 参照テスト: 0.8 ms (164 → 165 ms)並列枠 2CreateOrder/five_lines · フォーク(更新テスト専用のコピー): 14 ms (89 → 103 ms)CreateOrder/five_lines · サンプルデータ投入: 12 ms (103 → 116 ms)CreateOrder/five_lines · 更新テスト: 0.9 ms (116 → 116 ms)ShipOrder/one_paid · フォーク(更新テスト専用のコピー): 8.8 ms (117 → 126 ms)ShipOrder/one_paid · サンプルデータ投入: 18 ms (126 → 144 ms)ShipOrder/one_paid · 更新テスト: 0.4 ms (144 → 144 ms)GetOrder/orders_6_16_26_36 · 参照テスト: 3.5 ms (145 → 148 ms)RevenueByCategory/Garden · 参照テスト: 0.8 ms (148 → 149 ms)RevenueByCategory/Toys · 参照テスト: 0.3 ms (149 → 150 ms)RevenueByCategory/Games · 参照テスト: 0.3 ms (150 → 150 ms)RevenueByCategory/Music · 参照テスト: 0.4 ms (150 → 150 ms)GetOrder/orders_10_20_30_40 · 参照テスト: 2.0 ms (150 → 152 ms)SearchProducts/product_0 · 参照テスト: 0.8 ms (152 → 153 ms)DeleteUser/user_36 · フォーク(更新テスト専用のコピー): 11 ms (153 → 164 ms)DeleteUser/user_36 · サンプルデータ投入: 9.6 ms (164 → 173 ms)DeleteUser/user_36 · 更新テスト: 0.3 ms (173 → 174 ms)並列枠 3CreateOrder/out_of_stock · フォーク(更新テスト専用のコピー): 13 ms (89 → 102 ms)CreateOrder/out_of_stock · サンプルデータ投入: 20 ms (102 → 122 ms)CreateOrder/out_of_stock · 更新テスト: 0.2 ms (122 → 122 ms)TopProducts/top_10 · 参照テスト: 1.5 ms (135 → 136 ms)TopProducts/top_20 · 参照テスト: 1.4 ms (136 → 138 ms)ApplyDiscount/movies_50 · フォーク(更新テスト専用のコピー): 9.3 ms (138 → 147 ms)ApplyDiscount/movies_50 · サンプルデータ投入: 13 ms (147 → 160 ms)ApplyDiscount/movies_50 · 更新テスト: 0.6 ms (160 → 161 ms)ListOrders/user_43 · 参照テスト: 0.2 ms (161 → 161 ms)SearchProducts/product_4 · 参照テスト: 0.3 ms (161 → 162 ms)ListOrders/user_36 · 参照テスト: 0.4 ms (162 → 162 ms)ListOrders/user_15 · 参照テスト: 0.7 ms (162 → 163 ms)SearchProducts/product_2 · 参照テスト: 0.9 ms (163 → 164 ms)SearchProducts/product_6 · 参照テスト: 0.6 ms (164 → 164 ms)SearchProducts/product_5 · 参照テスト: 0.7 ms (164 → 165 ms)並列枠 4CreateOrder/one_line · フォーク(更新テスト専用のコピー): 16 ms (89 → 106 ms)CreateOrder/one_line · サンプルデータ投入: 14 ms (106 → 119 ms)CreateOrder/one_line · 更新テスト: 0.5 ms (119 → 120 ms)ShipOrder/twice · フォーク(更新テスト専用のコピー): 10 ms (120 → 130 ms)ShipOrder/twice · サンプルデータ投入: 10 ms (130 → 141 ms)ShipOrder/twice · 更新テスト: 3.5 ms (141 → 144 ms)GetOrder/orders_5_15_25_35 · 参照テスト: 3.1 ms (145 → 148 ms)GetOrder/orders_2_12_22_32 · 参照テスト: 2.3 ms (148 → 151 ms)RevenueByCategory/Outdoors · 参照テスト: 0.6 ms (151 → 151 ms)RevenueByCategory/Sports · 参照テスト: 0.5 ms (151 → 152 ms)GetOrder/orders_8_18_28_38 · 参照テスト: 1.8 ms (152 → 154 ms)DeleteUser/user_22 · フォーク(更新テスト専用のコピー): 8.6 ms (154 → 162 ms)DeleteUser/user_22 · サンプルデータ投入: 9.8 ms (162 → 172 ms)DeleteUser/user_22 · 更新テスト: 0.3 ms (172 → 172 ms)並列枠 5CancelOrder/paid · フォーク(更新テスト専用のコピー): 12 ms (89 → 102 ms)CancelOrder/paid · サンプルデータ投入: 17 ms (102 → 119 ms)CancelOrder/paid · 更新テスト: 0.7 ms (119 → 119 ms)ShipOrder/pending_rejected · フォーク(更新テスト専用のコピー): 8.3 ms (121 → 129 ms)ShipOrder/pending_rejected · サンプルデータ投入: 18 ms (129 → 146 ms)ShipOrder/pending_rejected · 更新テスト: 0.2 ms (146 → 147 ms)GetOrder/orders_4_14_24_34 · 参照テスト: 2.3 ms (147 → 150 ms)RevenueByCategory/Movies · 参照テスト: 0.4 ms (150 → 150 ms)GetOrder/orders_9_19_29_39 · 参照テスト: 2.1 ms (150 → 152 ms)DeleteUser/user_15 · フォーク(更新テスト専用のコピー): 5.8 ms (152 → 158 ms)DeleteUser/user_15 · サンプルデータ投入: 14 ms (158 → 172 ms)DeleteUser/user_15 · 更新テスト: 0.3 ms (172 → 172 ms)並列枠 6CancelOrder/another_paid · フォーク(更新テスト専用のコピー): 15 ms (89 → 105 ms)CancelOrder/another_paid · サンプルデータ投入: 12 ms (105 → 116 ms)CancelOrder/another_paid · 更新テスト: 2.8 ms (116 → 119 ms)TopProducts/top_50 · 参照テスト: 1.7 ms (135 → 136 ms)TopProducts/top_15 · 参照テスト: 2.1 ms (136 → 139 ms)ApplyDiscount/music_25 · フォーク(更新テスト専用のコピー): 11 ms (139 → 149 ms)ApplyDiscount/music_25 · サンプルデータ投入: 9.7 ms (149 → 159 ms)ApplyDiscount/music_25 · 更新テスト: 0.5 ms (159 → 160 ms)ListOrders/user_50 · 参照テスト: 1.4 ms (162 → 163 ms)SearchProducts/product_3 · 参照テスト: 1.8 ms (163 → 165 ms)SearchProducts/product_9 · 参照テスト: 0.3 ms (165 → 165 ms)並列枠 7CancelOrder/shipped · フォーク(更新テスト専用のコピー): 14 ms (90 → 104 ms)CancelOrder/shipped · サンプルデータ投入: 11 ms (104 → 115 ms)CancelOrder/shipped · 更新テスト: 0.5 ms (115 → 116 ms)ShipOrder/all_paid · フォーク(更新テスト専用のコピー): 6.0 ms (118 → 124 ms)ShipOrder/all_paid · サンプルデータ投入: 12 ms (124 → 136 ms)ShipOrder/all_paid · 更新テスト: 0.9 ms (136 → 136 ms)TopProducts/top_3 · 参照テスト: 2.3 ms (137 → 139 ms)GetOrder/orders_1_11_21_31 · 参照テスト: 0.9 ms (139 → 140 ms)GetOrder/orders_7_17_27_37 · 参照テスト: 0.5 ms (140 → 141 ms)RevenueByCategory/Books · 参照テスト: 6.7 ms (141 → 147 ms)GetOrder/orders_3_13_23_33 · 参照テスト: 3.4 ms (147 → 151 ms)RevenueByCategory/Kitchen · 参照テスト: 0.9 ms (151 → 152 ms)RevenueByCategory/Tools · 参照テスト: 0.4 ms (152 → 152 ms)ListOrders/user_8 · 参照テスト: 0.5 ms (152 → 152 ms)SearchProducts/product_7 · 参照テスト: 0.8 ms (153 → 153 ms)DeleteUser/user_29 · フォーク(更新テスト専用のコピー): 10 ms (153 → 164 ms)DeleteUser/user_29 · サンプルデータ投入: 9.6 ms (164 → 173 ms)DeleteUser/user_29 · 更新テスト: 0.3 ms (173 → 174 ms)並列枠 8CancelOrder/pending · フォーク(更新テスト専用のコピー): 13 ms (90 → 103 ms)CancelOrder/pending · サンプルデータ投入: 16 ms (103 → 119 ms)CancelOrder/pending · 更新テスト: 0.7 ms (119 → 120 ms)TopProducts/top_5 · 参照テスト: 2.0 ms (135 → 137 ms)ApplyDiscount/books_10 · フォーク(更新テスト専用のコピー): 7.6 ms (137 → 145 ms)ApplyDiscount/books_10 · サンプルデータ投入: 19 ms (145 → 165 ms)ApplyDiscount/books_10 · 更新テスト: 0.4 ms (165 → 165 ms)スイート開始からのミリ秒
Testcontainers 共有サーバー 1 台 1.73 s 合計公式イメージを testcontainers-go の postgres モジュールでオンメモリ起動(tmpfs、fsync なし)。更新テストはリセットを挟んで順番に走るコピーはなく、参照テスト 50 本と更新テスト 20 本が 1 つのデータベースを共有します。
Testcontainers 共有サーバー 1 台: 代表実行のタイムライン, 1.73 s050010001500合計 1.73 sTestMainTestMain · DB 起動: 761 ms (0.0 → 761 ms)761TestMain · スキーマ投入 + マスタデータ投入: 108 ms (761 → 868 ms)108共有データベース(参照テスト)共有データベース(参照テスト) · データのリセット: 5.1 ms (1.62 s → 1.63 s ms)共有データベース(参照テスト) · サンプルデータ投入: 29 ms (1.63 s → 1.65 s ms)並列枠 1CreateOrder/two_lines · データのリセット: 9.2 ms (869 → 878 ms)CreateOrder/two_lines · サンプルデータ投入: 36 ms (878 → 913 ms)CreateOrder/two_lines · 更新テスト: 2.0 ms (913 → 915 ms)CreateOrder/one_line · データのリセット: 8.1 ms (915 → 923 ms)CreateOrder/one_line · サンプルデータ投入: 28 ms (923 → 951 ms)CreateOrder/one_line · 更新テスト: 0.9 ms (951 → 952 ms)CreateOrder/five_lines · データのリセット: 7.6 ms (952 → 960 ms)CreateOrder/five_lines · サンプルデータ投入: 27 ms (960 → 987 ms)CreateOrder/five_lines · 更新テスト: 1.9 ms (987 → 989 ms)CreateOrder/out_of_stock · データのリセット: 7.5 ms (989 → 996 ms)CreateOrder/out_of_stock · サンプルデータ投入: 27 ms (996 → 1.02 s ms)CreateOrder/out_of_stock · 更新テスト: 0.4 ms (1.02 s → 1.02 s ms)CancelOrder/paid · データのリセット: 7.0 ms (1.02 s → 1.03 s ms)CancelOrder/paid · サンプルデータ投入: 26 ms (1.03 s → 1.06 s ms)CancelOrder/paid · 更新テスト: 1.7 ms (1.06 s → 1.06 s ms)CancelOrder/pending · データのリセット: 6.8 ms (1.06 s → 1.07 s ms)CancelOrder/pending · サンプルデータ投入: 27 ms (1.07 s → 1.09 s ms)CancelOrder/pending · 更新テスト: 1.3 ms (1.09 s → 1.09 s ms)CancelOrder/another_paid · データのリセット: 6.8 ms (1.09 s → 1.1 s ms)CancelOrder/another_paid · サンプルデータ投入: 28 ms (1.1 s → 1.13 s ms)CancelOrder/another_paid · 更新テスト: 1.4 ms (1.13 s → 1.13 s ms)CancelOrder/shipped · データのリセット: 6.9 ms (1.13 s → 1.14 s ms)CancelOrder/shipped · サンプルデータ投入: 28 ms (1.14 s → 1.17 s ms)CancelOrder/shipped · 更新テスト: 0.4 ms (1.17 s → 1.17 s ms)ShipOrder/one_paid · データのリセット: 6.6 ms (1.17 s → 1.17 s ms)ShipOrder/one_paid · サンプルデータ投入: 28 ms (1.17 s → 1.2 s ms)ShipOrder/one_paid · 更新テスト: 0.5 ms (1.2 s → 1.2 s ms)ShipOrder/pending_rejected · データのリセット: 6.1 ms (1.2 s → 1.21 s ms)ShipOrder/pending_rejected · サンプルデータ投入: 30 ms (1.21 s → 1.24 s ms)ShipOrder/pending_rejected · 更新テスト: 0.2 ms (1.24 s → 1.24 s ms)ShipOrder/all_paid · データのリセット: 7.7 ms (1.24 s → 1.24 s ms)ShipOrder/all_paid · サンプルデータ投入: 40 ms (1.24 s → 1.28 s ms)ShipOrder/all_paid · 更新テスト: 4.2 ms (1.28 s → 1.29 s ms)ShipOrder/twice · データのリセット: 8.4 ms (1.29 s → 1.3 s ms)ShipOrder/twice · サンプルデータ投入: 37 ms (1.3 s → 1.33 s ms)ShipOrder/twice · 更新テスト: 0.5 ms (1.33 s → 1.34 s ms)DeleteUser/user_15 · データのリセット: 4.9 ms (1.34 s → 1.34 s ms)DeleteUser/user_15 · サンプルデータ投入: 32 ms (1.34 s → 1.37 s ms)DeleteUser/user_15 · 更新テスト: 0.8 ms (1.37 s → 1.37 s ms)DeleteUser/user_22 · データのリセット: 5.3 ms (1.37 s → 1.38 s ms)DeleteUser/user_22 · サンプルデータ投入: 30 ms (1.38 s → 1.41 s ms)DeleteUser/user_22 · 更新テスト: 0.6 ms (1.41 s → 1.41 s ms)DeleteUser/user_29 · データのリセット: 5.9 ms (1.41 s → 1.41 s ms)DeleteUser/user_29 · サンプルデータ投入: 29 ms (1.41 s → 1.44 s ms)DeleteUser/user_29 · 更新テスト: 0.6 ms (1.44 s → 1.44 s ms)DeleteUser/user_36 · データのリセット: 6.0 ms (1.44 s → 1.45 s ms)DeleteUser/user_36 · サンプルデータ投入: 28 ms (1.45 s → 1.48 s ms)DeleteUser/user_36 · 更新テスト: 0.6 ms (1.48 s → 1.48 s ms)ApplyDiscount/books_10 · データのリセット: 5.7 ms (1.48 s → 1.48 s ms)ApplyDiscount/books_10 · サンプルデータ投入: 27 ms (1.48 s → 1.51 s ms)ApplyDiscount/books_10 · 更新テスト: 1.0 ms (1.51 s → 1.51 s ms)ApplyDiscount/music_25 · データのリセット: 6.0 ms (1.51 s → 1.52 s ms)ApplyDiscount/music_25 · サンプルデータ投入: 30 ms (1.52 s → 1.55 s ms)ApplyDiscount/music_25 · 更新テスト: 0.6 ms (1.55 s → 1.55 s ms)ApplyDiscount/movies_50 · データのリセット: 5.3 ms (1.55 s → 1.55 s ms)ApplyDiscount/movies_50 · サンプルデータ投入: 29 ms (1.55 s → 1.58 s ms)ApplyDiscount/movies_50 · 更新テスト: 0.6 ms (1.58 s → 1.58 s ms)ApplyDiscount/games_0 · データのリセット: 7.1 ms (1.58 s → 1.59 s ms)ApplyDiscount/games_0 · サンプルデータ投入: 29 ms (1.59 s → 1.62 s ms)ApplyDiscount/games_0 · 更新テスト: 0.6 ms (1.62 s → 1.62 s ms)TopProducts/top_1 · 参照テスト: 1.0 ms (1.65 s → 1.66 s ms)TopProducts/top_3 · 参照テスト: 0.8 ms (1.66 s → 1.66 s ms)TopProducts/top_2 · 参照テスト: 1.6 ms (1.66 s → 1.66 s ms)RevenueByCategory/Books · 参照テスト: 3.5 ms (1.66 s → 1.66 s ms)RevenueByCategory/Outdoors · 参照テスト: 1.9 ms (1.66 s → 1.66 s ms)RevenueByCategory/Sports · 参照テスト: 0.5 ms (1.66 s → 1.66 s ms)RevenueByCategory/Tools · 参照テスト: 0.8 ms (1.66 s → 1.66 s ms)RevenueByCategory/Kitchen · 参照テスト: 0.6 ms (1.66 s → 1.67 s ms)RevenueByCategory/Garden · 参照テスト: 0.8 ms (1.67 s → 1.67 s ms)RevenueByCategory/Games · 参照テスト: 0.6 ms (1.67 s → 1.67 s ms)RevenueByCategory/Movies · 参照テスト: 0.4 ms (1.67 s → 1.67 s ms)ListOrders/user_8 · 参照テスト: 1.0 ms (1.67 s → 1.67 s ms)ListOrders/user_57 · 参照テスト: 0.6 ms (1.67 s → 1.67 s ms)ListOrders/user_43 · 参照テスト: 1.2 ms (1.67 s → 1.67 s ms)GetOrder/orders_7_17_27_37 · 参照テスト: 2.9 ms (1.67 s → 1.67 s ms)SearchProducts/product_7 · 参照テスト: 1.9 ms (1.67 s → 1.67 s ms)並列枠 2TopProducts/top_10 · 参照テスト: 14 ms (1.65 s → 1.67 s ms)ListOrders/user_50 · 参照テスト: 1.6 ms (1.67 s → 1.67 s ms)GetOrder/orders_5_15_25_35 · 参照テスト: 2.7 ms (1.67 s → 1.67 s ms)SearchProducts/product_6 · 参照テスト: 0.8 ms (1.67 s → 1.67 s ms)SearchProducts/product_2 · 参照テスト: 1.9 ms (1.67 s → 1.68 s ms)並列枠 3TopProducts/top_50 · 参照テスト: 13 ms (1.65 s → 1.67 s ms)ListOrders/user_71 · 参照テスト: 2.0 ms (1.67 s → 1.67 s ms)GetOrder/orders_9_19_29_39 · 参照テスト: 3.1 ms (1.67 s → 1.67 s ms)SearchProducts/product_8 · 参照テスト: 1.4 ms (1.67 s → 1.67 s ms)並列枠 4TopProducts/top_30 · 参照テスト: 12 ms (1.65 s → 1.67 s ms)RevenueByCategory/Music · 参照テスト: 2.1 ms (1.67 s → 1.67 s ms)ListOrders/user_36 · 参照テスト: 0.3 ms (1.67 s → 1.67 s ms)GetOrder/orders_1_11_21_31 · 参照テスト: 2.4 ms (1.67 s → 1.67 s ms)GetOrder/orders_3_13_23_33 · 参照テスト: 1.5 ms (1.67 s → 1.67 s ms)SearchProducts/product_5 · 参照テスト: 0.9 ms (1.67 s → 1.67 s ms)SearchProducts/product_1 · 参照テスト: 0.5 ms (1.67 s → 1.67 s ms)並列枠 5TopProducts/top_20 · 参照テスト: 14 ms (1.65 s → 1.67 s ms)ListOrders/user_22 · 参照テスト: 0.5 ms (1.67 s → 1.67 s ms)GetOrder/orders_10_20_30_40 · 参照テスト: 2.9 ms (1.67 s → 1.67 s ms)GetOrder/orders_2_12_22_32 · 参照テスト: 1.9 ms (1.67 s → 1.67 s ms)並列枠 6TopProducts/top_15 · 参照テスト: 11 ms (1.65 s → 1.67 s ms)RevenueByCategory/Toys · 参照テスト: 3.4 ms (1.67 s → 1.67 s ms)ListOrders/user_29 · 参照テスト: 1.1 ms (1.67 s → 1.67 s ms)GetOrder/orders_6_16_26_36 · 参照テスト: 3.5 ms (1.67 s → 1.67 s ms)SearchProducts/product_4 · 参照テスト: 1.1 ms (1.67 s → 1.67 s ms)並列枠 7TopProducts/top_8 · 参照テスト: 13 ms (1.66 s → 1.67 s ms)ListOrders/user_64 · 参照テスト: 1.2 ms (1.67 s → 1.67 s ms)ListOrders/user_15 · 参照テスト: 1.4 ms (1.67 s → 1.67 s ms)GetOrder/orders_4_14_24_34 · 参照テスト: 2.2 ms (1.67 s → 1.67 s ms)SearchProducts/product_0 · 参照テスト: 1.0 ms (1.67 s → 1.67 s ms)SearchProducts/product_3 · 参照テスト: 2.5 ms (1.67 s → 1.68 s ms)並列枠 8TopProducts/top_5 · 参照テスト: 15 ms (1.66 s → 1.67 s ms)GetOrder/orders_8_18_28_38 · 参照テスト: 2.9 ms (1.67 s → 1.67 s ms)SearchProducts/product_9 · 参照テスト: 1.5 ms (1.67 s → 1.67 s ms)スイート開始からのミリ秒

スイートの中身、計測ハーネス、各ノードの時間はベンチマークのページで説明しています。プロジェクトは bench/modelcase にあります。

本物の PostgreSQL

PostgreSQL 18.3 を WebAssembly にコンパイルし、Go に変換したものです。SQL の解釈もプランナの挙動もエラーコードも、エミュレータではなく PostgreSQL そのものです。

インストールするものがない

ライブラリと対応するプラットフォームのバイナリを導入するだけです。Docker デーモンも、CI 上のコンテナランタイムも要りません。データベースのファイルをディスクに書きません。

読み取りは共有、書き込みは分離

マイグレーションとシードは一度だけ。読み取り専用テストではフォークを共有し、書き込みテストには専用の複製を渡します。書き込みテスト同士も並列に走らせられます。

ドライバを選ばない

PostgreSQL のワイヤプロトコルで待ち受けるので、pgx、psycopg、JDBC、node-postgres、ORM、マイグレーションツールがそのまま動きます。

s, err := pgmem.Start(ctx, pgmem.Options{Database: "app"})
if err != nil {
t.Fatal(err)
}
defer s.Close()
db, _ := sql.Open("pgx", s.DSN())

同じスキーマ、同じクエリ、同じテスト単位の分離を、同じマシンで計測しました。比較相手は公式イメージを使った docker run、Testcontainers、devbox で入れた PostgreSQL です。

pgmem の値は 2026-09-18 に 5 回計測した中央値です。Docker、Testcontainers、devbox の比較値は 2026-09-14 の基準値を引き継いでいます。Docker と Testcontainers のメモリは OrbStack を再起動して 3 回測定しました。バーは各カード内の最大値を基準にし、短いほど値が小さくなります。

起動から最初のクエリまで

起動コマンドから TCP SELECT 1 まで。取得時間は除外し、Devbox は初期化済みクラスタを使います。

  • pgmem · Go ライブラリ70 ms
  • Docker · PostgreSQL 181.65 s
  • Testcontainers · Go1.09 s
  • devbox · services up411 ms

テストごとの複製

DB を分離し、結合クエリを実行する時間の中央値。

  • pgmem · Go ライブラリ15 ms
  • Docker · PostgreSQL 1861 ms
  • Testcontainers · Go21 ms
  • devbox · services up83 ms

インデックス SELECT

ウォームアップ後に行う TCP 経由の検索。

  • pgmem · Go ライブラリ29 µs
  • Docker · PostgreSQL 1893 µs
  • Testcontainers · Go102 µs
  • devbox · services up28 µs

20万行ソート

20 万行を並べ替えて数える時間の中央値。

  • pgmem · Go ライブラリ117 ms
  • Docker · PostgreSQL 18259 ms
  • Testcontainers · Go258 ms
  • devbox · services up228 ms

DB と計測プロセスのメモリ

スキーマ準備後、クエリ前の値です。Docker と Testcontainers はコンテナ使用量(Testcontainers は PostgreSQL と Ryuk)と計測プロセスの増分を合算します。OrbStack VM の変化は別に示します。

  • pgmem · Go ライブラリ103 MiB
  • Docker · PostgreSQL 1877 MiB
  • Testcontainers · Go137 MiB
  • devbox · services up36 MiB

初回取得サイズ

同じ MB スケールですが、Go のリンク増分、圧縮イメージ、devbox の取得量で測る対象が異なります。

  • pgmem · Go ライブラリ33.1 MB
  • Docker · PostgreSQL 18117.9 MB
  • Testcontainers · Go120.0 MB
  • devbox · services up112.7 MB

現在の darwin/arm64 向け strip 済み pgmem バイナリは、エクスポートを絞った AOT バックエンドを含めて 36.7 MB です。ベンチマークページには pgmem だけを 再計測した最新値を記録し、比較対象は再現可能な基準値として残しています。

クエリ性能、計測方法、再現手順はベンチマークのページにあります。