实测:C++ vs Go vs Rust,谁的 Web 性能更强?

“2026 年了,还有人用 C++ 写 Web 服务?” 这个问题我被问过不止一次。答案是:有,而且有相当充分的理由。本文不是要说服你用 C++,而是把三种语言放在同一个擂台上,用数据说话,帮你在实际项目里做出最合适的选择。


目录


1. 背景:三种语言在 Web 领域的 2026 年现状

C++:从游戏服务器到高性能 API

C++ 在 Web 领域长期处于"少数派"地位,但 2020 年代之后情况在变化。C++20 协程(co_await)和 PMR 内存池让 C++ 的异步 Web 编程体验大幅改善;C++26 的反射提案进一步压缩了模板样板代码。游戏公司、金融公司、CDN 基础设施商是 C++ Web 服务的主要用户群——他们要么已经有大量 C++ 代码,要么对延迟的要求超出了 GC 语言的舒适区。

本文使用 Hical(基于 Boost.Asio + picohttpparser 自研 HTTP/WebSocket 栈 + C++20 协程 + PMR 内存池)代表 C++ 阵营。

Hical v2.6.0 关键变更:该版本移除了 Boost.Beast 依赖,HTTP 解析层替换为 picohttpparser(CPU 占比从 10% 降至 0.08%),请求头零堆分配(栈上 64 条目数组 + string_view 引用连接级读缓冲区),响应序列化使用 512B 栈缓冲 + scatter-gather I/O。WebSocket 栈完全自研(RFC 6455 + permessage-deflate 压缩)。配合 SO_REUSEPORT 多 acceptor 和连接级原子时间戳超时,QPS 从 v2.5.x 的 27K 提升至 159K(+489%)。

Go:从出道即巅峰到稳健成熟

Go 是 2010 年代最成功的"实用主义"决策之一。goroutine + channel 让并发编程门槛骤降,go mod 让依赖管理摆脱了 C++ 生态的历史包袱,标准库覆盖了绝大多数 Web 服务需求。2026 年的 Go 已经非常成熟:泛型(1.18 引入)消除了大量重复代码,net/http 在 1.22 重构后路由能力大幅增强。Gin 依然是社区最常用的 Web 框架。

Rust:安全性优先,生态追赶

Rust 在 Web 领域的崛起速度超出很多人预期。Actix-web 连续多年霸占 TechEmpower 榜单前列,serde 的 JSON 序列化性能和开发体验在三个语言里公认最好。2026 年 Rust 的 async 生态已相当完善,但学习曲线(尤其是生命周期和借用检查器)仍是进入门槛。


2. 测试环境与方法论

2.1 硬件环境

项目规格
宿主机Windows 10 Enterprise LTSC 2021,Intel Core i7-11700K @ 3.60GHz(8核16线程),32GB 内存
虚拟机Oracle VirtualBox 7.1,Ubuntu 24.04.3 LTS Server,8 CPU / 16GB 内存 / 102GB SSD
DockerDocker Engine 29.4.3(VM 内原生运行,非 Docker Desktop)
部署Docker 容器化,每容器限制 4 CPU + 512MB 内存
网络Docker 内部网桥,wrk 独立容器通过网络名访问各服务

测试环境说明:本次测试从 Docker Desktop(Hyper-V 虚拟网络)迁移到 VirtualBox Linux VM + Docker Engine 原生运行。Docker Desktop 的 Hyper-V 虚拟网络层不经过完整的 Linux TCP 栈,导致 QPS 数据异常偏高;VirtualBox VM 内的 Docker Engine 使用真实的 Linux 内核网络栈,数据更接近实际生产部署环境。

VirtualBox 对 Go 运行时的已知影响:Go 1.21+ 引入的 per-P timer 机制大量调用 timer_create / timer_settime 系统调用,VirtualBox 对这些系统调用的虚拟化开销比 KVM/Hyper-V 高 5-10 倍(参见 golang/go#65073)。C++ 和 Rust 基于 epoll_wait 超时参数实现定时器,不受影响。因此本文中 Gin 的 QPS 数据受此问题影响,显著低于其在 KVM/裸机环境下的真实水平,Gin 与 C++/Rust 的绝对差距不应作为定论。

网络拓扑说明:wrk 运行在独立的 Alpine 容器中,通过 Docker 内部网桥以网络名(hical / gin / fiber / actix)访问四个框架服务。各框架的网络条件完全一致,测试公平。

2.2 框架版本

语言框架版本
C++20Hicalv2.6.0(本地源码编译,自研 HTTP/WS 栈,静态链接 Boost.Asio,GCC 14)
GoGinv1.10(Go 1.24,runtime.GOMAXPROCS(4)
GoFiberv2.52.13(Go 1.24,fasthttp 后端)
RustActix-webv4(Rust latest)

2.3 构建与运行

所有框架均通过 Docker Compose 一键构建和运行,详见 benchmark/README.md

1
2
cd benchmark
docker compose --profile cross-lang up -d --build

各框架容器内的编译配置(Dockerfile 中):

框架编译方式
Hical (C++)cmake -DCMAKE_BUILD_TYPE=Release + 静态链接 Boost
Gin (Go)CGO_ENABLED=0 go build -ldflags="-s -w"
Fiber (Go)CGO_ENABLED=0 go build -ldflags="-s -w"
Actix-web (Rust)cargo build --release

2.4 压测工具

  • 吞吐量(QPS)wrk(独立 Alpine 容器),4 threads,100 connections,持续 30 秒,记录 Avg/Max/Stdev 延迟
  • 内存docker stats --no-stream(容器级 RSS),分别采集空载和满载数据
  • 代码行数wc -l,含注释和空行

2.5 测试场景说明

重要提示:微基准(尤其是 Hello World)不能代表真实生产环境的性能表现。框架调度开销在高并发下会被数据库 I/O、业务逻辑等摊薄。本文数据仅反映框架本身的原始吞吐能力,请结合业务场景判断。

测试接口统一设计:

  • GET / — 返回固定字符串,测框架调度开销下限
  • GET /api/status — 返回 JSON 响应,测序列化路径
  • POST /api/echo — 接收 JSON Body 并返回,测反序列化+序列化完整链路
  • GET /users/42 — 路径参数路由匹配 + JSON 响应,测参数路由性能

参与框架:Hical (C++)、Gin (Go)、Fiber (Go/fasthttp)、Actix-web (Rust)。并发配置:wrk 4 threads,100 connections,持续 30 秒(单轮测试)。


3. Hello World QPS 对比

3.1 代码实现

三个框架的最简 Hello World 如下,先直观感受语言差异:

Hical (C++)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include "core/HttpServer.h"

int main()
{
    hical::HttpServer server(8080, 4);

    server.router().get("/",
        [](const hical::HttpRequest&) -> hical::HttpResponse
        {
            return hical::HttpResponse::ok("Hello, World!");
        });

    server.start();
}

Gin (Go)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package main

import (
    "net/http"
    "github.com/gin-gonic/gin"
)

func main() {
    gin.SetMode(gin.ReleaseMode)
    r := gin.New()
    r.GET("/", func(c *gin.Context) {
        c.String(http.StatusOK, "Hello, World!")
    })
    r.Run(":8081")
}

Actix-web (Rust)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
use actix_web::{web, App, HttpServer, Responder};

async fn hello() -> impl Responder {
    "Hello, World!"
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new().route("/", web::get().to(hello))
    })
    .bind("0.0.0.0:8082")?
    .workers(4)
    .run()
    .await
}

3.2 QPS 数据(实测,2026-05-12)

测试场景:GET /,返回固定字符串。wrk 4 threads,100 connections,30s。

框架QPSAvg 延迟Max 延迟Stdev
Actix-web (Rust)201,9091.67ms96.48ms3.52ms
Hical (C++)176,6291.68ms108.83ms3.80ms
Fiber (Go)95,1712.66ms123.34ms4.67ms
Gin (Go)25,7927.33ms218.27ms12.14ms

3.3 分析

Hello World 返回固定字符串,不涉及 JSON 序列化、内存池、数据库等复杂路径——测的是框架调度 + 网络 I/O 的纯开销下限

  • Actix-web 以 202K QPS 居首,Hical 177K 位居第二,Actix 领先 Hical 约 14%。两者 Avg 延迟分别为 1.67ms 和 1.68ms,Stdev 均在 3.5–3.8ms 级,同处第一梯队。
  • Fiber (Go/fasthttp) 以 95K QPS 排第三,是 Gin(26K)的 3.7 倍。同样是 Go 语言,两者差距如此之大,有力说明 net/http 是 Gin 性能瓶颈的重要因素,而非 Go 语言运行时本身。
  • Gin QPS 26K,Avg 延迟 7.33ms,Max 延迟达 218ms,延迟波动与无 GC 语言有量级差异。此次 Gin 已添加 runtime.GOMAXPROCS(4) + GODEBUG=asynctimerchan=1,相比旧测试有所改善,但 net/http 层面的开销仍显著。

4. JSON Response QPS 对比

4.1 场景设计

测试 GET /api/statusPOST /api/echoGET /users/{id} 三个场景,覆盖框架的 JSON 序列化、反序列化和路径参数路由路径。以下代码示例展示各框架的实现写法,与 benchmark 源码一致。参与框架为 Hical、Gin、Fiber、Actix-web 共四个。

实现差异说明:四个框架的 JSON 响应体大小略有不同(Hical 40 bytes / Gin 38 bytes / Actix 44 bytes),差异在 6 bytes 以内,对 QPS 影响可忽略。Actix 的 StatusResponse 使用 &'static str 静态字符串引用(零堆分配),而 Hical 和 Gin 在运行时构建 map/object——这是 Rust 语言特性的自然写法,给 serde 序列化带来额外优势。

4.2 代码实现

Hical (C++) — 使用反射宏,零手写序列化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "core/HttpServer.h"
#include "core/MetaJson.h"
#include <boost/json.hpp>

using namespace hical;
namespace json = boost::json;

struct UserDTO
{
    std::string name;
    int age{0};
    std::string email;
    HICAL_JSON(UserDTO, name, age, email)
};

// JSON 响应 — 手动构建 boost::json 对象
server.router().get("/api/status",
    [](const HttpRequest&) -> HttpResponse
    {
        json::object obj;
        obj["status"] = "running";
        obj["framework"] = "hical";
        return HttpResponse::json(json::value(std::move(obj)));
    });

// JSON Echo — 反射宏自动反序列化 + 序列化
server.router().post("/api/echo",
    [](const HttpRequest& req) -> Awaitable<HttpResponse>
    {
        auto user = req.readJson<UserDTO>();
        co_return HttpResponse::json(meta::toJson(user));
    });

Gin (Go) — 标准 json.Unmarshal 路径

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
type UserDTO struct {
    Name  string `json:"name"`
    Age   int    `json:"age"`
    Email string `json:"email"`
}

// JSON 响应
r.GET("/api/status", func(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "status":    "running",
        "framework": "gin",
    })
})

// JSON Echo
r.POST("/api/echo", func(c *gin.Context) {
    var user UserDTO
    if err := c.ShouldBindJSON(&user); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }
    c.JSON(http.StatusOK, user)
})

Actix-web (Rust) — serde,编译期生成序列化代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
use actix_web::{web, HttpResponse, Responder};
use serde::{Deserialize, Serialize};

#[derive(Serialize)]
struct StatusResponse {
    status: &'static str,
    framework: &'static str,
}

#[derive(Serialize, Deserialize)]
struct UserDTO {
    name: String,
    age: i32,
    email: String,
}

// JSON 响应
async fn status() -> impl Responder {
    HttpResponse::Ok().json(StatusResponse {
        status: "running",
        framework: "actix-web",
    })
}

// JSON Echo
async fn echo(user: web::Json<UserDTO>) -> impl Responder {
    HttpResponse::Ok().json(user.into_inner())
}

4.3 QPS 数据(实测,2026-05-12)

JSON 响应(GET /api/status

wrk 4 threads,100 connections,30s。

框架QPSAvg 延迟Max 延迟Stdev备注
Actix-web (Rust)162,0011.70ms81.65ms3.21ms领先 Hical 约 4%
Hical (C++)155,5121.65ms82.37ms3.22ms
Fiber (Go)58,9794.20ms96.98ms7.49ms
Gin (Go)26,7346.64ms141.68ms9.75ms

JSON Echo(POST /api/echo

框架QPSAvg 延迟Max 延迟Stdev
Hical (C++)158,4521.55ms75.34ms3.08ms
Actix-web (Rust)129,6731.73ms77.48ms3.18ms
Fiber (Go)56,2374.06ms98.26ms7.01ms
Gin (Go)23,2417.02ms128.29ms9.59ms

路径参数(GET /users/42

框架QPSAvg 延迟Max 延迟Stdev备注
Hical (C++)159,9131.60ms79.92ms3.05ms领先 Actix 约 36%
Actix-web (Rust)117,8802.01ms74.27ms3.66ms
Fiber (Go)46,1704.90ms162.47ms8.61ms
Gin (Go)23,2877.52ms111.98ms10.64ms

4.4 分析

JSON Echo 和路径参数场景 Hical QPS 居首,JSON 响应场景 Actix 以微弱优势领先

  • JSON 响应:Actix 162K vs Hical 156K,Actix 领先约 4%。Actix 的 StatusResponse 使用 &'static str 静态字符串引用(零堆分配)+ serde 编译期代码生成,在极简结构体序列化场景下效率最高。
  • JSON Echo:Hical 158K vs Actix 130K,领先约 22%。引入反序列化开销(堆分配 String 字段)后,boost::json 零拷贝解析的优势开始体现。
  • 路径参数:Hical 160K vs Actix 118K,领先约 36%。Hical 的静态路由哈希表(O(1) 透明查找)+ 参数路由 per-method 分组在参数提取场景下优势显著。

Fiber vs Gin:两者均使用 Go 语言,但 Fiber(fasthttp 后端)在 JSON 场景的 QPS 约为 Gin(net/http 后端)的 2.2 倍(59K vs 27K)。这与 Hello World 场景的 3.7 倍差距有所收窄,因为 JSON 序列化本身(encoding/json)是共同瓶颈,与 HTTP 底层无关。两者绝对值仍与 C++/Rust 有明显差距。

延迟稳定性:各场景下 Hical 和 Actix 的 Avg 延迟均在 1.6–2.0ms 级别,Stdev 在 3.0–3.7ms 级别,两者延迟分布接近。Fiber Avg 延迟在 4.1–4.9ms 级别,Gin 在 6.6–7.5ms 级别,Go 两框架的延迟稳定性均明显低于 C++/Rust。

为什么 Actix 在 JSON 响应场景反超 Hical,而 Echo/路径参数 Hical 领先? JSON 响应测的是纯序列化路径——Actix 的 StatusResponse 使用 &'static str 零堆分配 + serde 编译期代码生成,在极简结构体序列化场景下效率极高。而 JSON Echo 引入了反序列化开销(堆分配 String 字段),路径参数引入了路由查找开销——这两者正是 Hical 的 boost::json 零拷贝解析和 O(1) 哈希路由的优势区间,因此 Hical 在后两场景拉开差距。单轮测试结论的置信度有限,JSON 响应 4% 的差距在正常波动范围内。


5. 内存占用对比

5.1 空载内存(启动后,无请求压力)

以下数据通过 docker stats --no-stream 实测采集(每容器限制 4 CPU / 512MB)。Fiber 空载内存未采集。

框架空载内存备注
Hical (C++)5.5 MiB静态链接 Boost,无动态库映射开销
Actix-web (Rust)8.379 MiBTokio 多线程运行时初始开销
Fiber (Go)未采集
Gin (Go)19.96 MiBGo 运行时 + goroutine 调度器常驻

5.2 满载内存(100 并发连接,持续压测中)

四个服务同时被 wrk(4t100c)压测时,通过 docker stats 采样。Fiber 满载内存未采集。

框架满载内存相比空载增长
Hical (C++)5.508 MiB+0.008 MiB
Actix-web (Rust)8.398 MiB+0.019 MiB
Fiber (Go)未采集
Gin (Go)20.55 MiB+0.59 MiB

关键数据:Hical 空载内存 5.5 MiB,Actix 8.4 MiB,两者均远低于 Gin 的 20 MiB(Gin 是 Hical 的约 3.6 倍)。Hical 最低得益于静态链接 Boost + 无 GC 运行时。Actix 略高于 Hical,推测为 Tokio 多线程工作窃取线程池的初始内存。三者满载与空载内存增长均很小(Hical +0.008 MiB / Actix +0.019 MiB / Gin +0.59 MiB),本次测试为 100 并发,并发量有限,不足以区分内存管理策略的优劣。

5.3 PMR 内存策略详解

Hical 使用三层 PMR 策略,这是 C++ 在内存管理上区别于 Go/Rust 的关键设计:

1
2
3
4
5
6
7
8
┌────────────────────────────────────────┐
│  全局同步池(跨线程复用,加锁)          │  ← 大对象 / 长生命周期
├────────────────────────────────────────┤
│  线程局部非同步池(无锁,per-thread)    │  ← 中等大小对象
├────────────────────────────────────────┤
│  请求级单调缓冲区(无锁,请求粒度)      │  ← JSON 解析临时对象
└────────────────────────────────────────┘
         请求结束 → 整块归还,零碎片

设计意图:在 JSON 密集的 API 服务下,每个请求解析 Body 产生的临时 std::stringboost::json::value 等对象可从单调缓冲区分配,整个请求处理完成后一次性归还,不需要逐个 delete,也不会产生堆碎片。不过本次测试并发量较低(100 连接),三个框架的满载内存增长均很小(Hical +0.2 MiB / Actix +0.055 MiB / Gin -0.56 MiB),PMR 的优势需要在更高并发或更大 JSON Body 场景下才能充分体现。

5.4 二进制与镜像大小

框架二进制大小(实测)Docker 镜像大小(实测)基础镜像
Hical (C++)2.0 MB120 MBubuntu:24.04(静态链接)
Gin (Go)8.3 MB24.3 MBalpine:3.19(静态链接)
Actix-web (Rust)3.7 MB119 MBdebian:bookworm-slim
Fiber (Go)未采集未采集

镜像大小说明:Hical 静态链接后二进制仅 2.0 MB(旧测试动态链接为 9.2 MB),但镜像因基础镜像为 ubuntu:24.04(含系统工具)达到 120 MB。Gin 镜像最小(24.3 MB)得益于 Go 静态编译 + Alpine 基础镜像(~5 MB)。如果 Hical/Actix 改用 scratchdistroless 基础镜像,镜像可压缩至接近二进制本身大小。

5.5 GC 暂停 vs 无 GC

这是跨语言 Web 服务最常见的争议点(以下为行业常见认知,非本次实测数据):

场景Go 的影响C++/Rust 的影响
普通业务接口P99 偶尔 +1~3ms
大对象密集(如文件上传)可能触发频繁 GC手动控制释放时机
延迟 SLA < 5ms P999需要专门调优 GOGC天然满足
开发便利性完全不需要考虑内存释放需要理解所有权(Rust)或 RAII(C++)

结论:对于 P999 延迟有严格 SLA 的场景(如实时竞价、游戏状态同步),GC 暂停是实质问题;对于普通 Web API 服务,Go 的 GC 完全够用,不应成为放弃 Go 的理由。


6. 开发效率对比

6.1 代码量对比

以下数据基于 benchmark 目录下各框架压测源码的 wc -l 计数(含注释和空行),实现了相同的 4 个端点(//api/status/api/echo/users/{id})加中间件端点。

场景Hical (C++)Gin (Go)Actix-web (Rust)
完整压测代码(4 个端点 + main)149 行54 行64 行

代码行数说明:Hical 代码量较多(149 行 vs Gin 54 行)主要因为 benchmark 代码包含了多个中间件端点的演示实现,并非核心 4 端点本身的复杂度。纯 4 端点实现的代码量与 Gin/Actix 在同一量级。

6.2 编译时间

以下数据为参考估算(不做任何构建优化的基线)。

框架首次编译(参考)增量编译(改一个 .cpp)(参考)备注
Hical (C++)~45s~8sBoost 头文件模板展开耗时
Gin (Go)~3s~1sgo build 缓存友好
Actix-web (Rust)~120s~15sTokio + serde 宏展开

重要说明:C++ 模块(C++20 Modules)在 2026 年已有相当好的编译器支持(GCC 14+/Clang 20+/MSVC 2022+),配合预编译头(PCH)可以显著缩短编译时间;Rust 同样可以通过合理拆分 crate 加速增量编译。上表数据是不做任何优化的基线。

6.3 编译错误可读性

这是三个语言差异最大的维度之一:

Go 的错误信息最直接,通常一行就能定位问题:

1
./main.go:12:18: cannot use req.Name (variable of type string) as type int

Rust 的错误信息经过精心设计,带有建议(suggestions),但涉及生命周期时可能让新手困惑:

1
2
3
4
5
error[E0597]: `req` does not live long enough
  --> src/main.rs:24:18
   |
24 |     let name = &req.name;
   |                ^^^^ borrowed value does not live long enough

C++ (使用 Concepts) 的错误信息相比 C++17 已大幅改善,但模板嵌套深时仍可能出现长篇报错:

1
2
3
error: no matching function for call to 'hical::Router::get'
note: constraints not satisfied
note: 'HandlerType' must be invocable with 'const HttpRequest&'

Hical 通过 C++20 Concepts 约束 Handler 类型,错误定位到 concept 名称,而非展开整个模板实例化链——这比 C++17 时代有质的改善,但和 Go 相比仍有差距。

6.4 综合开发效率评分(主观)

维度C++ (Hical)Go (Gin)Rust (Actix)
上手难度(越低越好)中等最低最高
包管理便利性中等(vcpkg/Conan)最好(go mod)好(Cargo)
代码复杂度中等(反射宏简化)最低中等(serde 宏简化)
错误定位速度中等最快中等
重构安全性低(编译器不保证所有权)中等最高(借用检查器)
IDE 支持好(clangd)最好好(rust-analyzer)
调试便利性好(GDB/LLDB)好(dlv)中等(LLDB/GDB 稍难)

7. 生态与工具链对比

7.1 HTTP 周边生态

功能C++ (Hical/Boost)Go (标准库 + 社区)Rust (Actix 生态)
JWT 认证需要第三方库(jwt-cpp)成熟(golang-jwt)成熟(jsonwebtoken)
gRPC需要 gRPC C++一流(google/grpc-go)成熟(tonic)
OpenAPI/SwaggerHical 内置第三方(swaggo)第三方(utoipa)
数据库 ORM无原生,Hical DB 中间件GORM(一流)Diesel/SeaORM(成熟)
配置管理第三方Viper(成熟)config crate(成熟)
链路追踪需要集成 OpenTelemetry原生 SDK 完善原生 SDK 完善

直白评价:Go 的生态在 Web 服务领域是三个语言里最完整、最开箱即用的。Rust 在 2025 年之后追赶很快,主要生产需求都有答案。C++ 生态分散,Boost 解决了网络和 JSON 基础,但业务层(ORM、配置、可观测性)需要更多集成工作。

7.2 容器化与部署

三个语言在 Docker 场景下的二进制大小和镜像大小(实测数据)见第 5.4 节。


8. 各语言适用场景

经过上文的数据对比,这一节给出客观的场景建议。

8.1 选 C++ (Hical) 的场景

强推荐

  • 已有 C++ 代码库需要 HTTP API:游戏服务器、实时引擎、量化策略服务——你不可能把几十万行 C++ 逻辑重写成 Go,但可以在同进程内暴露一个 HTTP 管理接口或 RESTful API。这是 Hical 最典型的使用场景。
  • P999 延迟 SLA 极其严格:实时竞价(RTB)、HFT 场景、实时游戏状态同步——任何 GC 暂停都不可接受时,C++ 或 Rust 是唯一选项。
  • 内存资源极度受限:嵌入式设备或边缘计算节点,PMR 可以精确控制内存使用上限;静态链接后二进制仅 2 MB,空载内存 5.5 MiB。
  • 团队 C++ 技术栈成熟:如果团队全是 C++ 工程师,学习 Go/Rust 的成本反而更高。

不推荐

  • 从零启动的微服务项目,团队没有 C++ 经验。
  • 业务迭代速度是第一优先级,性能只要"够用"。

8.2 选 Go (Gin) 的场景

强推荐

  • 快速原型和 MVP:Go 的上手速度在三个语言里最快,go mod 依赖管理几乎零配置。一个新入职的工程师,一周内可以独立写出可上线的 API 服务。
  • 微服务架构:Go 的 goroutine 天然适合大量并发连接,net/http + Gin 的生态非常成熟,K8s、Prometheus、gRPC 等云原生工具的 Go 支持一流。
  • 团队技术多样性:Go 的语法和错误处理比 C++/Rust 更直观,招人、培训、Code Review 成本都低。
  • 需要快速 Debug 生产问题:Go 的 pprof + trace + dlv 工具链非常成熟,线上问题排查体验在三者中最好。

不推荐

  • GC 暂停绝对不可接受的场景。
  • 需要直接调用 C 库且对性能要求高(CGO 有额外开销)。

8.3 选 Rust (Actix-web) 的场景

强推荐

  • 安全性是硬需求:金融、医疗、安全关键系统——Rust 的借用检查器在编译期杜绝了 UAF(Use-After-Free)、数据竞争等整类漏洞,这在 C++ 里只能依赖工具链和 Code Review 保证。
  • 新项目且没有历史 C++ 包袱:如果可以从零开始,Rust 能提供和 C++ 接近的性能,同时享有更强的安全保证和更好的包管理(Cargo 明显优于 vcpkg/Conan)。
  • WebAssembly 目标:Rust 的 WASM 工具链(wasm-pack、wasm-bindgen)在三个语言里最成熟。
  • serde JSON 性能极致追求:配合 simd-json,Rust 的 JSON 吞吐可以超越三者。

不推荐

  • 团队有大量已有 C++ 代码需要集成——FFI 边界的 unsafe 管理很繁琐。
  • 开发速度是最高优先级——Rust 的学习曲线(尤其是生命周期)会显著拉长早期迭代周期。

9. 总结

性能:数据说了什么

场景第一名QPS第二名QPS第三名QPS第四名QPS
Hello WorldActix201,909Hical176,629Fiber95,171Gin25,792
JSON 响应Actix162,001Hical155,512Fiber58,979Gin26,734
JSON EchoHical158,452Actix129,673Fiber56,237Gin23,241
路径参数Hical159,913Actix117,880Fiber46,170Gin23,287

几个事实:

  1. 纯调度开销(Hello World)Actix 最强,领先 Hical 14%。Tokio 调度器在极简任务下效率极高。
  2. JSON Echo 和路径参数场景 Hical 第一,领先 Actix 22%-36%。boost::json 零拷贝解析 + O(1) 哈希路由在这些路径上有优势。JSON 响应场景 Actix 以 4% 微弱优势居首(&'static str 零堆分配 + serde 编译期代码生成)。
  3. Fiber 是理解 Go 性能天花板的关键:同为 Go 1.24,fasthttp 绕过 net/http 后 Hello World 达 95K——是 Gin 的 3.7 倍,但仍只有 Hical 的 54%、Actix 的 47%。Go 的 GC + goroutine 调度器是其性能上限的根本约束。
  4. Gin 的 26K 不能代表 Go 的真实水平。一方面 net/http 每请求 8-10 次堆分配拖了后腿(Fiber 证明了这点),另一方面 VirtualBox 对 Go timer_create 的虚拟化开销会进一步压低数据(参见第 2.1 节说明)。
  5. 延迟:Hical/Actix 平均 1.6-2.0ms,Fiber 2.7-4.9ms,Gin 6.6-7.5ms。C++/Rust 在延迟稳定性上有本质优势(无 GC 暂停、固定线程数)。

不只是性能

维度C++ (Hical)Go (Gin/Fiber)Rust (Actix)
性能天花板极高(无 GC,零拷贝,PMR)中高(GC 设上限,fasthttp 可弥补框架层)极高(无 GC,编译期优化)
开发效率中等(反射宏简化后可接受)最高(语法简洁,go mod,工具链成熟)中等(Cargo 好用,但生命周期学习曲线陡)
内存安全低(靠规范 + 工具链)中(GC 防 UAF,但无数据竞争保护)最高(编译期借用检查)
生态完整度基础完整,业务层分散最完整(云原生第一语言)完整,快速成熟中
空载内存5.5 MiB20 MiB (Gin)8.4 MiB

选型建议

没有最好的语言,只有最合适的上下文:

  • 已有 C++ 代码库,需要暴露 HTTP API → Hical。零依赖引入(同进程 Boost),JSON/路由场景性能最高,空载内存 5.5 MiB。
  • 从零起步的 Web 服务,团队混合背景 → Go + Gin。上线最快,生态最全,go mod 几乎零配置。对吞吐有要求可上 Fiber。
  • 安全性不可妥协,愿意投入学习成本 → Rust + Actix-web。Hello World 极限吞吐最高,借用检查器在编译期杜绝整类内存漏洞。
  • 极端延迟 SLA(P999 < 5ms) → C++ 或 Rust。Go 的 GC 暂停在 P999 尾部会成为问题。

数据说明:Gin v1.10 / Go 1.24(runtime.GOMAXPROCS(4) + GODEBUG=asynctimerchan=1),Fiber v2.52.13 / Go 1.24,Actix-web v4 / Rust latest,Hical v2.6.0 / GCC 14。测试日期:2026-05-12。VirtualBox 对 Go 运行时 timer_create 的虚拟化影响参见第 2.1 节说明。


10. 复现指南

所有测试代码、Docker 配置和压测脚本均已公开,详见仓库 benchmark/README.md,包含完整的构建、启动、压测、采集和清理流程。

1
2
3
git clone https://github.com/hical61/hical.git
cd hical/benchmark
# 后续步骤参照 benchmark/README.md

反馈:如果你发现数据有明显偏差,或者有更好的测试方案,欢迎在评论区指出,本文保持持续更新。


Hical — 基于 C++20/26 的现代高性能 Web 框架

如果觉得有帮助,请点赞收藏,你的支持是最大的动力!

项目地址:GitHub - hical