4、基准测试设计:基准测试场景设计、交易负载模型、测试数据生成
基准测试这事儿,说白了就是给系统「照个CT」。你得知道它到底能扛多少压力,瓶颈在哪,极限在哪。我这些年做过的撮合引擎项目,但凡跳过这一步的,最后都回来补课了。嗯,咱们今天就把这块掰开揉碎讲清楚。
4.1 基准测试场景设计
场景设计不是拍脑袋。你得先想清楚:你要测什么?
我个人习惯把场景分成三类:
- 吞吐量测试:系统每秒能处理多少笔订单?
- 延迟测试:从订单进入系统到撮合完成,花了多少微秒?
- 压力测试:在极限负载下,系统会不会崩?
举个例子。我之前做过一个期货撮合项目,客户说「我们日交易量100万笔」。我一听就知道,峰值肯定不止这个数。后来我们设计的基准场景是:峰值吞吐量按日均的5倍来压。结果呢?系统在3倍的时候就出现了锁竞争。幸亏提前测出来了。
核心原则:基准场景必须覆盖「正常负载」和「峰值负载」两个区间。峰值负载建议按正常值的3-5倍设计。
场景设计时还要考虑:
- 订单类型比例:限价单、市价单、止损单各占多少?
- 订单方向分布:买单和卖单的比例是否均衡?
- 订单规模分布:小单多还是大单多?
我曾经踩过一个坑:测试时全是小单,系统跑得飞快。上线后大单一来,直接超时。为什么?因为大单的撮合逻辑更复杂,需要遍历更多的价格档位。所以场景设计一定要覆盖各种订单规模。
4.2 交易负载模型
负载模型,就是模拟真实交易行为。你不能随便扔一堆订单进去就完事。真实市场的订单流是有规律的。
4.2.1 订单流模型
订单流模型要模拟两个维度:到达率和订单属性。
到达率模型:
- 泊松过程:适合模拟随机到达的订单流。我一般用这个做基准测试。
- 自相似过程:适合模拟有突发性的市场行为。比如开盘、收盘时的订单洪峰。
订单属性模型:
- 价格分布:围绕当前市场价格,按一定概率分布生成。
- 数量分布:通常符合幂律分布——小单多,大单少。
- 时间分布:订单的存活时间(即撤单前等待的时间)。
我的经验:别把订单到达率设成均匀的。真实市场是「一阵一阵」的。我习惯用「泊松过程 + 突发脉冲」的组合模型。先跑10秒平稳流,然后突然注入一波高峰,看看系统怎么反应。
4.2.2 市场数据模型
市场数据包括:行情快照、逐笔成交、深度变化。测试时你得模拟这些数据的生成和推送。
我个人建议:
- 行情快照:每100ms生成一次。包含买卖各20档的挂单量。
- 逐笔成交:每笔撮合完成后立即生成。
- 深度变化:订单进入或撤出时触发。
这里有个容易忽略的点:市场数据的生成速度不能比订单处理速度慢。否则你测的就是数据生成器的性能,而不是撮合引擎的性能。我曾经犯过这个错,跑了一整天测试,结果发现瓶颈在行情推送线程上。尴尬。
4.3 测试数据生成
数据生成是基准测试的基础设施。你得有一套可靠的数据生成工具。
4.3.1 订单数据生成
我常用的生成策略:
// 伪代码示例:订单生成器核心逻辑
class OrderGenerator {
// 价格围绕基准价随机波动
price = basePrice + randomGaussian(0, spread);
// 数量符合幂律分布
quantity = pow(random(), -alpha) * maxQuantity;
// 订单类型按比例分配
type = weightedRandom([
(LIMIT, 0.7),
(MARKET, 0.2),
(STOP, 0.1)
]);
// 到达时间间隔符合泊松分布
interval = -log(random()) / lambda;
}
生成的数据要满足几个条件:
- 可重复性:用固定种子,保证每次测试数据一致。
- 可调节性:能调整订单量、价格波动范围、订单类型比例。
- 真实性:价格不能乱跳,要符合市场逻辑。
注意:千万别用随机数生成器直接生成价格。我见过有人生成的价格范围从1到100000,结果撮合引擎根本找不到匹配的对手单。正确的做法是:围绕一个基准价,用正态分布生成价格波动。
4.3.2 市场数据生成
市场数据生成要和订单流联动。你不能订单都撮合完了,行情还没更新。
我习惯的做法:
- 预生成一批订单:先往订单簿里塞一些「背景订单」,模拟已有的挂单。
- 实时注入新订单:按负载模型持续注入。
- 同步生成行情:每次订单簿变化后,立即生成新的行情快照。
这里有个小技巧:预生成的背景订单数量,要占到总订单量的70%左右。为什么?因为真实市场中,大部分订单是挂在那等成交的,真正新进来的订单只占一小部分。这样测出来的结果才贴近真实。
4.4 测试数据规模与预热
数据规模怎么定?我有个简单的公式:
测试数据量 = 系统设计容量 × 测试时长(秒) × 1.5
多出来的0.5倍,是为了防止测试中途数据不够用。
另外,一定要做预热。JVM也好,内存池也好,刚启动时性能都不稳定。我一般先跑3分钟「热身」,让系统进入稳定状态,再开始记录数据。
预热建议:用测试数据量的20%做预热。预热完成后,重置统计指标,再开始正式测试。
4.5 知识体系总览
下面这张图,是我对基准测试设计的整体理解。你可以把它当作一个检查清单:
基准测试设计,说白了就是「模拟真实、覆盖极端、保证可重复」。你把这三点做到位了,测试结果就有说服力。我见过太多团队,测试数据随便生成,场景随便设计,最后测出来的数据根本不敢拿给老板看。嗯,咱们别犯这种错。
最后一个小建议:每次测试完,把测试场景、数据种子、结果都存档。这样下次优化后,可以跑同样的测试做对比。我习惯用「场景名_日期_版本号」的命名方式,方便回溯。