はじめに
「結局どの言語が速いの?」
Web APIを開発する際、言語選定で悩んだことはありませんか?
言語の話を切り出すと好みの言語のプレゼン大会が開催され、結局経験値の高い言語が選ばれがちです。
なんとかプレゼンに打ち勝つ方法はないか・・・
(筆者はGoが好きです)
そこで同一Docker環境・同一リソース制限のもとでよく使われがちな5つの言語のAPI性能を比較してみました。
(5言語は公平性?を求めて筆者ではなくAIに選んでもらいました)
検証環境
対象言語・フレームワーク
| 言語 | フレームワーク | バージョン |
|---|---|---|
| Node.js | Fastify | 4.x |
| Python | FastAPI | 0.100+ |
| Go | Gin | 1.9.x |
| Rust | Actix-web | 4.x |
| Java | Spring Boot | 3.x |
実行環境
- コンテナ: Docker (各言語同一条件)
- リソース制限: CPU 2コア / メモリ 2GB(全サーバー統一)
- データベース: PostgreSQL 15
- 負荷テストツール: wrk
テストシナリオ
| シナリオ | 内容 |
|---|---|
| JSON処理 | 大きなJSONオブジェクト(100件)の生成・シリアライズ |
| DB操作 | PostgreSQLへのクエリ(件数取得・平均計算) |
| ファイルI/O | ファイル読み込み処理 |
| CPU処理 | フィボナッチ数列計算(CPU集約型処理) |
| 並行処理 | 複数のDBクエリを並行実行 |
負荷テスト規模
| 規模 | 同時接続数 | 継続時間 |
|---|---|---|
| 小規模 | 10 | 10秒 |
| 中規模 | 100 | 30秒 |
| 大規模 | 1,000 | 60秒 |
検証結果
JSON処理(秒間リクエスト数)
| 規模 | Node.js | Python | Go | Rust | Java |
|---|---|---|---|---|---|
| 小 | 2,749 | 328 | 7,538 | 5,906 | 7,656 |
| 中 | 2,686 | 323 | 8,460 | 5,519 | 8,745 |
| 大 | 2,731 | 321 | 9,069 | 5,597 | 9,189 |
JSON処理ではJavaとGoが僅差でトップ。
Rustは安定した性能を発揮。Node.jsは中程度、Pythonは大きく差をつけられた。
DB操作(秒間リクエスト数)
| 規模 | Node.js | Python | Go | Rust | Java |
|---|---|---|---|---|---|
| 小 | 9,701 | 3,015 | 13,431 | 11,281 | 7,582 |
| 中 | 8,151 | 3,146 | 22,430 | 13,954 | 9,735 |
| 大 | 9,181 | 3,241 | 25,378 | 15,017 | 10,467 |
DB操作ではGoが圧倒的な性能。
pgxドライバの効率の良さが光る。
Rustも高性能。
Node.jsは健闘し、Javaを上回る結果に。
ファイルI/O(秒間リクエスト数)
| 規模 | Node.js | Python | Go | Rust | Java |
|---|---|---|---|---|---|
| 小 | 6,897 | 6,775 | 24,443 | 28,584 | 21,574 |
| 中 | 6,824 | 7,142 | 43,761 | 29,611 | 44,927 |
| 大 | 7,301 | 6,922 | 43,385 | 29,149 | 46,901 |
ファイルI/OではJava、Go、Rustがトップ争い。
規模が大きくなるとJavaが最速に。Node.jsとPythonは同程度の性能。
CPU処理(秒間リクエスト数)
| 規模 | Node.js | Python | Go | Rust | Java |
|---|---|---|---|---|---|
| 小 | 9 | 1 | 44 | 101 | 55 |
| 中 | 9 | 0 | 44 | 101 | 55 |
| 大 | 9 | 0 | 36 | 110 | 53 |
CPU集約型処理ではRustが他を圧倒。
ネイティブコンパイルの威力を見せつけた。
Java、Goも健闘。Node.jsとPythonはインタプリタ型の限界が見えた。
並行処理(秒間リクエスト数)
| 規模 | Node.js | Python | Go | Rust | Java |
|---|---|---|---|---|---|
| 小 | 3,140 | 1,652 | 6,631 | 10,113 | 3,919 |
| 中 | 3,225 | 1,678 | 7,402 | 13,954 | 4,015 |
| 大 | 2,881 | 0 | 6,985 | 11,426 | 3,951 |
並行処理ではRustがダントツ。
Goも安定した性能。
Pythonは大規模時に処理が追いつかなくなった。
総合ランキング
各シナリオの性能を総合的に評価すると:
| 順位 | 言語 | 得意分野 | 苦手分野 |
|---|---|---|---|
| 🥇 1位 | Rust | CPU処理、並行処理 | - |
| 🥈 2位 | Go | DB操作、ファイルI/O | - |
| 🥉 3位 | Java | JSON処理、ファイルI/O | 起動時間(JITウォームアップ) |
| 4位 | Node.js | DB操作(意外と健闘) | CPU処理 |
| 5位 | Python | 開発効率(性能面では厳しい) | 全般的に低速 |
シナリオ別 最速言語
| シナリオ | 1位 | 2位 | 3位 |
|---|---|---|---|
| JSON処理 | Java | Go | Rust |
| DB操作 | Go | Rust | Java |
| ファイルI/O | Java | Go | Rust |
| CPU処理 | Rust | Java | Go |
| 並行処理 | Rust | Go | Java |
各言語の特徴まとめ
Rust
- 強み: 全シナリオで安定して高性能。特にCPU処理と並行処理で圧倒的
- 弱み: 学習コストが高い、開発速度がやや遅い
- 向いている用途: 高性能が求められるシステム、リアルタイム処理
Go
- 強み: DB操作で最速。シンプルな言語仕様で高性能を実現
- 弱み: ジェネリクスの歴史が浅い
- 向いている用途: マイクロサービス、CLIツール、インフラツール
Java
- 強み: JSON処理・ファイルI/Oで最速クラス。エンタープライズ実績豊富
- 弱み: JITウォームアップが必要、メモリ消費が多め
- 向いている用途: 大規模エンタープライズシステム、バッチ処理
Node.js
- 強み: DB操作で予想以上に健闘。非同期I/Oが効率的
- 弱み: CPU集約型処理は苦手
- 向いている用途: I/O中心のWebアプリ、リアルタイム通信
Python
- 強み: 開発効率、機械学習エコシステム
- 弱み: 純粋な処理速度では他言語に劣る
- 向いている用途: プロトタイプ、データ分析、機械学習API
実装コードの一部
各言語のJSON処理エンドポイント例を紹介します。
Node.js (Fastify)
fastify.get('/api/json', async (request, reply) => {
const items = Array.from({ length: 100 }, (_, i) => ({
id: i,
name: `Item ${i}`,
price: Math.random() * 1000,
categories: ['cat1', 'cat2', 'cat3']
}));
return { timestamp: Date.now(), items };
});
Go (Gin)
r.GET("/api/json", func(c *gin.Context) {
items := make([]Item, 100)
for i := 0; i < 100; i++ {
items[i] = Item{
ID: i,
Name: fmt.Sprintf("Item %d", i),
Price: rand.Float64() * 1000,
Categories: []string{"cat1", "cat2", "cat3"},
}
}
c.JSON(200, gin.H{"timestamp": time.Now().UnixMilli(), "items": items})
})
Rust (Actix-web)
async fn json_handler() -> impl Responder {
let items: Vec<Item> = (0..100).map(|i| Item {
id: i,
name: format!("Item {}", i),
price: rand::random::<f64>() * 1000.0,
categories: vec!["cat1".into(), "cat2".into(), "cat3".into()],
}).collect();
HttpResponse::Ok().json(JsonResponse {
timestamp: Utc::now().timestamp_millis(),
items
})
}
まとめ
今回の検証で分かったことをまとめると:
- 最速を求めるなら Rust - 全シナリオで安定した高性能
- バランス重視なら Go - 高性能かつ開発効率も良好
- エンタープライズなら Java - JSON・ファイルI/Oで最速クラス
- I/O中心なら Node.js - DB操作で予想以上の性能
- 開発効率優先なら Python - 性能は劣るが開発速度は最速
ただし、これはあくまで純粋な処理速度の比較です。
結局のところ実際の開発では:
- チームのスキルセット
- エコシステムの充実度
- 保守性・可読性
- 採用のしやすさ
なども考慮する必要があります。
言語選定の際に自分の好みをプレゼンするための一助になれば幸いです!