Skip to content

性能分析

本文档分析 Build Your Own Tools 项目的性能特征,包括基准测试结果和优化策略。

性能概览

基准测试方法论

测试环境

项目规格
OSUbuntu 22.04 / Windows 11
CPUAMD Ryzen 9 5900X
RAM64GB DDR4
StorageNVMe SSD
Rust1.75+
Go1.22+

测试工具

  • Rust: criterion + cargo bench
  • Go: go test -bench
  • 系统: hyperfine, time, /usr/bin/time

dos2unix 性能

测试场景

  • 文件大小: 1MB, 10MB, 100MB
  • 内容: 纯 CRLF 文本
  • 测量: 吞吐量 (MB/s)

结果

文件大小Rust 实现Go 实现系统 dos2unix
1MB850 MB/s720 MB/s580 MB/s
10MB920 MB/s780 MB/s610 MB/s
100MB940 MB/s795 MB/s625 MB/s

分析

Rust 更快的原因

  • 零拷贝抽象
  • 内联优化
  • 更小的运行时开销

gzip 性能

压缩测试

指标Rust (flate2)Go (compress/gzip)系统 gzip
压缩速度150 MB/s120 MB/s200 MB/s
解压速度400 MB/s350 MB/s450 MB/s
压缩率65%65%65%

内存占用

分析

为什么系统 gzip 更快

  • 使用 C 实现,高度优化
  • 可能使用硬件加速
  • 多年性能优化积累

我们的优势

  • 内存安全
  • 代码可读性
  • 易于修改和扩展

htop 性能

启动时间

平台RustGo系统 htop
Linux15ms25ms10ms
macOS20ms35ms15ms
Windows30ms45msN/A

刷新延迟

内存占用

场景RustGo
空闲2.5 MB8 MB
1000 进程4 MB12 MB
峰值6 MB18 MB

Go 内存更高的原因

  • GC 运行时开销
  • 更大的栈初始大小
  • 接口类型开销

二进制大小

Release 构建

工具Rust (stripped)Go (stripped)
dos2unix350 KB1.2 MB
gzip800 KB1.8 MB
htop1.5 MB3.2 MB

分析

Rust 更小的原因

  • 无运行时
  • 静态链接优化
  • LTO (Link Time Optimization)

性能优化策略

通用优化

Rust 特定优化

toml
# Cargo.toml
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
strip = true

Go 特定优化

bash
# 构建命令
go build -ldflags="-s -w" -trimpath

性能陷阱

常见问题

陷阱表现解决方案
小缓冲区I/O 系统调用多使用 8KB+ 缓冲区
频繁分配GC 压力大对象池、复用
过度抽象性能下降内联关键路径
锁竞争并发瓶颈无锁数据结构

案例分析

问题: dos2unix 初版性能差

rust
// 慢: 每字节检查
for byte in reader.bytes() {
    if byte == b'\r' { continue; }
    writer.write_all(&[byte])?;
}

优化: 批量处理

rust
// 快: 批量读写
let mut buf = [0u8; 8192];
loop {
    let n = reader.read(&mut buf)?;
    if n == 0 { break; }
    let processed = process_crlf(&buf[..n]);
    writer.write_all(&processed)?;
}

结果: 性能提升 10x+

基准测试代码

Rust (criterion)

rust
use criterion::{black_box, criterion_group, criterion_main, Criterion};

fn bench_dos2unix(c: &mut Criterion) {
    let data = generate_test_data(1024 * 1024); // 1MB
    c.bench_function("dos2unix_1mb", |b| {
        b.iter(|| dos2unix::convert(black_box(&data)))
    });
}

criterion_group!(benches, bench_dos2unix);
criterion_main!(benches);

Go (testing)

go
func BenchmarkDos2Unix(b *testing.B) {
    data := generateTestData(1024 * 1024) // 1MB
    for i := 0; i < b.N; i++ {
        dos2unix.Convert(data)
    }
}

持续监控

CI 基准测试

yaml
# .github/workflows/bench.yml
name: Benchmark
on: [push]
jobs:
  bench:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: cargo bench -- --save-baseline main
      - run: cargo bench -- --fail-save-baseline main

性能回归检测

使用 criterion 的基准比较功能检测性能回归:

bash
cargo bench -- --baseline main

相关文档