Skip to content

Utils_FixedSizePool

SweerItTer edited this page Feb 1, 2026 · 3 revisions

FixedSizePool API 文档

概述

FixedSizePool 是 utilsCore 核心模块的高性能内存池类,提供固定大小的内存块管理,用于减少内存分配开销,通过线程本地缓存(TLS)和批量操作实现高并发性能。

职责

  • 管理固定大小的内存块池
  • 提供超高速的内存块分配和释放
  • 通过线程本地缓存减少锁竞争
  • 支持批量填充和刷新操作

适用场景

  • 高频内存分配和释放
  • 多线程高并发环境
  • 固定大小对象的内存管理
  • RGA、V4L2 等硬件模块的缓冲区管理
  • Frame 对象的底层内存池

性能优势

  • 线程本地缓存: 每个线程独占缓存,避免锁竞争
  • 批量操作: 减少锁持有时间
  • 缓存行对齐: 防止伪共享(alignas(64))
  • 分支预测优化: 使用 LIKELY/UNLIKELY 宏

依赖关系

  • 依赖: C++ STL, thread_local
  • 被依赖: RgaProcessor, Frame, CameraController 等上层模块

类分析

FixedSizePool 类

职责与用途

FixedSizePool 是固定大小内存池的实现,提供:

  • 固定大小内存块的快速分配(allocate()
  • 内存块的快速释放(deallocate()
  • 自动内存管理和批量操作
  • 线程本地缓存优化

设计模式

  • 对象池模式: 复用内存块,减少分配开销
  • TLS 模式: 线程本地缓存,减少锁竞争
  • 批量操作: refill/flush 批量填充和刷新

结构体定义

Node 结构体

职责与用途

Node 是内存块链表节点,用于构建空闲链表。

结构体定义

struct Node {
    Node* next;
};

字段说明

字段 类型 说明
next Node* 指向下一个空闲节点的指针

ThreadCache 结构体

职责与用途

ThreadCache 是线程本地缓存,使用 alignas(64) 防止伪共享。每个线程独享一个缓存,减少锁竞争。

结构体定义

struct alignas(ARCH_LINE_SIZE) ThreadCache {
    void* blocks[TLS_CACHE_SIZE];
    size_t count = 0;
    FixedSizePool* owner = nullptr;

    ~ThreadCache() {
        if (owner && count > 0) owner->flush_all(this);
    }
};

字段说明

字段 类型 说明
blocks void*[TLS_CACHE_SIZE] 缓存的内存块数组
count size_t 当前缓存的内存块数量
owner FixedSizePool* 所属的内存池指针

缓存参数

参数 ARM 架构 x86 架构 说明
ARCH_LINE_SIZE 64 64 缓存行大小
TLS_CACHE_SIZE 1024 2048 线程缓存最大容量
TLS_BATCH_SIZE 256 512 批量填充/刷新大小

公共 API 方法

FixedSizePool() - 构造函数

FixedSizePool(size_t blockSize, size_t blocksPerPage = 2048, size_t alignment = 64, size_t prealloc = 0)

参数说明:

  • blockSize (输入): 单个内存块大小(字节)
  • blocksPerPage (输入): 每页分配的内存块数量,默认 2048
  • alignment (输入): 内存对齐要求,默认 64 字节
  • prealloc (输入): 预分配的页数,默认 0

返回值: 无

所有权归属:

  • FixedSizePool 拥有所有内存块的所有权

注意事项:

  1. blockSize 会被自动对齐到 alignment 的倍数
  2. 最小 blockSizesizeof(Node*)(8 字节)
  3. prealloc > 0 时会立即分配内存页
  4. 对齐参数影响缓存性能,建议使用 64 字节

使用例程:

// 创建 128 字节内存块池,每页 2048 个块
FixedSizePool pool(128);

// 创建 256 字节内存块池,预分配 2 页
FixedSizePool pool(256, 2048, 64, 2);

// 创建 512 字节内存块池,自定义对齐
FixedSizePool pool(512, 1024, 128);

~FixedSizePool() - 析构函数

~FixedSizePool()

参数说明: 无

返回值: 无

所有权归属:

  • 释放所有内存页

注意事项:

  1. 析构时会自动回收所有线程缓存的内存块
  2. 使用 _aligned_free(Windows)或 free(Linux)释放内存
  3. 析构后所有分配的内存块都变为无效

allocate() - 分配内存块

void* allocate()

参数说明: 无

返回值:

  • 成功: 返回内存块指针
  • 失败: 返回 nullptr(内存不足)

所有权归属:

  • 返回的内存块由调用者持有
  • 必须使用 deallocate() 归还

注意事项:

  1. 首先从线程本地缓存获取
  2. 缓存为空时调用 refill() 批量填充
  3. 极其精简,适合 inline 展开
  4. 时间复杂度: O(1)(缓存命中)

使用例程:

FixedSizePool pool(128);

// 分配内存块
void* ptr = pool.allocate();
if (ptr) {
    // 使用内存块
    memset(ptr, 0, 128);
    
    // 使用后归还
    pool.deallocate(ptr);
} else {
    printf("Memory allocation failed\n");
}

deallocate() - 释放内存块

void deallocate(void* p)

参数说明:

  • p (输入): 要释放的内存块指针

返回值: 无

所有权归属:

  • 内存块所有权归还给 FixedSizePool

注意事项:

  1. pnullptr 时直接返回
  2. 释放到线程本地缓存
  3. 缓存满时调用 flush() 批量刷新到全局
  4. 时间复杂度: O(1)

使用例程:

FixedSizePool pool(128);

void* ptr = pool.allocate();

// 使用内存块
MyStruct* obj = (MyStruct*)ptr;
obj->value = 42;

// 释放内存块
pool.deallocate(ptr);

私有 API 方法

get_fast_thread_cache() - 获取线程本地缓存

ThreadCache* get_fast_thread_cache()

职责与用途: 使用 thread_local 获取当前线程的缓存,确保每个线程独享缓存。

实现要点:

  • 使用 static thread_local ThreadCache cache
  • 首次使用时设置 owner
  • 无锁访问,极快

refill() - 批量填充缓存

void refill(ThreadCache* cache)

职责与用途: 从全局空闲链表批量获取内存块,填充到线程缓存。

参数说明:

  • cache (输入): 线程本地缓存指针

填充策略:

  • 尽量填满缓存或拿走一个 Batch(TLS_BATCH_SIZE
  • 使用 central_mutex_ 保护全局链表

flush() - 批量刷新缓存

void flush(ThreadCache* cache)

职责与用途: 将线程本地缓存的一半内存块刷新到全局空闲链表。

参数说明:

  • cache (输入): 线程本地缓存指针

刷新策略:

  • 回冲一半缓存到全局
  • 保留一半在本地继续使用
  • 在锁外构造链表,减少锁持有时间

flush_all() - 刷新全部缓存

void flush_all(ThreadCache* cache)

职责与用途: 将线程本地缓存的所有内存块刷新到全局空闲链表。

参数说明:

  • cache (输入): 线程本地缓存指针

调用时机:

  • 线程退出时(ThreadCache 析构函数)

expand() - 扩展内存池

void expand(size_t pages)

职责与用途: 分配指定数量的内存页,扩展内存池。

参数说明:

  • pages (输入): 要分配的页数

使用场景:

  • 预分配内存(构造函数调用)
  • 动态扩展内存池

expand_internal() - 内部扩展实现

void expand_internal()

职责与用途: 分配单个内存页,初始化并链接到空闲链表。

实现要点:

  • 使用 _aligned_malloc(Windows)或 posix_memalign(Linux)
  • 初始化为单向链表
  • 挂载到全局空闲链表头部

内存池结构

整体架构

┌─────────────────────────────────────────────────────────┐
│                   FixedSizePool                         │
├─────────────────────────────────────────────────────────┤
│  ThreadCache (thread_local, 每线程一个)                  │
│  ┌──────────────────────────────────────────────────┐   │
│  │  blocks[2048]  ← void* 指针数组                   │   │
│  │  count = 1024   ← 当前缓存数量                    │   │
│  │  owner = this   ← 所属池指针                      │   │
│  └──────────────────────────────────────────────────┘   │
│                                                         │
│  Global Freelist (中心空闲链表)                          │
│  ┌──────────────────────────────────────────────────┐   │
│  │  freelist_head_ → Node → Node → ...              │   │
│  └──────────────────────────────────────────────────┘   │
│                                                         │
│  Memory Pages(内存页)                                    │
│  ┌──────────────────────────────────────────────────┐   │
│  │  Page 1: [Block][Block]...[Block]                │   │
│  │  Page 2: [Block][Block]...[Block]                │   │ 
│  │  ...                                             │   │
│  └──────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────┘

分配流程

1. 调用 allocate()
   ↓
2. 获取线程本地缓存 (get_fast_thread_cache)
   ↓
3. 检查缓存是否为空 (cache->count == 0)
   ↓
4. 如果为空,调用 refill() 批量填充
   ↓
5. 从缓存末尾取出一个内存块
   ↓
6. 返回内存块指针

释放流程

1. 调用 deallocate(void* p)
   ↓
2. 检查指针是否为 nullptr
   ↓
3. 获取线程本地缓存
   ↓
4. 检查缓存是否已满 (cache->count >= TLS_CACHE_SIZE)
   ↓
5. 如果已满,调用 flush() 批量刷新
   ↓
6. 将内存块放入缓存
   ↓
7. 缓存计数加 1

所有权规则总结

资源 拥有者 释放方式 线程保护
内存页 FixedSizePool ~FixedSizePool() page_mutex_
全局空闲链表 FixedSizePool ~FixedSizePool() central_mutex_
allocate() 后的内存块 调用者 必须调用 deallocate() -
deallocate() 后的内存块 FixedSizePool 重新入池 -

所有权传递规则

分配流:
FixedSizePool → allocate() → void* → 调用者持有

归还流:
调用者 → deallocate(void*) → ThreadCache → 全局空闲链表

线程安全说明

同步机制

  • ThreadCache: thread_local,每个线程独享,无锁访问
  • 全局空闲链表: central_mutex_ 保护
  • 内存页管理: page_mutex_ 保护
  • 内存池扩展: expand_mutex_ 保护

锁分离策略

锁名称 保护资源 使用场景
central_mutex_ 全局空闲链表 refill, flush
page_mutex_ 内存页列表 expand_internal, 析构
expand_mutex_ 扩展操作 expand

线程安全建议

  • allocate()deallocate() 可以多线程并发调用
  • 线程本地缓存自动管理,无需外部同步
  • 线程退出时自动刷新缓存到全局
  • 避免跨线程传递内存块

性能优化

1. 线程本地缓存(TLS)

static thread_local ThreadCache cache;
  • 每个线程独享缓存
  • 无锁访问,减少竞争
  • 线程退出时自动清理

2. 批量操作

// 批量填充
refill(ThreadCache* cache) {
    size_t take = std::min(TLS_BATCH_SIZE, TLS_CACHE_SIZE - cache->count);
    // 批量取出内存块
}

// 批量刷新
flush(ThreadCache* cache) {
    size_t to_flush = TLS_BATCH_SIZE;
    // 批量归还内存块
}
  • 减少锁获取次数
  • 提高缓存命中率

3. 缓存行对齐

struct alignas(ARCH_LINE_SIZE) ThreadCache {
    // ...
};
  • 防止伪共享
  • 提高 CPU 缓存效率

4. 分支预测优化

if (UNLIKELY(cache->count == 0)) {
    refill(cache);
}
  • 告诉编译器分支概率
  • 优化 CPU 指令流水线

典型使用场景

场景 1: 基本使用

// 创建 128 字节内存块池
FixedSizePool pool(128);

// 分配和使用内存块
for (int i = 0; i < 1000; ++i) {
    void* ptr = pool.allocate();
    if (ptr) {
        // 使用内存块
        MyStruct* obj = (MyStruct*)ptr;
        obj->id = i;
        obj->value = i * 2;
        
        // 处理完成后释放
        pool.deallocate(ptr);
    }
}

场景 2: RgaProcessor 缓冲池

class RgaProcessor {
private:
    FixedSizePool buffer_pool_;
    size_t buffer_size_;
    
public:
    RgaProcessor(int width, int height, uint32_t format)
        : buffer_size_(calculateBufferSize(width, height, format))
        , buffer_pool_(buffer_size_, 1024, 64, 2) {
        // 预分配 2 页缓冲区
    }
    
    void* allocateBuffer() {
        return buffer_pool_.allocate();
    }
    
    void releaseBuffer(void* buffer) {
        if (buffer) {
            buffer_pool_.deallocate(buffer);
        }
    }
    
private:
    size_t calculateBufferSize(int width, int height, uint32_t format) {
        // 根据格式计算缓冲区大小
        return width * height * 2; // 假设 NV12 格式
    }
};

场景 3: 多线程高并发

#include <thread>
#include <vector>

FixedSizePool pool(256, 2048, 64, 10);

void worker(int id) {
    for (int i = 0; i < 10000; ++i) {
        void* ptr = pool.allocate();
        if (ptr) {
            // 模拟处理
            memset(ptr, id, 256);
            pool.deallocate(ptr);
        }
    }
}

int main() {
    std::vector<std::thread> threads;
    for (int i = 0; i < 8; ++i) {
        threads.emplace_back(worker, i);
    }
    
    for (auto& t : threads) {
        t.join();
    }
    
    return 0;
}

场景 4: Frame 对象内存池

class FramePool {
private:
    FixedSizePool frame_pool_;
    size_t frame_size_;
    
public:
    FramePool(int width, int height, uint32_t format)
        : frame_size_(width * height * 4)  // RGBA 格式
        , frame_pool_(frame_size_, 1024, 64, 5) {
    }
    
    std::shared_ptr<void> allocateFrame() {
        void* ptr = frame_pool_.allocate();
        if (ptr) {
            return std::shared_ptr<void>(ptr, [this](void* p) {
                frame_pool_.deallocate(p);
            });
        }
        return nullptr;
    }
};

场景 5: 自定义对象管理

template<typename T>
class ObjectPool {
private:
    FixedSizePool pool_;
    
public:
    ObjectPool(size_t count = 1024)
        : pool_(sizeof(T), count, 64, 1) {
    }
    
    T* allocate() {
        void* ptr = pool_.allocate();
        if (ptr) {
            return new(ptr) T();  // placement new
        }
        return nullptr;
    }
    
    void deallocate(T* obj) {
        if (obj) {
            obj->~T();  // 调用析构函数
            pool_.deallocate(obj);
        }
    }
};

// 使用
ObjectPool<MyClass> pool;
MyClass* obj = pool.allocate();
if (obj) {
    obj->doSomething();
    pool.deallocate(obj);
}

高级用法

用法 1: 替换 new/delete 操作符

通过重载类的 new/delete 操作符,让对象自动使用内存池分配:

class MyClass {
public:
    int id;
    double value;
    
    MyClass() : id(0), value(0.0) {}
    MyClass(int i, double v) : id(i), value(v) {}
    
    void doSomething() {
        printf("MyClass: id=%d, value=%f\n", id, value);
    }
    
    // 重载 new 操作符
    void* operator new(size_t size) {
        return my_pool.allocate();
    }
    
    // 重载 delete 操作符
    void operator delete(void* ptr) {
        my_pool.deallocate(ptr);
    }
    
    // 支持 new[] 和 delete[]
    void* operator new[](size_t size) {
        return my_pool.allocate();
    }
    
    void operator delete[](void* ptr) {
        my_pool.deallocate(ptr);
    }
    
private:
    static FixedSizePool my_pool;
};

// 静态成员初始化
FixedSizePool MyClass::my_pool(sizeof(MyClass), 1024, 64, 2);

// 使用方式 - 与普通 new/delete 完全一致
int main() {
    // 自动使用内存池分配
    MyClass* obj1 = new MyClass(1, 3.14);
    obj1->doSomething();
    delete obj1;  // 自动归还到内存池
    
    // 数组分配
    MyClass* obj2 = new MyClass[5];
    for (int i = 0; i < 5; ++i) {
        obj2[i].id = i;
        obj2[i].value = i * 1.5;
    }
    delete[] obj2;
    
    return 0;
}

用法 2: 自定义 STL 分配器

创建兼容 STL 容器的自定义分配器:

template<typename T>
class PoolAllocator {
public:
    using value_type = T;
    using pointer = T*;
    using const_pointer = const T*;
    using reference = T&;
    using const_reference = const T&;
    using size_type = size_t;
    using difference_type = ptrdiff_t;
    
    PoolAllocator() noexcept : pool_(sizeof(T), 1024, 64, 1) {}
    
    template<typename U>
    PoolAllocator(const PoolAllocator<U>&) noexcept {}
    
    template<typename U>
    struct rebind {
        using other = PoolAllocator<U>;
    };
    
    T* allocate(size_type n) {
        if (n != 1) {
            throw std::bad_alloc();
        }
        void* ptr = pool_.allocate();
        if (!ptr) {
            throw std::bad_alloc();
        }
        return static_cast<T*>(ptr);
    }
    
    void deallocate(T* p, size_type) noexcept {
        if (p) {
            pool_.deallocate(p);
        }
    }
    
    template<typename U, typename... Args>
    void construct(U* p, Args&&... args) {
        ::new((void*)p) U(std::forward<Args>(args)...);
    }
    
    template<typename U>
    void destroy(U* p) noexcept {
        p->~U();
    }
    
private:
    FixedSizePool pool_;
};

// 使用自定义分配器的 STL 容器
int main() {
    // 使用内存池的 vector
    std::vector<MyClass, PoolAllocator<MyClass>> vec;
    
    for (int i = 0; i < 1000; ++i) {
        vec.emplace_back(i, i * 2.5);
    }
    
    // 使用内存池的 list
    std::list<int, PoolAllocator<int>> lst;
    for (int i = 0; i < 1000; ++i) {
        lst.push_back(i);
    }
    
    // 使用内存池的 map
    std::map<int, double, std::less<int>, 
             PoolAllocator<std::pair<const int, double>>> mp;
    
    for (int i = 0; i < 1000; ++i) {
        mp[i] = i * 1.5;
    }
    
    return 0;
}

用法 3: 智能指针包装器

使用智能指针自动管理内存池对象的生命周期:

template<typename T>
class PooledObjectDeleter {
public:
    PooledObjectDeleter(FixedSizePool& pool) : pool_(pool) {}
    
    void operator()(T* ptr) const {
        if (ptr) {
            ptr->~T();  // 调用析构函数
            pool_.deallocate(ptr);
        }
    }
    
private:
    FixedSizePool& pool_;
};

template<typename T>
class PooledObject {
private:
    FixedSizePool pool_;
    
public:
    PooledObject(size_t count = 1024) 
        : pool_(sizeof(T), count, 64, 1) {}
    
    using unique_ptr = std::unique_ptr<T, PooledObjectDeleter<T>>;
    
    unique_ptr create() {
        void* ptr = pool_.allocate();
        if (ptr) {
            return unique_ptr(new(ptr) T(), PooledObjectDeleter<T>(pool_));
        }
        return nullptr;
    }
    
    template<typename... Args>
    unique_ptr create(Args&&... args) {
        void* ptr = pool_.allocate();
        if (ptr) {
            return unique_ptr(
                new(ptr) T(std::forward<Args>(args)...), 
                PooledObjectDeleter<T>(pool_)
            );
        }
        return nullptr;
    }
};

// 使用方式
int main() {
    PooledObject<MyClass> pool;
    
    // 创建对象
    auto obj1 = pool.create();
    if (obj1) {
        obj1->doSomething();
    }  // 自动释放
    
    // 带参数创建
    auto obj2 = pool.create(42, 3.14159);
    if (obj2) {
        obj2->doSomething();
    }  // 自动释放
    
    return 0;
}

用法 4: 混合分配策略

根据对象大小选择不同的内存池:

class HybridAllocator {
public:
    HybridAllocator() {
        // 小对象池 (<= 64 字节)
        small_pool_ = std::make_unique<FixedSizePool>(64, 2048, 64, 2);
        // 中等对象池 (<= 256 字节)
        medium_pool_ = std::make_unique<FixedSizePool>(256, 1024, 64, 2);
        // 大对象池 (<= 1024 字节)
        large_pool_ = std::make_unique<FixedSizePool>(1024, 512, 64, 1);
    }
    
    void* allocate(size_t size) {
        if (size <= 64) {
            return small_pool_->allocate();
        } else if (size <= 256) {
            return medium_pool_->allocate();
        } else if (size <= 1024) {
            return large_pool_->allocate();
        } else {
            // 超大对象直接使用 malloc
            return malloc(size);
        }
    }
    
    void deallocate(void* ptr, size_t size) {
        if (size <= 64) {
            small_pool_->deallocate(ptr);
        } else if (size <= 256) {
            medium_pool_->deallocate(ptr);
        } else if (size <= 1024) {
            large_pool_->deallocate(ptr);
        } else {
            free(ptr);
        }
    }
    
private:
    std::unique_ptr<FixedSizePool> small_pool_;
    std::unique_ptr<FixedSizePool> medium_pool_;
    std::unique_ptr<FixedSizePool> large_pool_;
};

// 使用方式
int main() {
    HybridAllocator allocator;
    
    // 自动选择合适的内存池
    void* small = allocator.allocate(32);
    void* medium = allocator.allocate(128);
    void* large = allocator.allocate(512);
    void* huge = allocator.allocate(2048);
    
    allocator.deallocate(small, 32);
    allocator.deallocate(medium, 128);
    allocator.deallocate(large, 512);
    allocator.deallocate(huge, 2048);
    
    return 0;
}

用法 5: 性能统计包装器

为内存池添加性能统计功能:

class PoolWithStats {
public:
    PoolWithStats(size_t blockSize, size_t blocksPerPage = 2048, 
                  size_t alignment = 64, size_t prealloc = 0)
        : pool_(blockSize, blocksPerPage, alignment, prealloc)
        , alloc_count_(0)
        , dealloc_count_(0)
        , total_alloc_time_(0)
        , total_dealloc_time_(0) {}
    
    void* allocate() {
        auto start = std::chrono::high_resolution_clock::now();
        void* ptr = pool_.allocate();
        auto end = std::chrono::high_resolution_clock::now();
        
        if (ptr) {
            alloc_count_++;
            total_alloc_time_ += 
                std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
        }
        
        return ptr;
    }
    
    void deallocate(void* p) {
        if (!p) return;
        
        auto start = std::chrono::high_resolution_clock::now();
        pool_.deallocate(p);
        auto end = std::chrono::high_resolution_clock::now();
        
        dealloc_count_++;
        total_dealloc_time_ += 
            std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
    }
    
    void printStats() const {
        printf("=== Memory Pool Statistics ===\n");
        printf("Total allocations: %zu\n", alloc_count_);
        printf("Total deallocations: %zu\n", dealloc_count_);
        printf("Current allocations: %zu\n", alloc_count_ - dealloc_count_);
        
        if (alloc_count_ > 0) {
            printf("Avg alloc time: %.2f ns\n", 
                   (double)total_alloc_time_ / alloc_count_);
        }
        
        if (dealloc_count_ > 0) {
            printf("Avg dealloc time: %.2f ns\n", 
                   (double)total_dealloc_time_ / dealloc_count_);
        }
        
        printf("==============================\n");
    }
    
private:
    FixedSizePool pool_;
    std::atomic<size_t> alloc_count_;
    std::atomic<size_t> dealloc_count_;
    std::atomic<uint64_t> total_alloc_time_;
    std::atomic<uint64_t> total_dealloc_time_;
};

// 使用方式
int main() {
    PoolWithStats pool(128);
    
    // 分配和释放大量对象
    for (int i = 0; i < 1000000; ++i) {
        void* ptr = pool.allocate();
        if (ptr) {
            pool.deallocate(ptr);
        }
    }
    
    // 打印统计信息
    pool.printStats();
    
    return 0;
}

注意事项

  1. 内存块大小: 内存块大小会在构造时自动对齐到 alignment 的倍数
  2. 最小大小: 内存块最小为 sizeof(Node*)(8 字节)
  3. 线程本地缓存: 线程退出时自动刷新缓存,无需手动处理
  4. 跨线程传递: 避免在不同线程间传递和释放内存块
  5. 指针有效性: 析构后所有分配的指针都变为无效
  6. 空指针检查: deallocate(nullptr) 安全,会直接返回
  7. 内存泄漏: 必须确保所有分配的内存块都被 deallocate()
  8. 性能监控: 建议监控分配失败率,适当调整预分配数量
  9. new/delete 重载: 重载操作符是类级别的,所有对象共享同一个内存池
  10. STL 分配器: 确保 rebind 正确实现,否则某些容器可能无法工作

性能对比

与直接 malloc/free 对比

操作 malloc/free FixedSizePool 性能提升
单线程分配 ~100 ns ~5 ns 20x
单线程释放 ~100 ns ~5 ns 20x
多线程分配 ~200 ns ~10 ns 20x
多线程释放 ~200 ns ~10 ns 20x
内存碎片 -
缓存命中率 -

架构特定性能

架构 TLS_CACHE_SIZE TLS_BATCH_SIZE 推荐场景
ARM 1024 256 嵌入式设备
x86 2048 512 桌面/服务器

相关文档


参考资料

主页

API 文档

DMA 模块

DRM 模块

NET 模块

V4L2 模块

V4L2Param 模块

RGA 模块

MPP 模块

Sys 模块

Mouse 模块

Utils 模块

Clone this wiki locally