From a91d490f84881ee85e9110b54b98a1297b4abf75 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Fri, 11 Sep 2026 20:58:03 +0000 Subject: [PATCH] =?UTF-8?q?perf:=20kernel=5Flifetime=20=E5=A4=8D=E8=B7=91?= =?UTF-8?q?=E8=BE=B9=E7=95=8C=20malloc=5Ftrim=20=E5=BD=92=E9=A1=B5?= =?UTF-8?q?=E2=80=94=E2=80=94=E7=AC=AC=E4=BA=8C=E5=A4=8D=E8=B7=91=E5=A2=9E?= =?UTF-8?q?=E9=95=BF=E7=9B=B8=E5=85=8D=E9=83=A8=E5=88=86=E6=AE=8B=E7=95=99?= =?UTF-8?q?=E9=A1=B5=E5=A4=8D=E7=94=A8=EF=BC=88=E7=83=AD=E6=80=81=E6=96=9C?= =?UTF-8?q?=E7=8E=87=E4=B8=8B=E7=95=8C=EF=BC=89=EF=BC=8Cdoc=20=E6=B3=A8?= =?UTF-8?q?=E6=98=8E=E9=A6=96=E6=B5=8B=E5=9F=BA=E7=BA=BF=E5=8F=96=E5=86=B7?= =?UTF-8?q?=E8=B7=91=E3=80=81=E8=B6=85=E9=98=88=E6=BC=82=E7=A7=BB=E5=85=88?= =?UTF-8?q?=E6=8C=89=E6=BB=9E=E7=95=99=E5=BD=92=E5=9B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_cli/src/bench/leak_detect.rs | 26 ++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/crates/oxide_cli/src/bench/leak_detect.rs b/crates/oxide_cli/src/bench/leak_detect.rs index 91aa4a3b..7a53a97d 100644 --- a/crates/oxide_cli/src/bench/leak_detect.rs +++ b/crates/oxide_cli/src/bench/leak_detect.rs @@ -93,6 +93,25 @@ pub fn read_vmrss_kb() -> Option { None } +// glibc 堆归页入口:把堆顶连续空闲页全部还给 OS(碎片化的内部空闲块 +// 不受影响);仅 Linux/glibc 宿主链接,其余平台空操作。 +#[cfg(target_os = "linux")] +extern "C" { + fn malloc_trim(pad: usize) -> bool; +} + +/// 把上轮校准释放的堆页归还 OS,消除同进程复跑时"上轮残留页被下轮 +/// 增长相复用"导致的第二复跑 RSS 斜率结构性低估。 +fn release_free_heap() { + #[cfg(target_os = "linux")] + { + // SAFETY: 无参无指针状态的 libc 调用,无别名与生命周期问题。 + unsafe { + let _ = malloc_trim(0); + } + } +} + /// 反复运行固定 JS 脚本,跟踪 session/code-forge/symbol 等内存指标, /// 用 `LeakSampler` 回归检测随迭代次数增长的内存占用。 pub fn run_leak_detect(config: &BenchConfig, kernel: &Arc, pool: &Arc) -> ExitCode { @@ -538,7 +557,9 @@ pub fn run_mem_object_churn_peak(kernel: &Arc) -> ExitCode { /// 面;本 case 全程无存活 VM(JS 段 VM 出作用域即 drop),drop 旧 Arc 即 /// 整体释放。重建后 RSS 可能不回落至增长前之下(glibc 小对象 free 滞留 /// 分配器自由链不回 OS),RSS 为次锚仅参考、不进 exit 判据。exit 0/1 -/// 仅由重建相确定性断言驱动。 +/// 仅由重建相确定性断言驱动。第二复跑的增长相可能复用第一复跑的滞留 +/// 页(内部空闲块不随堆顶归页归还 OS),其斜率是热态下界——首测基线 +/// 取第一(冷)复跑;复跑斜率差超阈先按此归因,再疑用例。 pub fn run_mem_kernel_lifetime() -> ExitCode { const JS_OBJECTS: u32 = 8_192; // JS 固定段对象数(每对象一个唯一计算键) const TOTAL_STRINGS: u32 = 191_704; // 增长循环唯一键数(与 JS 固定段键不相交) @@ -648,6 +669,9 @@ pub fn run_mem_kernel_lifetime() -> ExitCode { if rebuilt_entries != 0 || rebuilt_knob.is_some() { return ExitCode::FAILURE; } + + // 复跑边界:本轮回放释放的堆页归还 OS,免残留页计入下轮增长相。 + release_free_heap(); } // 复跑一致性(仅记录不判定):跨轮斜率差 >10% 先查 harness 污染