Replies: 1 comment
-
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment



Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Axvisor内存分配器设计文档
1. 引言
1.1 背景
axvisor作为基于ArceOS的Hypervisor,内存管理是其核心基础设施。当前内存分配器架构存在多内存区域支持不足、大页面分配效率不高、长期运行稳定性问题等问题,需要设计新的架构以满足虚拟化环境的特殊需求。
1.2 设计目标
2. 当前架构分析与问题
2.1 Level-1单级TLSF分配器(当前默认)
axvisor通过
alloc-level-1特性启用Level-1架构:工作流程:
优势:
局限性:
2.2 Level-2两级分配器架构(理论存在但实际不可用)
虽然代码中存在Level-2的实现,但由于bitmap分配器的限制,实际上不可用:
Bitmap分配器架构限制:
单一连续内存模型:
单一基址对齐机制:
为什么
add_memory难以实现:2.3 当前架构的根本性问题
3. 内存分配器技术分析
3.1 主流操作系统内存分配器
3.1.1 通用操作系统的设计哲学
主流操作系统(如Linux、Windows)的需求与TLSF的设计目标存在根本差异,linux内存分配器实现为:
设计特点:
3.1.2 为什么主流操作系统不采用TLSF作为核心分配器
具体技术差异:
3.2 Buddy+Slab vs Bitmap+TLSF架构对比
3.2.1 架构概述
当前架构(Bitmap+TLSF)
目标架构(Buddy+Slab)
3.2.2 内存生态完整性对比
Buddy+Slab:双向流动的健康生态
Bitmap+TLSF:单向流动的架构缺陷
真实影响:
3.3 内存分配器核心原理
3.3.1 Buddy System原理
基本概念与设计思想
Buddy分配器是一种基于二分伙伴关系的页面分配算法,其核心思想是:
分配与释放算法
分配算法流程:
释放算法流程:
Buddy分配过程示例
3.3.2 Slab分配器原理
基本概念与设计思想
Slab分配器是一种针对小对象优化的固定大小分配器,其核心思想是:
Slab分配过程示例
3.4 Per-CPU缓存设计原理与价值
3.4.1 多核环境下的内存分配挑战
在现代多核处理器环境中,传统的全局锁内存分配器面临严重的性能瓶颈:
锁竞争问题:
缓存一致性开销:
性能扩展性限制:
3.4.2 Per-CPU缓存的核心设计思想
Per-CPU缓存通过将内存分配资源分散到各个CPU核心,从根本上解决了多核环境下的性能问题:
资源分散化:
无锁快速路径:
Slab组织结构
三层抽象模型:
对象层(Object Layer)
Slab层(Slab Layer)
缓存层(Cache Layer)
分配与释放机制
对象分配流程:
4. 新内存分配架构设计
4.1 架构层次与职责
新架构基于模块化设计原则,将内存分配功能完全封装在allocator模块中,axalloc模块仅作为轻量级适配层:
4.2 核心数据结构与接口设计
4.2.1 全局协调器接口
4.2.2 页面分配器接口
4.2.3 Buddy分配器内部结构
4.2.4 Slab字节分配器接口
4.2.5 Slab分配器内部结构
4.3 Buddy页面分配器设计
4.3.1 角色与约束
Buddy 层承担“页帧银行”的职能:它要把平台暴露的多个不连续可用区整合为统一库存,再按需向 Slab 或直接向调用方出售大块页帧。为了在
GlobalAllocator自举前运行,它需要满足以下硬性约束:const数组、percpu段或页帧自身承载,避免Vec/Box。modules/axalloc传入&[MemoryRegionDescriptor]后即可即时拆块,无需长驻列表。4.3.2 Buddy分配算法
核心数据结构
BuddyPageAllocatorPageAllocatortrait,封装全局/本地池与统计modules/axalloc只与它交互BuddySetPerCpuPoolSmallChunkCache+ 本地BuddySet+ 平衡计时SmallChunkCacheBuddyStatsTOTAL_FREE_PAGES、分层水位分配算法流程
释放算法流程
4.3.3 协作与调度策略
LOCAL_ORDER(通常覆盖 0~18 阶)之内的请求优先由当前 CPU 处理;更高阶由global_pool以SpinNoIrq保护处理。target_local_pages = TOTAL_FREE_PAGES / MAX_CPUS,每个PerCpuPool以该值为基准执行“借/还”批处理,防止单核屯货。BuddyPageAllocator::alloc_pages(order)。dealloc_pages(),Buddy 立即把块合并回链表。BuddyStats为 Slab 提供“可借额度”,防止 Slab 在系统内存紧张时继续扩张。4.4 Slab字节分配器设计
4.4.1 角色与协作定位
Slab 层是“字节粒度前哨站”:它屏蔽高频的小对象波动,让 Buddy 只需处理页面级事件。为了维持该定位,Slab 在架构上遵循以下原则:
UsageKind对齐。LocalObjectCache在 IRQ-off 区域内完成 push/pop,99% 的请求不会触发锁。SlabMeta中,便于与 Buddy 同步启动。4.4.2 Slab分配算法
核心组件
SlabByteAllocatorByteAllocator,桥接 Buddypage_allocator: &'static BuddyPageAllocator借页SlabCachePerCpuSlabCacheLocalObjectCache与水位线LocalObjectCachecached_bytesrefill_from_global/drain_to_global分配算法流程
释放算法流程
4.4.3 运行路径与Buddy的联动
alloc()→ 当前 CPULocalObjectCache::alloc_fast(),直接弹出 freelist。cached_bytes < low_watermark时,取一半SlabCache::partial槽位;如果 partial 为空,则向 Buddy 借整页并初始化SlabMeta。cached_bytes > high_watermark时,把一半槽位推回SlabCache::partial;若整页无人使用,直接调用BuddyPageAllocator::dealloc_pages()。LocalObjectCache更新UsageKind::{SlabBytes, SlabPages},GlobalAllocator因而知道 Slab 是否在快速消耗或归还页帧,可据此调整阈值策略。4.4.4 初始化顺序(与 Buddy 同步)
BuddyPageAllocator::bootstrap()完成后立即向 Slab 暴露首批页面。SlabByteAllocator::bootstrap()初始化global_caches/percpu段,并为每个 size class 设定low/high watermark。percpu::init_secondary()调用PerCpuSlabCache::init_local(),确保在 AP 上下文也能无锁分配。alloc/dealloc先命中 Slab;只有当对象大于 2 KB 或 Slab 暂缺页面时才退回 Buddy。这种"先 Slab、后 Buddy、再回 Buddy"的闭环正是 4.1 所述生态的关键。4.5 分配器协作机制
4.5.1 智能分配路由
全局分配器根据请求大小自动选择最优分配器:
4.5.2 双向流动的内存生态
这种双向流动机制解决了原有架构的"单向流动"缺陷:
4.5.3 Per-CPU缓存平衡机制
4.6 初始化与运行流程
4.6.1 系统启动流程
4.6.2 运行期分配流程
4.7 Axalloc适配层设计
4.7.1 极简适配层实现
4.7.2 使用方式
5. 架构优势与实现价值
5.1 性能优势分析
5.1.1 大页面分配效率提升
场景对比:分配1GB连续内存
性能提升:大页面分配效率提升巨大,特别是在内存碎片化场景下。
5.1.2 多核扩展性优化
Per-CPU缓存优势:
性能指标:
5.3 长期运行稳定性
5.3.1 内存碎片控制
Buddy系统优势:
Slab系统优势:
5.3.2 内存泄漏防护
引用计数机制:
6. 总结
Axvisor内存分配器重新设计基于对现有架构问题的深入分析和对主流操作系统设计理念的学习,采用Buddy+Slab两级分配架构,通过Per-CPU缓存优化多核性能,实现了以下关键改进:
Beta Was this translation helpful? Give feedback.
All reactions