微秒级延迟需全链路放弃通用性换取确定性:禁用动态内存分配、内核协议栈、原子操作强序等,采用对象池、DPDK、自定义内存序、缓存行对齐及CPU亲和性等硬实时优化。

微秒级不是靠调参压出来的,是每一层都主动放弃“通用性”换来的确定性。真实 HFT 系统里,new、std::map、epoll_wait(带超时)、clock_gettime 这类调用只要出现一次,整条路径就基本告别 1μs 了。
内存分配必须绕开 malloc 和 new
动态分配在 L3 缓存未命中 + TLB miss + 锁竞争下,单次延迟常突破 300ns;而行情线程每微秒可能要处理多个增量包,根本耗不起。
- 所有订单结构体、行情事件、价格档位对象,全部从预分配的
ObjectPool中acquire(),生命周期与 batch 对齐 -
std::vector必须传入自定义 allocator(如boost::pool_allocator),std::string改用std::string_view或固定长度char[32] - 禁用
std::shared_ptr:析构不可控,且引用计数本身是原子操作,memory_order_seq_cst下开销极大
网络收发必须跳过内核协议栈
传统 recvfrom → socket buffer → copy to user 的路径,光上下文切换+内存拷贝就吃掉 5–10μs。真实系统里,这条链路必须物理级旁路。
- 生产环境首选
DPDK或AF_XDP:报文 DMA 直达用户态 ring buffer,无中断、无拷贝、无 syscall - 若用内核协议栈,至少启用
SO_BUSY_POLL+EPOLLET+SO_RCVLOWAT,把epoll_wait超时设为0,转为轮询模式 - UDP 报文解析必须用
__builtin_expect优化分支预测,关键字段访问强制 8 字节对齐,避免跨 cache line
std::atomic 的 memory_order 选错会拖慢 4–7 倍
x86 架构下 memory_order_seq_cst 会插入 mfence,阻塞整个流水线;但多数场景根本不需要全局顺序一致性。
立即学习“C++免费学习笔记(深入)”;
- 订单簿价格档位更新(幂等):用
memory_order_relaxed即可 - 环形队列
tail推进(生产者-消费者边界):配对使用memory_order_release(写 tail)和memory_order_acquire(读 tail) - 仅当跨线程强依赖时才用
memory_order_seq_cst,例如确认订单已进入交易所匹配引擎的 final ack -
std::atomic_flag以外的类型,绝不能依赖默认构造——它隐式是seq_cst
CPU 亲和性与 cache line 对齐不是可选项
一个未对齐的 struct Order 若跨 cache line 存储,单次读取触发两次 L1d 访问;若又和隔壁线程热数据共享同一 line,就会产生 false sharing——实测使订单解析吞吐下降 40%。
- 关键结构体强制
alignas(64),字段按大小降序排列(double、int64_t、int32_t…),空缺用char pad[]填充 - 用
sched_setaffinity()将行情接收、策略计算、订单发送三类线程分别绑定到隔离物理核,启动参数加isolcpus=并禁用该核上所有 irq 和内核线程 - 禁用超线程(Hyper-Threading):逻辑核共享执行单元和缓存,争用反而抬高延迟抖动
真正难的不是知道这些点,而是敢在整条链路上同时砍掉所有“安全网”:不用异常、不用 RTTI、不查空指针、不依赖 libc 时间函数、连 printf 都得换成 lock-free ring buffer 写二进制 trace。每个妥协背后都是对确定性的绝对优先——因为市场不会等你 page fault 完再给下一档报价。


















