为实时音视频处理构建高性能、零碎片的处理流水线


1. 高频数据系统中的性能瓶颈分析

在设计用于处理高频数据流(例如每10毫秒产生一个数据包)的实时音视频系统时,传统的内存管理和并发控制方法往往会成为性能瓶颈。这些问题并非孤立存在,而是系统设计与实时处理需求及现代硬件特性不匹配所共同导致的系统性症状。

1.1. 内存碎片的根源及其系统性影响

内存碎片是动态内存管理中一个长期存在的问题,其定义为:尽管总可用内存足以满足分配请求,但由于可用空间被分割成不连续的小块,导致无法找到一个足够大的连续内存块。在所描述的音视频场景中,系统以100 Hz的频率循环执行内存的申请与释放。每一次调用标准分配器(如malloc 或 new)来存储数据包,处理完毕后又调用 free 或 delete 释放。这个过程会在堆内存中留下许多无法再利用的微小“空洞”。随着时间推移,堆的状态会变得像一块高度碎片化的磁盘,最终导致即使总空闲内存充足,也无法为新的数据包分配出连续的空间,从而引发分配失败。

这种状况对实时系统会带来一系列严重的系统性后果:

  • 非确定性延迟(抖动):标准内存分配函数本质上是非确定性的。它们的执行时间不可预测,这与实时系统的核心要求背道而驰。随着碎片化加剧,分配器为了寻找合适的内存块需要遍历更复杂的空闲链表,导致分配耗时增加且波动剧烈。
  • 性能下降:内存管理器为了满足分配请求而进行的搜索工作变得越来越繁重,直接导致整个系统的运行速度减慢。
  • 灾难性故障:最严重的情况下,内存分配请求会彻底失败。这在音视频流处理等应用中是不可接受的,它将直接导致系统不稳定甚至崩溃。

1.2. 并发瓶颈:为何传统锁机制在低延迟场景下失效

锁(例如互斥锁)是保证多线程数据安全访问的传统机制,但其开销在高频交易和实时系统中是极其昂贵的。当多个线程竞争同一个锁时,需要操作系统内核进行仲裁,这通常会导致代价高昂的上下文切换。上下文切换不仅会暂停等待的线程,更会污染CPU缓存,使得先前“预热”的数据和指令失效,当线程恢复执行时必须从主内存重新加载,从而产生显著的性能损失。

在“一个生产者,多个消费者”模型中,保护共享数据结构的单一锁会成为一个剧烈的争用点。生产者和所有消费者都必须串行访问该数据结构,这完全抵消了并行处理带来的优势。LMAX的性能测试数据惊人地揭示了这一问题:一个在单线程上仅需300毫秒的简单计数器递增操作,在引入无竞争的锁后耗时增至10,000毫秒;而当两个线程竞争该锁时,耗时更是飙升至224,000毫秒——性能下降了近千倍。这个数据雄辩地证明了,对于要求低延迟和高吞吐的系统,基于锁的并发模型是完全不合适的。

更深层次的分析表明,内存碎片和锁争用并非两个独立的问题,它们会相互作用,形成一个性能恶化的恶性循环。首先,高频的数据包处理需求导致频繁调用 malloc,引发内存碎片。接着,碎片化使得 malloc 的执行时间变得更长且不可预测。由于生产者在分配内存期间需要持有数据结构的锁,malloc 的耗时增加意味着锁的持有时间也相应延长。更长的锁持有时间极大地增加了多个消费者线程发生争用的概率和等待时间,导致它们频繁停顿。这种相互加强的破坏性效应,使得系统整体性能急剧下降,并产生严重的延迟抖动。

因此,当前系统面临的根本问题并非简单的代码实现缺陷,而是一种架构层面的错配。标准库函数如 malloc 和互斥锁是为通用计算场景设计的,其首要目标是保证正确性和易用性,而非满足高频、低延迟系统的极端性能需求。实时系统要求的是可预测性和最小化的开销。因此,解决方案不能局限于“优化”现有工具的使用,而必须从根本上替换它们,采用专为该问题领域设计的架构模式。


2. 基础解决方案之一:确定性内存管理模型

解决性能瓶颈的第一步是构建一个确定性的内存管理模型,用专门为高性能场景设计的策略取代通用的堆分配器,从而根除内存碎片并提供可预测的性能。

2.1. 定长块分配与内存池原理

解决外部碎片的根本方法是在系统初始化时,一次性地从操作系统申请一块大的连续内存区域(即“内存池”),然后将其预先分割成一系列大小固定的内存块。当应用程序需要内存来存储数据包时,它不再调用malloc,而是向内存池管理器请求一个块。这个操作非常快速,通常只是从一个空闲块链表中取出一个指针。当数据包处理完毕,该内存块被归还到池的空闲链表中,而不是返还给操作系统,以备后续重用。

这种模式带来了两大核心优势:

  • 根除外部碎片:由于所有内存块大小相同,释放后不会产生无法利用的“空洞”。任何一个被归还的块都可以完美地满足未来的任何一次分配请求。
  • 确定性性能:内存的分配和释放都变成了时间复杂度为 O ( 1 ) O(1) O(1)的操作,本质上只是简单的指针移动,彻底消除了 malloc 中因搜索空闲块而带来的不可预测的延迟 5。这对于满足实时系统的严格时间限制至关重要。

2.2. 高级实现:用于零开销对象回收的Slab分配器

Slab分配器是内存池概念的进一步演化,在Linux和Solaris等操作系统内核中得到了广泛应用 16。它将内存池组织成特定对象的“缓存(caches)”,每个缓存由多个“板(slabs)”组成。其核心创新在于对象缓存机制:它能在对象的多次使用之间保持其已初始化的状态。一个对象仅在其所属的slab首次被创建时构造一次。当对象被“释放”时,它并不会被析构,而是被原封不动地归还到slab的空闲链表中,可以被立即重新分配和使用。

这一机制极大地降低了系统开销。对于许多复杂的对象而言,构造和析构的成本(例如初始化内部锁、条件变量或复杂数据结构)远高于单纯分配内存的成本。通过缓存已构造的对象,Slab分配器将这部分高昂的开销从应用程序的关键执行路径中移除。

2.3. 硬件感知优化:CPU缓存着色的角色

为了进一步提升性能,Slab分配器引入了“缓存着色(Cache Coloring)”技术。该技术通过在不同slab中为对象分配不同的起始偏移量,确保来自不同slab的对象能够映射到不同的CPU缓存行(Cache Line)。这有效减少了来自同一个对象缓存的对象在CPU的L1或L2缓存中相互驱逐的概率,从而提高了缓存的整体命中率和系统性能。这是“机械共鸣”(Mechanical Sympathy)思想的初步体现,即软件设计应与底层硬件的工作方式相协调。

采用内存池或Slab分配器不仅仅是一项内存优化,它更是实现高性能、无锁并发模型的关键基石。一个无锁算法的性能高度依赖于其关键代码段内操作的极致速度和可预测性。如果一个无锁算法在执行过程中需要调用非确定性的 malloc 来为新数据包获取内存,那么“无锁”所带来的性能优势将被内存分配器不可预测的延迟所完全抵消。内存池提供了确定性的内存分配,确保了生产者逻辑中的内存获取步骤始终是快速且一致的。因此,一个确定性的内存模型是构建真正确定性、高性能并发数据交换机制的先决条件。

此外,这种预分配策略也引发了开发范式的转变。它将问题从“运行时不可预测性”转移到了“设计时分析”。使用 malloc 是一种被动的、反应式的内存管理方式,导致了运行时的不确定性。而内存池则要求开发者在设计阶段就必须主动分析并确定系统的内存需求,例如峰值负载下可能存在的“在途”数据包的最大数量。这迫使开发者对系统的分配模式和大小进行“直方图分析”,从而更深刻地理解数据流和系统容量。尽管这需要更多的前期设计工作,但其回报是巨大的:它用一个可解的设计时问题(系统容量规划)替换了一个棘手的、甚至无法在运行时解决的问题(碎片化和抖动),最终构建出更健壮、更可预测的系统。


3. 基础解决方案之二:高吞吐并发数据交换模型

在解决了内存管理问题之后,第二项核心挑战是设计一个能够高效地将数据从单一生产者广播到多个消费者的数据交换机制。这需要我们摆脱传统的基于队列的思维定式,转向一种更符合现代硬件特性的新范式。

3.1. 单生产者、多消费者(SPMC)广播挑战

系统的核心并发需求是:将由单一生产者线程生成的单个数据包,高效地广播给所有消费者线程,以供它们并行处理。若采用传统方法,例如使用一个受锁保护的队列,会立即遇到根本性难题。队列的语义是“单一所有权”,一旦某个消费者取走一个元素,该元素便从队列中消失了。为了实现广播,生产者将被迫为每个消费者维护一个独立的队列,并将同一份数据(或其指针)入队N次,这会造成巨大的数据复制开销和管理复杂性。

3.2. LMAX Disruptor简介:从队列到环形缓冲区的范式转变

LMAX Disruptor是一个为应对高频交易中极端低延迟需求而生的高性能线程间消息传递框架。它被明确设计用来取代那些在高负载下会成为性能瓶颈的传统队列架构。

Disruptor的核心数据结构是一个环形缓冲区(Ring Buffer),也称循环队列。这是一个固定大小的数组,其索引在到达末尾后会“环绕”回起点,为处理连续的数据流提供了天然的结构支持。

Disruptor的革命性思想在于关注点分离。传统队列将数据存储与并发协调(如管理头、尾指针)两个关注点混杂在一起。Disruptor则将它们彻底解耦:

  • 环形缓冲区:纯粹用于数据存储。
  • 序号(Sequence Numbers):专门用于并发协调。

这种设计带来了惊人的性能提升。测试表明,与基于队列的等效实现相比,Disruptor的平均延迟降低了三个数量级,而吞吐量则提升了约八倍 9。

将Disruptor简单地视为“一个更快的队列”会严重低估其架构上的重要性。它代表了一种从“拉(pull)”模型到“推/广播(push/broadcast)”模型的根本性转变。在传统队列中,消费者的核心操作是 dequeue,这是一种破坏性读取,元素被永久地从队列中移除。而在Disruptor中,生产者的操作是publish,消费者的操作是 get。消费者通过一个序号来获取环形缓冲区中特定位置上事件的引用,数据本身保留在缓冲区中,可供其他消费者继续读取。这意味着该数据结构在概念上不再是传统计算机科学意义上的队列,而更像一个可供多个游标(消费者)并发读取的、循环写入的事件日志。正是这种概念上的转变,使得真正意义上的零拷贝广播成为可能。其性能优势并非源于让enqueue/dequeue 操作更快,而是从根本上用非破坏性的读取取代了 dequeue 操作。

此外,当前场景的SPMC模型恰好是Disruptor性能表现最佳的理想用例。Disruptor的设计充分利用了“单一写入者原则”来消除写争用。研究表明,不同线程对共享数据的写入是导致性能下降的主要原因,它会引发缓存行在不同CPU核心间“乒乓”的现象。在SPMC模型中,永远只有一个线程——即生产者线程——在向环形缓冲区的数据槽写入数据并更新主游标。由于写入者唯一,因此不存在写争用。这意味着生产者在声明和发布序号时,无需使用昂贵的锁,甚至连原子性的CAS(比较并交换)操作都可以省略,仅依靠内存屏障来确保数据对消费者的可见性。这使得生产者的执行路径极为快速和高效。而所有的消费者都只是数据的读取者,它们之间以及与生产者之间都不会发生写争用。该架构与当前应用场景完美契合,使其能够发挥出Disruptor最强大的性能潜力。


4. 整合架构:深入解析Disruptor模式

本节将整合前两节的概念,详细阐述LMAX Disruptor如何通过一个统一而优雅的架构,同时解决内存管理和并发通信两大核心挑战。

4.1. 环形缓冲区:数据结构与内存池的统一

Disruptor的环形缓冲区不仅是一个空数组,它在启动时就通过用户提供的 EventFactory 预先填充了事件对象。这意味着在应用程序的整个生命周期中,关键路径上不存在任何动态内存分配。生产者只是从环形缓冲区中获取一个预先分配好的事件对象的“槽”,填入数据,然后发布。随着环形缓冲区的指针循环,这些事件对象被不断重用。

这种设计直接实现了第二节中讨论的内存池模型,从而彻底消除了内存碎片及其带来的性能惩罚。可以说,Disruptor本身就是一个高性能的内存池。

4.2. 机械共鸣:为现代CPU架构而设计

“机械共鸣”(Mechanical Sympathy)是指软件设计应与底层硬件(特别是CPU及其缓存系统)的工作方式保持一致,以最大化性能。Disruptor是这一理念的典范。

  • 缓存友好的数据结构:环形缓冲区作为一个连续的数组,天然对CPU缓存友好。当消费者按顺序处理事件时,CPU的预取器(Prefetcher)可以高效地将后续事件提前加载到缓存中,避免了访问主内存所带来的高昂延迟。这与那些需要进行指针追逐的数据结构(如链表)形成了鲜明对比。
  • 2的幂次大小:Disruptor要求环形缓冲区的大小必须是2的幂。这并非随意规定,而是为了一个关键的性能优化:它允许通过一次快速的位运算 &(sequence & (bufferSize - 1))来完成序号到数组索引的映射,取代了效率低得多的模运算 %。

为了更清晰地展示Disruptor的架构优势,下表将其与传统队列实现进行了对比。

表1:传统队列与Disruptor环形缓冲区的架构对比分析

特性传统锁队列 (如 ArrayBlockingQueue)基于CAS的无锁队列LMAX Disruptor (SPMC)
并发控制整个结构的单一锁头/尾指针的原子性CAS操作序号与内存屏障
争用点高 (生产者 vs 消费者, 消费者 vs 消费者)中 (头/尾指针的CAS争用)无 (单一写入者)
内存分配可能按项分配按节点分配 (链式队列)零分配 (预分配池)
碎片风险高 (若不使用池)高 (若不使用池)无
CPU缓存友好性差 (锁争用导致缓存失效)中到差 (ABA问题, 指针追逐)极佳 (连续数组, 单一写入者)
广播模型非原生 (需N个队列)非原生 (需N个队列)原生,零拷贝

4.3. 无锁协调:序号与内存屏障

Disruptor通过精巧的序号系统和内存屏障实现无锁协调。

  • 生产者路径(声明与发布):
    1. 生产者调用 ringBuffer.next() 请求下一个可用序号。
    2. 通过 ringBuffer.get(sequence) 获取该序号对应的预分配事件对象。
    3. 将数据写入事件对象。
    4. 调用 ringBuffer.publish(sequence)。此操作会更新一个称为“游标(cursor)”的特殊序号,并通过内存屏障确保所有对事件对象的修改对消费者立即可见。
  • 消费者路径(等待与读取):
    1. 每个消费者独立维护一个序号,记录其已处理的最后一个事件。
    2. 消费者等待生产者的游标前进,直到超过自己当前的序号。
    3. 一旦游标足够靠前,消费者便知道目标数据已准备就绪,可以直接从环形缓冲区中安全地读取。
    4. 处理完毕后,消费者更新自己的序号。
  • 门控(Gating):为防止生产者速度过快而覆盖掉尚未被最慢消费者处理的事件,生产者在声明下一个序号之前,会检查所有消费者的序号。只有当目标槽位已被所有消费者“消费”过后,生产者才能写入。这形成了一种隐式的、无锁的背压机制。

4.4. 实现广播:多消费者的独立进度跟踪

Disruptor实现真正广播的关键在于,每个消费者都拥有一个独立的 Sequence 对象。生产者只需通过更新主游标发布一次事件,所有消费者都能看到这一更新。消费者A可能正在处理第100号事件,而消费者B可能还在处理第95号事件,它们互不干扰,以各自的步调读取同一个环形缓冲区。此外,Disruptor还支持构建复杂的依赖图,例如让消费者B等待消费者A处理完某个事件后再开始处理,这只需让B同时等待A的序号和生产者的游标即可。

4.5. 消除抖动:等待策略的比较分析

消费者在等待新事件时需要采用一种等待策略,这直接关系到CPU消耗和延迟之间的权衡。

  • BlockingWaitStrategy:使用锁和条件变量。CPU占用最低,但延迟和抖动最大,不适用于本场景。
  • SleepingWaitStrategy:一种折中策略。它会短暂地自旋,然后调用 LockSupport.parkNanos(1) 让出CPU。适用于异步日志等非核心任务。
  • YieldingWaitStrategy:一种高性能策略。它在循环中忙等待,并调用 Thread.yield() 允许其他线程运行。当消费者线程数少于逻辑核心数时,推荐使用此策略。
  • BusySpinWaitStrategy:性能最高、延迟最低的策略。它会持续地忙等待,不让出CPU,将一个CPU核心的占用率推至100%。该策略仅适用于可以将线程绑定到专用物理核心且对延迟要求极为苛刻的场景。对于实时音视频系统,这通常是关键消费者线程的正确选择。

5. 实施蓝图与战略建议

本节提供可操作的实施指南,重点介绍对于实现巅峰性能至关重要的先进优化技术。

5.1. 数据事件设计:利用缓存行填充规避伪共享

“伪共享(False Sharing)”是并发编程中一个隐蔽的性能杀手。它发生在两个或多个被不同线程访问的独立变量,恰好位于同一个CPU缓存行(通常为64字节)上时。当一个线程修改其中一个变量时,会导致整个缓存行在其他CPU核心中失效,迫使其他核心从更慢的L3缓存或主内存中重新加载数据,即使它们访问的是逻辑上完全无关的变量。

在Disruptor中,由生产者和每个消费者维护的序号是伪共享的主要风险点,因为它们被不同线程频繁更新。Disruptor的实现通过在关键序号变量周围添加填充(Padding)(例如,7个未使用的 long 类型变量)来解决此问题,确保每个序号都独占一个缓存行。在设计应用自身的事件对象时,必须遵循同样的原则:如果不同的消费者线程需要将处理结果写回到同一个事件对象的不同字段中,那么这些字段之间也需要进行缓存行填充,以避免伪共享。

5.2. 环形缓冲区大小设定:平衡突发处理能力与缓存占用

一个常见的误区是认为环形缓冲区越大越好。实际上,过大的缓冲区会对CPU缓存利用率产生负面影响,因为它占用了更多的L3缓存空间,挤占了其他数据和指令的缓存位置。

正确的设定原则是:缓冲区的大小应足以应对生产者可预见的数据突发。它需要足够大,以在消费者处理积压数据时吸收临时的生产高峰,但又不应超出必要范围。同时,必须再次强调,其大小必须是2的幂,以实现高效的索引计算。一个合理的初始大小可能是1024或4096,但最佳值应通过对特定应用负载进行性能剖析来确定。

5.3. 线程策略:CPU亲和性(绑定)的重要性

CPU亲和性(或称线程绑定)是指将一个特定线程强制绑定到某个特定的CPU核心上执行的做法。对于追求极致低延迟的系统,这是至关重要的一步。在通用操作系统中,调度器可能会在不同核心之间迁移线程。一旦线程被迁移,它在原核心L1/L2缓存中的“热”数据就会丢失,导致缓存未命中和性能抖动。特别是当消费者采用BusySpinWaitStrategy 时,线程绑定是必不可少的,它可以防止操作系统将其他任务调度到这个本应专用于忙等待的核心上,从而保证最低的响应延迟。

因此,强烈建议将生产者线程以及每个关键的消费者线程都绑定到独立的、专用的物理CPU核心上 。

5.4. 生产者与消费者实现模式

  • 生产者:应遵循规范的两阶段发布模式:首先调用 next() 声明一个序号,然后通过 get() 获取事件对象并填充数据,最后调用 publish() 发布。为了保证健壮性,强烈建议将此过程置于 try-finally 块中,以确保即使在填充数据时发生异常,已声明的序号也总能被发布,避免Disruptor状态不一致。
  • 消费者 (EventHandler):核心是实现 onEvent 方法,该方法会接收到事件对象、其序号以及一个 endOfBatch 标志。
  • 高效批处理:endOfBatch 标志是一个极其强大的优化工具。如果消费者需要执行较慢的I/O操作(如写入磁盘或网络),它不应该每处理一个事件就执行一次I/O。正确的做法是在内部缓存一批事件,只有当 endOfBatch 标志为 true 时,才将整个批次一次性地刷出。这将I/O操作的固定开销摊销到多个事件上,可以极大地提升吞吐量。

最终的系统性能并非由单一的“银弹”技术决定,而是由一系列精心选择的、与硬件协同工作的优化措施叠加而成。Disruptor架构提供了宏观层面的性能基础,而缓存行填充、CPU亲和性以及高效的批处理等微观优化则是达到纳秒级延迟的关键。忽略其中任何一个环节,都可能在不经意间削弱其他优化带来的成果。

同时,Disruptor所施加的约束,如固定大小的缓冲区、预分配机制和单一写入者原则,实际上是一种有益的设计驱动力。它们迫使开发者在设计初期就深入思考系统的容量、数据访问模式和数据流,从而引导架构走向一条本质上就具备高性能和健壮性的道路。采用Disruptor不仅是选择一个库,更是采纳一种能够构建出“设计即性能”的系统架构哲学。


6. 结论:实现确定性的超低延迟性能

综上所述,针对音视频系统中高频数据包处理所面临的内存碎片和并发性能瓶颈问题,一个基于LMAX Disruptor模式的整合架构提供了全面而高效的解决方案。该架构通过其核心的环形缓冲区,将确定性的内存池模型(通过事件预分配实现)和无锁的并发模型(通过序号协调实现)无缝地融合在一个协同工作的体系中。

采纳此架构将为系统带来多重决定性优势:

  • 彻底消除内存碎片,保证系统长期运行的稳定性和可预测性。
  • 实现运行时零内存分配,消除了由标准分配器和垃圾回收(在托管环境中)引入的延迟抖动。
  • 通过遵循“单一写入者原则”,避免了锁争用和上下文切换,使生产者路径的性能达到极致。
  • 凭借“机械共鸣”的设计思想,如连续内存布局和缓存行填充,实现了卓越的CPU缓存利用率。
  • 原生支持高效的单生产者、多消费者(SPMC)广播模型,完美契合目标应用场景。

通过从传统的、与现代硬件特性不符的编程模型,转向一个精心设计的、以低延迟和高吞吐为核心目标的架构,该音视频系统将能够从一个性能不可预测、存在潜在不稳定风险的状态,转变为一个具备确定性、超低延迟和高吞-吐量能力的高性能实时数据处理平台。

引用的著作
  1. RTOS Memory Fragmentation: Analysis and Mitigation Strategies | by Lance Harvie, 访问时间为 十月 2, 2025, https://medium.com/@lanceharvieruntime/rtos-memory-fragmentation-analysis-and-mitigation-strategies-ea3acfd4773e
  2. Memory Fragmentation, your worst nightmare - Software Verify, 访问时间为 十月 2, 2025, https://www.softwareverify.com/blog/memory-fragmentation-your-worst-nightmare/
  3. A Study of Real-time Memory Management: Evaluating Operating System’s Performance, 访问时间为 十月 2, 2025, https://journals.bg.agh.edu.pl/AUTOMAT/2013.17.1/automat.2013.17.1.29.pdf
  4. Memory fragmentation - Qt Forum, 访问时间为 十月 2, 2025, https://forum.qt.io/topic/102292/memory-fragmentation
  5. Dynamic memory in real time systems - a solution? - Embedded Software, 访问时间为 十月 2, 2025, https://blogs.sw.siemens.com/embedded-software/2014/05/06/dynamic-memory-in-real-time-systems-a-solution/
  6. System memory in different time instances with diverse fragmentation states - ResearchGate, 访问时间为 十月 2, 2025, https://www.researchgate.net/figure/System-memory-in-different-time-instances-with-diverse-fragmentation-states-as-dynamic_fig1_305333536
  7. What is Heap Fragmentation? - C++ for Arduino, 访问时间为 十月 2, 2025, https://cpp4arduino.com/2018/11/06/what-is-heap-fragmentation.html
  8. Storage Allocation for Real-Time, Embedded Systems * - University of North Texas, 访问时间为 十月 2, 2025, https://engineering.unt.edu/cse/research/labs/csrl/files/DARPA-Workshop-01.pdf
  9. LMAX Disruptor: High performance alternative to bounded queues for exchanging data between concurrent threads, 访问时间为 十月 2, 2025, https://lmax-exchange.github.io/disruptor/disruptor.html
  10. The LMAX Disruptor – Open-Sourced Mechanical Sympathy in Action - HFT Review’s blog, 访问时间为 十月 2, 2025, https://www.hftreview.com/pg/blog/mike/read/6991/the-lmax-disruptor-opensourced-mechanical-sympathy-in-action
  11. Dissecting the Disruptor: Why it’s so fast (part one) - Locks Are Bad - Trisha Gee, 访问时间为 十月 2, 2025, https://trishagee.com/2011/07/16/dissecting_the_disruptor_why_its_so_fast_part_one__locks_are_bad/
  12. Memory pool - Wikipedia, 访问时间为 十月 2, 2025, https://en.wikipedia.org/wiki/Memory_pool
  13. endurodave/Allocator: An Efficient C++ Fixed Block Memory Allocator - GitHub, 访问时间为 十月 2, 2025, https://github.com/endurodave/Allocator
  14. How to solve Memory Fragmentation - c++ - Stack Overflow, 访问时间为 十月 2, 2025, https://stackoverflow.com/questions/60871/how-to-solve-memory-fragmentation
  15. performance - Memory Allocation/Deallocation Bottleneck? - Stack Overflow, 访问时间为 十月 2, 2025, https://stackoverflow.com/questions/470683/memory-allocation-deallocation-bottleneck
  16. Slab Allocator - The Linux Kernel Archives, 访问时间为 十月 2, 2025, https://www.kernel.org/doc/gorman/html/understand/understand011.html
  17. Allocating Kernel Memory (Buddy System and Slab System) - Tutorials Point, 访问时间为 十月 2, 2025, https://www.tutorialspoint.com/allocating-kernel-memory-buddy-system-and-slab-system
  18. The Slab Allocator: An Object-Caching Kernel … - People @EECS, 访问时间为 十月 2, 2025, https://people.eecs.berkeley.edu/~kubitron/courses/cs194-24-S14/hand-outs/bonwick_slab.pdf
  19. Allocating kernel memory (buddy system and slab system) - GeeksforGeeks, 访问时间为 十月 2, 2025, https://www.geeksforgeeks.org/operating-systems/operating-system-allocating-kernel-memory-buddy-system-slab-system/
  20. fragmentation in Baremetal vs OS : r/embedded - Reddit, 访问时间为 十月 2, 2025, https://www.reddit.com/r/embedded/comments/16vxxfm/fragmentation_in_baremetal_vs_os/
  21. LMAX Disruptor - GitHub Pages, 访问时间为 十月 2, 2025, https://lmax-exchange.github.io/disruptor/
  22. Disruptor-1.0.pdf - GitHub Pages, 访问时间为 十月 2, 2025, https://lmax-exchange.github.io/disruptor/files/Disruptor-1.0.pdf
  23. Java – Adrian’s Blog, 访问时间为 十月 2, 2025, https://masteranyfield.com/category/java/
  24. The LMAX Architecture - Martin Fowler, 访问时间为 十月 2, 2025, https://martinfowler.com/articles/lmax.html
  25. What is LMAX Disruptor Design Pattern? - Stack Overflow, 访问时间为 十月 2, 2025, https://stackoverflow.com/questions/14630901/what-is-lmax-disruptor-design-pattern
  26. What is a ring buffer? - Redisson PRO, 访问时间为 十月 2, 2025, https://redisson.pro/glossary/ring-buffer.html
  27. Circular buffer - Wikipedia, 访问时间为 十月 2, 2025, https://en.wikipedia.org/wiki/Circular_buffer
  28. LMAX Disruptor User Guide, 访问时间为 十月 2, 2025, https://lmax-exchange.github.io/disruptor/user-guide/index.html
  29. Difference between a ring buffer and a queue - Stack Overflow, 访问时间为 十月 2, 2025, https://stackoverflow.com/questions/23111496/difference-between-a-ring-buffer-and-a-queue
  30. How does LMAX’s disruptor pattern work? - Stack Overflow, 访问时间为 十月 2, 2025, https://stackoverflow.com/questions/6559308/how-does-lmaxs-disruptor-pattern-work
  31. Concurrency with LMAX Disruptor - An Introduction - Baeldung, 访问时间为 十月 2, 2025, https://www.baeldung.com/lmax-disruptor-concurrency
  32. False Sharing - Mechanical Sympathy, 访问时间为 十月 2, 2025, https://mechanical-sympathy.blogspot.com/2011/07/false-sharing.html
  33. RingBuffer: The Secret Weapon for High-Performance Java Applications - Medium, 访问时间为 十月 2, 2025, https://medium.com/@amit.agarwal0422/ringbuffer-the-secret-weapon-for-high-performance-java-applications-ebabdb64ce58
  34. Explaining the LMAX Disruptor - DEV Community, 访问时间为 十月 2, 2025, https://dev.to/kspeakman/explaining-the-lmax-disruptor-jkd
  35. Port of LMAX Disruptor to .NET - GitHub, 访问时间为 十月 2, 2025, https://github.com/disruptor-net/Disruptor-net
  36. disruptor - crates.io: Rust Package Registry, 访问时间为 十月 2, 2025, https://crates.io/crates/disruptor
  37. Dissecting the Disruptor: What’s so special about a ring buffer? - Trisha’s Ramblings, 访问时间为 十月 2, 2025, https://mechanitis.blogspot.com/2011/06/dissecting-disruptor-whats-so-special.html
  38. Dissecting the Disruptor: Why it’s so fast (part two) - Magic cache line padding - Trisha Gee, 访问时间为 十月 2, 2025, https://trishagee.com/2011/07/22/dissecting_the_disruptor_why_its_so_fast_part_two__magic_cache_line_padding/
  39. Disruptor - Using High Performance, Low Latency Technology in the CERN Control System - JACoW, 访问时间为 十月 2, 2025, https://jacow.org/icalepcs2015/papers/web3o03.pdf
  40. High Performance Event Publishing with Disruptor | by Udai Bhaskar - Medium, 访问时间为 十月 2, 2025, https://medium.com/@pvub/high-performance-event-publishing-with-disruptor-9d4d88fcfbc8
  41. Dissecting the Disruptor: What’s so special about a ring buffer? - Trisha Gee, 访问时间为 十月 2, 2025, https://trishagee.com/2011/06/22/dissecting_the_disruptor_whats_so_special_about_a_ring_buffer/
  42. Dissecting the Disruptor: Writing to the ring buffer - Trisha’s Ramblings, 访问时间为 十月 2, 2025, https://mechanitis.blogspot.com/2011/07/dissecting-disruptor-writing-to-ring.html
  43. Efficient Inter-Process Pub-Sub in C++: A Lock-Free, Low-Latency SPMC Queue - Medium, 访问时间为 十月 2, 2025, https://medium.com/@manojddesilva/efficient-inter-process-pub-sub-in-c-a-lock-free-low-latency-spmc-queue-9ee06f916827
  44. Package com.lmax.disruptor, 访问时间为 十月 2, 2025, https://lmax-exchange.github.io/disruptor/javadoc/com.lmax.disruptor/com/lmax/disruptor/package-summary.html
  45. java - Disruptor - Ring Buffer - Stack Overflow, 访问时间为 十月 2, 2025, https://stackoverflow.com/questions/31966781/disruptor-ring-buffer
  46. How to decide ring buffer size based upon L3 cache size? - Google Groups, 访问时间为 十月 2, 2025, https://groups.google.com/g/lmax-disruptor/c/kSMgjHvZ6wU
  47. Processor affinity - Wikipedia, 访问时间为 十月 2, 2025, https://en.wikipedia.org/wiki/Processor_affinity
  48. LMAX Disruptor – High Performance Inter-Thread Messaging Library | Hacker News, 访问时间为 十月 2, 2025, https://news.ycombinator.com/item?id=38313457
  49. CPU / thread affinity—core pinning for an app - Febooti, Ltd., 访问时间为 十月 2, 2025, https://www.febooti.com/products/automation-workshop/online-help/actions/tweak-app/cpu-core-thread-affinity/
  50. should I use thread affinity for “latency-critical” threads? - Stack Overflow, 访问时间为 十月 2, 2025, https://stackoverflow.com/questions/15295438/should-i-use-thread-affinity-for-latency-critical-threads
  51. Using disruptor in the Java Servlet and handling multiple events [closed] - Stack Overflow, 访问时间为 十月 2, 2025, https://stackoverflow.com/questions/18375147/using-disruptor-in-the-java-servlet-and-handling-multiple-events
  52. EventHandler (Disruptor) - javadoc.io, 访问时间为 十月 2, 2025, https://javadoc.io/doc/com.lmax/disruptor/3.4.4/com/lmax/disruptor/EventHandler.html
  53. EventHandler (Disruptor), 访问时间为 十月 2, 2025, https://lmax-exchange.github.io/disruptor/javadoc/com.lmax.disruptor/com/lmax/disruptor/EventHandler.html
  54. Is disruptor for situation where I have a slow consumer that must process events sequentially? - Google Groups, 访问时间为 十月 2, 2025, https://groups.google.com/g/lmax-disruptor/c/KsROT6yOesA
Logo

火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。

更多推荐