限价订单簿
我用 C++ 写的低延迟撮合引擎:扁平数组存价位、侵入式链表、内存池分配、位图追踪最优价。它被编译成 WebAssembly,所以撮合是在你的机器上跑的,不是在我的服务器上。可以自己下单,也可以打开随机流量,看订单簿动起来。
买一价
—
卖一价
—
价差
—
挂单数
—
成交笔数
—
操作数
—
正在加载引擎…
下单
价格的最小变动单位是 0.01。
改单
减量保留排队位置;增量会被排到队尾。
深度
—中间价
累计数量:左边买盘,右边卖盘。
成交
- 还没有成交。
工作原理
扁平数组存价位
价格 tick 直接作为下标访问 Level levels_[65536]。查找或插入一个价位是 O(1),没有指针追逐,也不用分配红黑树节点,这一点和用 std::map 的写法不同。
侵入式链表 + 内存池
每个价位是一条先进先出的双向链表,节点之间用 32 位下标而不是指针相连:内存减半,对缓存也更友好。订单从预先分配好的内存池里取,用空闲链表复用,所以热路径上从不调用 malloc。
位图找最优价
每个价格 tick 对应一个 bit。某个价位清空之后,用 __builtin_ctzll / clzll 在位图上找下一个最优价,实际上通常只要看一两个 64 位字。
开放寻址的订单号表
撤单时用线性探测的哈希表查订单号,哈希函数是 splitmix64 的收尾步骤。它比 unordered_map 的链地址法快,后者每次查找至少要解引用一次指针,通常还伴随一次缓存未命中。
关于这些数字
上面的操作计数如实反映吞吐量,但这个页面刻意不展示单次操作的延迟。为了防范计时攻击,浏览器把 performance.now() 的精度限制在大约 5 µs 到 100 µs,比被测的操作粗了好几个数量级。延迟分位数只有在固定的 CPU 核上用 rdtscp 原生测量才有意义。这部分我会做成静态图表并附上测试脚本,而不是假装浏览器能测出来。