撮合引擎压力测试指南

版本: v0.2.0 更新日期: 2025-12-17 开发团队: @yutiansut @quantaxis


📋 目录

  1. 测试概述
  2. 多标的压力测试
  3. 多用户多账户测试
  4. 吞吐量压力测试
  5. 延迟基准测试
  6. 并发安全测试
  7. 极端场景测试
  8. 测试执行指南
  9. 问题排查

测试概述

压力测试目标

测试维度目标验证方法
多标的支持100+合约并发多线程多合约撮合
多用户支持10,000+用户大规模订单提交
吞吐量> 100,000 orders/sec高频下单测试
延迟P99 < 100μs延迟统计分析
并发无数据竞争多线程读写测试
稳定性长时间无崩溃极端场景测试

测试分类

压力测试 (19个)
├── 9. 多标的并发撮合 (3个)
│   ├── test_multi_instrument_concurrent_orders
│   ├── test_multi_instrument_parallel_matching
│   └── test_multi_instrument_isolation
├── 10. 多用户多账户 (3个)
│   ├── test_large_scale_users
│   ├── test_multi_account_order_distribution
│   └── test_cross_account_matching
├── 11. 吞吐量压力 (3个)
│   ├── test_throughput_single_instrument
│   ├── test_throughput_batch_matching
│   └── test_deep_orderbook
├── 12. 延迟基准 (3个)
│   ├── test_latency_single_order
│   ├── test_latency_matching
│   └── test_latency_deep_matching
├── 13. 并发安全 (3个)
│   ├── test_concurrent_read_write
│   ├── test_high_concurrency_orders
│   └── test_concurrent_cancel
└── 14. 极端场景 (4个)
    ├── test_extreme_price_range
    ├── test_orderbook_rebuild_after_mass_cancel
    ├── test_mixed_workload_stress
    └── test_massive_order_submission

多标的压力测试

9.1 多标的同时下单

测试函数: test_multi_instrument_concurrent_orders

场景描述:

注册: 10个合约 (TEST0000 ~ TEST0009)
每合约:
  - 100个买单 (价格990~891)
  - 100个卖单 (价格1010~1109)
总订单: 2,000个

验证点:

  • 所有合约正确注册
  • 订单正确分配到各合约
  • 无跨合约数据污染

运行命令:

cargo test test_multi_instrument_concurrent_orders --lib -- --nocapture

9.2 多标的并发撮合

测试函数: test_multi_instrument_parallel_matching

场景描述:

合约数: 5个 (PARA0000 ~ PARA0004)
线程数: 5个 (每合约1个线程)
每线程:
  - 50对买卖单
  - 每对先挂卖单再买单成交
预期成交: 250笔 (5 × 50)

架构图:

Thread-0 ──┬──> Orderbook(PARA0000) ──> 50 trades
Thread-1 ──┼──> Orderbook(PARA0001) ──> 50 trades
Thread-2 ──┼──> Orderbook(PARA0002) ──> 50 trades
Thread-3 ──┼──> Orderbook(PARA0003) ──> 50 trades
Thread-4 ──┴──> Orderbook(PARA0004) ──> 50 trades
                                       ─────────
                                       250 trades

验证点:

  • 所有线程完成无panic
  • 成交数 = 250
  • DashMap + RwLock 并发安全

9.3 多标的隔离性验证

测试函数: test_multi_instrument_isolation

场景描述:

合约A: 挂买单 @1000 × 100
合约B: 挂卖单 @1000 × 100

验证: 合约B的卖单不应与合约A的买单成交

验证点:

  • 合约A买单状态: Accepted
  • 合约B卖单状态: Accepted (而非Filled)
  • 无跨合约撮合

多用户多账户测试

10.1 大量用户模拟

测试函数: test_large_scale_users

场景描述:

用户数: 1,000
订单分布:
  - 用户0-499: 买单 (价格900-949)
  - 用户500-999: 卖单 (价格1051-1100)
触发撮合: 大买单 @1200 × 500

验证点:

  • 1,000个订单全部接受
  • 大买单与500+卖单成交
  • 系统稳定无崩溃

10.2 多账户订单均衡

测试函数: test_multi_account_order_distribution

场景描述:

账户数: 100
每账户订单: 10
总订单: 1,000
订单类型: 交替买卖 (不成交)

验证点:

  • 接受订单数 = 1,000
  • 买卖订单均匀分布

10.3 账户间成交验证

测试函数: test_cross_account_matching

场景描述:

卖方账户: 50个,每户卖单 @1000 × 10
买方账户: 50个,每户买单 @1000 × 10

验证点:

  • 跨账户正常成交
  • 成交数 >= 50

吞吐量压力测试

11.1 单合约高频下单

测试函数: test_throughput_single_instrument

测试参数:

#![allow(unused)]
fn main() {
let order_count = 10_000;
// 买卖交替,价格不交叉,不触发撮合
}

性能指标: | 指标 | 目标 | 实际 | |------|------|------| | 吞吐量 | > 100K/s | ~300K/s | | 总耗时 | < 100ms | ~33ms |

运行命令:

cargo test test_throughput_single_instrument --lib --release -- --nocapture

11.2 批量撮合性能

测试函数: test_throughput_batch_matching

测试参数:

#![allow(unused)]
fn main() {
// 预挂5,000卖单
// 大买单一次消耗所有
let aggressive_buy = orders::new_limit_order_request(
    asset, OrderDirection::BUY, 1200.0, 5000.0, ts + 10000,
);
}

性能指标: | 指标 | 目标 | 实际 | |------|------|------| | 撮合速率 | > 100K/s | ~800K/s | | 单次撮合 | < 10μs | ~1.25μs |

11.3 深度订单簿压力

测试函数: test_deep_orderbook

测试参数:

#![allow(unused)]
fn main() {
let depth = 10_000; // 每边10,000档
}

性能指标: | 指标 | 实际 | |------|------| | 构建耗时 | ~150ms | | 每档耗时 | ~7.5μs |


延迟基准测试

12.1 单订单延迟

测试函数: test_latency_single_order

测试方法:

#![allow(unused)]
fn main() {
let sample_count = 1000;
for i in 0..sample_count {
    let start = Instant::now();
    ob.process_order(order);
    latencies.push(start.elapsed().as_nanos());
}
}

结果统计:

P50: 3.09 μs
P99: 6.11 μs
Avg: 3.28 μs

12.2 撮合延迟

测试函数: test_latency_matching

测试方法:

#![allow(unused)]
fn main() {
// 每次先挂卖单,再测量买单撮合延迟
for i in 0..500 {
    ob.process_order(sell);  // 挂卖单
    let start = Instant::now();
    ob.process_order(buy);   // 撮合
    latencies.push(start.elapsed().as_nanos());
}
}

结果统计:

P50: 2.22 μs
P99: 2.40 μs
Avg: 2.29 μs

12.3 深度撮合延迟

测试函数: test_latency_deep_matching

测试方法:

  • 构建100档卖盘
  • 大买单吃掉所有
  • 重复10轮取平均

结果统计:

平均: 190.74 μs
最大: 233.66 μs

并发安全测试

13.1 多线程并发读写

测试函数: test_concurrent_read_write

线程分配:

写线程 × 4: 每线程提交100订单
读线程 × 4: 每线程读取100次lastprice

验证点:

  • 所有线程无panic
  • 无数据竞争
  • 数据一致性

13.2 高并发下单

测试函数: test_high_concurrency_orders

参数:

#![allow(unused)]
fn main() {
let thread_count = 8;
let orders_per_thread = 500;
// 奇数线程买,偶数线程卖
// 统一价格可能触发成交
}

验证点:

  • 总订单数正确处理
  • 统计数据一致

13.3 并发撤单

测试函数: test_concurrent_cancel

流程:

1. 挂入400个买单
2. 收集所有order_id
3. 分成4组,4线程并发撤单
4. 验证撤单成功数 >= 350

验证点:

  • 无重复撤单
  • 无漏撤
  • 线程安全

极端场景测试

14.1 价格极端波动

测试函数: test_extreme_price_range

测试范围:

#![allow(unused)]
fn main() {
// 极低价格
let low_price = 0.001;

// 极高价格
let high_price = 9_999_999.99;
}

验证点:

  • 数值精度正确
  • 无溢出
  • 订单正常接受

14.2 大量撤单后重建

测试函数: test_orderbook_rebuild_after_mass_cancel

流程:

第一轮:
  1. 挂入500个买单
  2. 全部撤单

第二轮:
  1. 重新挂入500个买单
  2. 验证全部接受

验证点:

  • 内存正确释放
  • 订单ID继续递增
  • 队列状态正确

14.3 混合工作负载

测试函数: test_mixed_workload_stress

线程分配:

下单线程 × 2: 300订单/线程 (买卖交替,价差1)
撮合线程 × 2: 200订单/线程 (统一价格)

模拟场景: 真实交易环境

14.4 超大批量提交

测试函数: test_massive_order_submission

参数:

#![allow(unused)]
fn main() {
let order_count = 50_000;
}

验证点:

  • 100%接受率
  • 系统稳定
  • 内存可控

测试执行指南

运行全部压力测试

# Debug模式 (带符号信息)
cargo test matching::engine::tests --lib

# Release模式 (性能测试)
cargo test matching::engine::tests --lib --release

# 显示输出
cargo test matching::engine::tests --lib --release -- --nocapture

运行特定类别测试

# 多标的测试
cargo test test_multi_instrument --lib --release -- --nocapture

# 吞吐量测试
cargo test test_throughput --lib --release -- --nocapture

# 延迟测试
cargo test test_latency --lib --release -- --nocapture

# 并发测试
cargo test test_concurrent --lib --release -- --nocapture

# 极端场景
cargo test test_extreme --lib --release -- --nocapture
cargo test test_massive --lib --release -- --nocapture

性能分析

# CPU profiling (Linux)
perf record cargo test test_throughput --release -- --nocapture
perf report

# 火焰图
cargo install flamegraph
cargo flamegraph --test test_throughput

# 内存分析
valgrind --tool=massif cargo test test_massive --release

问题排查

常见问题

1. 测试超时

症状: 测试运行时间过长

排查:

# 检查是否有死锁
RUST_BACKTRACE=1 cargo test test_name --lib -- --nocapture

解决: 检查锁顺序,避免循环等待

2. 内存溢出

症状: OOM 错误

排查:

# 限制内存
ulimit -v 4000000  # 4GB
cargo test test_massive --release

解决: 减少测试规模或优化内存使用

3. 并发测试失败

症状: 断言失败,数据不一致

排查:

# 多次运行查看是否稳定
for i in {1..10}; do
  cargo test test_concurrent --release
done

解决: 检查原子操作和锁使用

调试技巧

#![allow(unused)]
fn main() {
// 添加调试输出
println!("[DEBUG] order_id={}, price={}, volume={}", id, price, volume);

// 使用 env_logger
RUST_LOG=debug cargo test test_name -- --nocapture

// 条件断点
if order_id == 12345 {
    panic!("Debug point reached");
}
}

压力测试检查清单

发布前检查

  • 所有76个测试通过
  • 吞吐量 > 100K orders/sec
  • 延迟 P99 < 100μs
  • 并发测试无数据竞争
  • 50K订单测试100%接受率
  • 内存使用稳定
  • 无panic或崩溃

CI/CD 集成

# .github/workflows/test.yml
jobs:
  stress-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Run stress tests
        run: |
          cargo test matching::engine::tests --lib --release
        timeout-minutes: 10

相关文档