Spine 内部ラボテスト
2026-11-01, Spine 0.5.2, GOGC=400
同じCPUとメモリの条件で、HTTPスループット、応答遅延、メモリ使用量を比較しました。Web Frameworks Benchmarkの公開測定方法を参考に、Spineプロジェクトが自ら測定した結果です。
比較結果
スループットは飽和負荷で、遅延とメモリは共通の毎秒2万リクエストで比較します。各値は、サーバーを起動し直して測定した3回の結果の中央値です。
飽和負荷、同時接続256
| 構成 | スループット (req/s) | p95 (ms) | p99 (ms) |
|---|---|---|---|
| Spine | 163,559観測範囲: 161,621–164,739 | 3.159 | 4.398 |
| NestJS / Express | 93,977観測範囲: 92,999–94,433 | 3.567 | 4.770 |
| Spring MVC | 118,943観測範囲: 117,960–121,504 | 3.119 | 3.891 |
| FastAPI / Uvicorn | 50,173観測範囲: 50,124–50,190 | 5.471 | 7.026 |
共通負荷、毎秒20,000リクエスト
| 構成 | 平均 (ms) | p95 (ms) | p99 (ms) | 観測メモリ使用量 (MiB) |
|---|---|---|---|---|
| Spine | 0.169 | 0.399 | 1.062観測範囲: 0.825–1.154 | 41.8 |
| NestJS / Express | 0.210 | 0.528 | 1.098観測範囲: 0.956–1.509 | 479.3 |
| Spring MVC | 0.199 | 0.511 | 1.115観測範囲: 1.093–1.235 | 608.8 |
| FastAPI / Uvicorn | 0.411 | 1.059 | 1.744観測範囲: 1.563–1.814 | 156.5 |
共通の毎秒2万リクエストで、Spineの平均応答時間は0.169ms、p95は0.399ms、p99は1.062msでした。
固定目標レートでの応答時間
毎秒118,000リクエストを目標に応答時間を比較しました。処理量を比較する別の飽和負荷テストでは、Spineが163,559 req/s、Spring MVCが118,943 req/sでした。
両構成とも3回の実行で記録されたリクエストはすべてHTTP 2xxで完了し、リクエストエラーとタイムアウトは0件でした。
| 構成 | p95 (ms) | p99 (ms) |
|---|---|---|
| Spine | 0.944 | 2.739 |
| Spring MVC | 60.927 | 89.248 |
完了レートと集計根拠を見る
この完了レートは固定目標負荷で記録した値で、最大処理量を示すものではありません。完了レートは、各実行の成功応答数を記録された経過時間で割った値です。経過時間は実行ごとに異なる場合があります。各列は独立したサーバー起動3回の指標ごとの中央値です。完了レートはリクエストの損失率を示す値ではありません。
| 構成 | 完了リクエスト数 (req/s) |
|---|---|
| Spine | 116,777 |
| Spring MVC | 117,305 |
両構成の完了レートの中央値となる3回目では、Spineは15.142秒で1,768,230件、Spring MVCは15.001秒で1,759,690件の成功応答を記録しました。集計時間が長いと、成功応答数が多くても毎秒の値は小さくなる場合があります。
毎秒11.8万リクエストの条件は、Spring MVCの飽和スループットに近い値です。p99の観測範囲は、Spineが2.707–2.931ms、Spring MVCが10.724–206.784msでした。Spring MVCは3回中1回で目標リクエストレートの98%に届きませんでしたが、その標本は保持しました。
年間削減額の予測
実測したCPUとメモリの使用量をvpsGODの公開プランに当てはめた予測です。以下の料金は、実際のVM性能の測定結果と区別してお読みください。
毎秒2万リクエストを基準に計算したシナリオ
vpsGODの年間前払い料金の差額で計算しました。月換算の削減額は年間の差額を12で割った値です。比較対象にも安価な公開割引プランを適用しました。
Spineは2 vCPUと256MBのメモリを備えたプランを基準に計算しました。年$25を前払いする構成です。
CPU性能と余力を仮定した予測です。このVMで処理量とp99は実測しておらず、追加の転送量と税金は除外しています。
構成と計算根拠を見る
計算に用いた仮定
コア当たりの性能を測定環境の50%と仮定し、CPU余力20%を反映しました。3回の測定で最も大きかった平均CPU使用量からコア数を計算しました。
起動とウォームアップを含む観測最大メモリの1.25倍に、軽量OS用の128MiBを加えました。ワーカー数の調整とビルド済みアプリの直接実行を想定した値で、最小RAMの実測値ではありません。
必要なCPUとRAMを満たす確認済みプランの中から、年間基本料金が最も安いものを選びました。大容量の割引プランの方が安ければ、比較対象にも適用しました。
割引プランではCPUを公平に共有する方式で割り当てます。持続的なCPU割当率は公開されていません。割引プランの地域、最終的な在庫状況と更新時の料金は確認していません。
含まれる転送量はSpineが100GB、NestJSが2TB、Spring MVCが1TB、FastAPIが4TBです。超過転送量の料金は別途かかります。表示料金で毎秒2万リクエストを1か月間継続して処理できるという意味ではありません。
CPU余力を30%に増やすと、Spring MVCも3コアが必要です。FastAPIは5コアが必要ですが、確認した公開一覧に条件を満たす単一VMがないため、その条件での料金は算出していません。
料金確認日2026-11-01。為替レートは2026-10-30の欧州中央銀行の基準値から計算した$1 = ₩1,335.27です。初回請求の割引コードは適用していません。
年間削減予測額 = (比較プランの年間料金 − Spineプランの年間料金) × 為替レート
測定環境と方法
| ホスト | ARM64、14コア(性能コア10、効率コア4)、RAM 24GB |
|---|---|
| 参考クロック | 約4.5GHzです。測定中の実際の動作クロックは記録も固定もしていません。 |
| 実行環境 | Docker Desktop、Linux/arm64、HTTP/1.1 keep-alive、loopback |
| サーバーのリソース上限 | すべての実装に3 vCPU、3GiBを割り当て、追加swapは使用していません |
| 負荷生成器 | zrk 2.4.2、別のCPUセット(CPU 9個)、メモリ1GiB |
| 処理 | 43バイトJSONの解析 → フィールド検証 → JSON応答 |
| 繰り返し | 実装ごとにサーバーを起動し直して3回測定、各測定区間は15秒、標本は計30個 |
| ウォームアップ | Spring MVCは最低135秒、その他は45秒です。直近3区間のスループットの変動係数は5%以下です |
| Spine設定 | GOGC=400、GOMAXPROCS=3、GOMEMLIMIT=2700MiB |
実行バージョン
| Spine | 0.5.2 · Echo 4.15.0 · Go 1.27.3 |
|---|---|
| NestJS / Express | NestJS 12.3.2 · Express 5.3.0 · Node.js 26.13.0 · 3 workers |
| Spring MVC | Spring Boot 4.1.2 · Java 25.0.5 · Tomcat · virtual threads |
| FastAPI / Uvicorn | FastAPI 0.162.0 · Uvicorn 0.54.0 · Python 3.15.2 · uvloop · httptools · 3 workers |
代表的な比較構成を選んだ理由
NestJS / ExpressAdapter
アダプターを省略したときの既定のExpressAdapter構成と、npmパッケージのダウンロード数を参考にしました。2026-10-01~30の@nestjs/platform-expressのダウンロード数は44,534,475回、@nestjs/platform-fastifyは7,725,701回でした。ダウンロード数はパッケージの利用規模の参考指標であり、ユーザーシェアではありません。
Spring MVC
State of Spring 2024調査で、回答者1,464人の70%がWebMVCを使用していると答えた点を参考にしました。複数回答の調査結果です。測定にはTomcatと仮想スレッドを使用しました。
FastAPI / Uvicorn
公式のfastapi runコマンドで既定のASGIサーバーとなるUvicornを選びました。ワーカー3個とuvloop、httptoolsを使用しました。
結果の読み方
- JSONは、測定に使用した共通の処理です。メモリはJSONデータだけのサイズではなく、ランタイム、プロセス、ワーカーを含むサーバーコンテナ全体の観測値です。
- 同じ試験用フィールド制約を、Spineは直接のフィールド検査、NestJSはValidationPipe/class-validator、Spring MVCはJakarta Validation、FastAPIはPydanticで確認しました。
- 固定リクエストレートの遅延は、予定送信時刻から計算し、送信待ちも含めます。飽和負荷では応答後に次のリクエストを送る別の方式を使うため、同じ負荷条件で比較してください。
- 単一ホストで15秒ずつ3回測定した結果です。DB、外部API、CORS、認証、TLS、リクエストごとのDIサービス呼び出し、長時間運用時の安定性は試験範囲に含めていません。
- メモリは、測定中に1秒間隔で取得したmemory.currentの測定区間ごとの中央値を求め、さらに3回の実行の中央値に集計しました。最低限必要なRAMやプロセスRSSを示す値ではありません。
公開データと検証
本測定の標本30個、HTTP契約の検査168件、HDRヒストグラム30個を検証しました。リクエストエラーやDocker OOMKilledの表示はありませんでした。ZIPにはアプリのソース、測定コード、元のzrk JSONとヒストグラムを収録しています。
選定基準と測定基準の出典
- Web Frameworks Benchmark
- Go garbage collector
- NestJS
- npm: Express
- npm: Fastify
- State of Spring 2024 (PDF)
- FastAPI / Uvicorn
- Uvicorn
- CPU reference clock
