Skip to content

添加 Heap dealloc free-list scan benchmark - #55

Merged
jiegec merged 4 commits into
rcore-os:masterfrom
Mango-Iced-Americano:bench/heap-dealloc-scan
Jul 5, 2026
Merged

添加 Heap dealloc free-list scan benchmark#55
jiegec merged 4 commits into
rcore-os:masterfrom
Mango-Iced-Americano:bench/heap-dealloc-scan

Conversation

@Pan-Peach

Copy link
Copy Markdown
Contributor

概要

这个 PR 为 Heap 添加了一个 Criterion benchmark,用来构造一种碎片化场景:在释放内存时,dealloc 需要在较长的 free list 中查找 buddy block。

这个 PR 只添加 benchmark,不修改 allocator 的任何行为。

背景

我在把 buddy_system_allocator::Heap 用作内核堆分配器时,遇到过一种 workload:大量重复的分配和释放会让某些 size class 的 free list 变长。

当前 Heap::dealloc 的逻辑会先计算 buddy 地址,但随后仍然需要遍历 free_list[current_class],确认对应的 buddy block 是否处于空闲状态。在碎片化比较明显的场景下,释放路径的开销会受到 free list 长度影响。

这个 benchmark 的目的,是在本仓库内提供一个尽量小的可复现场景,方便后续评估相关优化。

本地测试结果

我在本地运行:

cargo bench --bench heap_dealloc_scan

得到结果如下:

Case Time
100_pairs 24.4 µs
500_pairs 1.43 ms
1000_pairs 5.93 ms
2000_pairs 25.1 ms
5000_pairs 217 ms

较大的 case 是有意保留的压力场景,主要用于观察当 benchmark 构造出较长 free list 后,释放路径成本随之增长的趋势。可以看到性能的退化还是较为明显的,并且在我们内核的实践上,发现这样程度的退化对性能的影响较为显著

benchmark 做了什么

这个 benchmark 大致会:

  1. 初始化一个独立的 Heap

  2. 分配大量相同大小的块;

  3. 按特定模式释放其中一部分块,让某个 size class 的 free list 变长;

  4. 再释放另一部分块,触发 dealloc 中的 buddy lookup 路径。

benchmark 直接使用 Heap,没有使用 LockedHeap,这样可以尽量排除锁开销,更专注于 allocator 本身的行为。

后续想法

如果这个 benchmark 被认为有价值,我后续想继续探索一个可选的 metadata-backed heap 实现。

大致思路是参考页分配器中常见的做法:不要只把 free list 当作唯一的状态来源,而是为被管理的 block 维护显式 metadata,记录 block 的状态和 order。这样在 dealloc 时,可以通过 buddy 地址直接判断 buddy block 是否空闲,而不必线性扫描当前 order 的 free list。

后续可能的实现方向:

  • 默认保持现有 Heap / LockedHeap 行为不变;

  • 新增一个可选 feature,或者新增一个 metadata-backed heap 类型;

  • 显式记录 block 的状态和 order;

  • 使用 per-order free area,并支持 O(1) unlink;

  • 尽量复用现有 heap 测试,验证新实现和现有行为的一致性;

  • 用这个 benchmark 对比优化前后的表现。

我还不确定这个方向是否适合本项目,所以希望先通过这个 benchmark PR 收集一下维护者的意见,再决定是否继续实现。

Panpeach added 2 commits July 4, 2026 22:01
Add a Criterion benchmark that measures Heap::dealloc free-list scan
cost across multiple scales (100–10000 buddy pairs). Constructs a
fragmented workload where free_list[class_6] accumulates freed blocks,
then deallocates their lower-half buddies — each triggering a linear
scan of the intrusive linked list to find its buddy.

Key design:
- Uses raw Heap (not LockedHeap) to avoid spinlock noise
- Paired-buddy strategy with XOR-based pairing and class-7 isolation
- iter_batched with fresh heap state per iteration
- Multiple sizes (100/500/1k/2k/5k/10k pairs) to show O(N²) degradation

Results demonstrate the scan cost grows quadratically as the free
list lengthens: ~25µs at 100 pairs → ~1.7s at 10000 pairs.

Also fix: replace deprecated criterion::black_box with std::hint::black_box
in both bench files. Add .omo/ and core to .gitignore.
5000 pairs already demonstrates O(N²) scan cost clearly
(217ms vs 24µs at 100 pairs). 10000 takes ~250s with default
sample size — too heavy for a quick cargo bench run.
Copilot AI review requested due to automatic review settings July 4, 2026 15:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new Criterion benchmark to reproduce and measure buddy_system_allocator::Heap::dealloc’s free-list buddy-lookup scan cost under a deliberately fragmented workload, enabling future optimization work to be evaluated against a stable in-repo scenario.

Changes:

  • Register a new heap_dealloc_scan benchmark target in Cargo.toml.
  • Add benches/heap_dealloc_scan.rs, which constructs a long free_list[6] and measures dealloc scaling across multiple pair counts.
  • Minor benchmark-related cleanups to the existing memory_allocator_benchmark and .gitignore.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

File Description
Cargo.toml Adds the new heap_dealloc_scan Criterion bench target.
benches/memory_allocator_benchmark.rs Updates benchmark harness usage (rand API / black_box / ctor init details).
benches/heap_dealloc_scan.rs Introduces the new benchmark that stresses Heap::dealloc free-list scanning behavior.
.gitignore Adds ignores for additional local artifacts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread benches/heap_dealloc_scan.rs Outdated
Comment thread benches/memory_allocator_benchmark.rs Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@jiegec

jiegec commented Jul 4, 2026

Copy link
Copy Markdown
Member

benchmark 是可以加,不过本项目不考虑对分配算法进行优化,主要还是教科书上算法的直接实现,用于教学目的。

@Pan-Peach

Copy link
Copy Markdown
Contributor Author

明白了,感谢review,那这个pr只加benchmark可以吗,优化部分的工作我们自己fork下来做

Comment thread .gitignore Outdated
Comment thread benches/memory_allocator_benchmark.rs Outdated
@Pan-Peach

Copy link
Copy Markdown
Contributor Author

修好了,请review

@jiegec
jiegec merged commit da68b6d into rcore-os:master Jul 5, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants