公司动态
HarmonyOS 7 新特性(二十三)|hiprofiler + hidumper:跨堆内存分析
本文基于 HarmonyOS 7 配套的 hiprofiler、hidumper 与资源泄漏检测资料。不同工具的参数、输出格式和设备权限会随版本变化请以当前 DevEco Studio 与系统文档为准。内存问题很少只存在于一个堆。ArkTS 页面可能持有 Native 资源Web 组件拥有独立运行时图片和渲染又会消耗 GPU、DMA 或共享内存。只盯着 JavaScript heap常常会得出“没有泄漏”的错误结论。HarmonyOS 7 的新资料进一步完善 hiprofiler 录制分配与回收、hidumper 导出 ArkTS、Native、GPU、JSVM、ArkWeb、KMP 等内存信息的分析路径。本文给出一套从现象分类到根因闭环的实战方法。一、先区分泄漏、峰值和缓存泄漏是资源在业务结束后仍无法释放峰值可能来自瞬时大图、视频帧或编译缓存则会保留但应在压力或上限到达时回落。三者处理方法不同。设计固定复现脚本进入页面、执行核心操作、退出页面、等待回收重复 10 到 30 轮。每轮记录 ArkTS heap、RSS、GPU、句柄与线程。若基线逐轮上升且不回落才进入泄漏分析。二、建立统一采样模型interfaceMemorySample{timestamp:numberphase:before|active|after-gc|backgroundrssKb:numberarktsHeapKb:numbernativeHeapKb?:numbergpuKb?:numberfdCount:numberthreadCount:number}interfaceMemoryRun{device:stringbuildId:stringscenario:stringsamples:MemorySample[]}所有工具输出最终汇总到同一时间线避免分别看截图后凭感觉关联。三、hiprofiler 适合看分配过程hiprofiler 记录一段时间内的分配、调用栈和释放行为适合回答“哪类对象在什么时候开始增长”“退出页面后哪些分配没有回收”。录制区间应覆盖操作前基线、问题动作和退出后的稳定期。采样太短可能错过慢泄漏采样太长又会产生巨大文件。先用粗粒度指标定位窗口再在 30 到 90 秒的关键区间进行高精度录制。Round 0: open page - idle - baseline Round 1: import image - edit - close - wait Round 2: import image - edit - close - wait Marker: user_actionclose_editor Stop: after memory remains stable for 10s在业务动作处写稳定 Marker可以显著降低工具时间轴与用户步骤对齐的成本。四、hidumper 用于横向快照hidumper 更适合在关键时刻导出多个内存域的状态。建议至少抓三份首次进入后的基线、重复操作后的高点、退出并等待后的回落点。文件名写入轮次与阶段禁止手工覆盖。functionsnapshotName(runId:string,round:number,phase:string):string{constsafePhasephase.replace(/[^a-z0-9-]/gi,_)return${runId}-r${round}-${safePhase}-${Date.now()}}如果 ArkTS heap 回落但 RSS 与 GPU 不回落应转向 PixelMap、Native 缓冲区、渲染资源和文件映射而不是继续检查页面对象。五、用所有权表缩小根因每个重资源都应该有创建者、持有者和释放时机。常见对象包括订阅、定时器、PixelMap、ImageSource、文件描述符、Native handle、Web 页面、Surface 与线程。interfaceOwnedResource{id:stringtype:timer|listener|pixelMap|fd|native|webowner:stringcreatedAt:numberreleasedAt?:number}classResourceLedger{privaterecordsnewMapstring,OwnedResource()open(resource:OwnedResource){this.records.set(resource.id,resource)}close(id:string){constitemthis.records.get(id)if(item)item.releasedAtDate.now()}}这不是替代系统工具而是让工具发现的调用栈可以回到明确业务所有者。六、ArkTS 泄漏看引用链典型问题包括全局数组持有页面、事件总线未取消、闭包捕获大对象和长生命周期单例保存 UI 状态。快照中先按 Retained Size 排序再沿引用链找到 GC Root。aboutToAppear(){this.unsubscribeeventBus.on(assetChanged,this.onAssetChanged)}aboutToDisappear(){this.unsubscribe?.()this.unsubscribeundefinedthis.previewPixelMap?.release()this.previewPixelMapundefined}只把字段赋值为undefined不一定足够Native 资源还需要调用明确释放接口。七、句柄和线程泄漏同样危险文件导入、数据库、Socket 和事件对象都消耗句柄工作线程、解码线程与 Web 线程可能在页面退出后继续存在。系统资源泄漏检测会周期采样并在超过阈值时生成日志但项目不应等到系统管控才修复。为每个入口写压力测试检查打开与关闭次数是否成对。网络失败、取消选择和异常返回路径尤其容易漏掉close。asyncfunctionwithFileT(uri:string,action:(fd:number)PromiseT){constfileawaitfileService.open(uri)try{returnawaitaction(file.fd)}finally{awaitfileService.close(file)}}八、GPU 与大图需要独立观察图片页面可能出现 ArkTS 对象数量稳定但 GPU 内存不断增长。检查纹理缓存、离屏渲染、动画图帧缓存和未释放的 PixelMap。为缓存设置条目数与字节双上限并在后台、低内存与账号切换时清理。如果问题只在特定分辨率或窗口尺寸出现要把输入尺寸、色彩空间、HDR 和缩放策略加入复现记录。九、修复必须通过多轮回落证明修复后用同一构建类型、同一设备、同一数据和同一脚本重复测试。比较的不是最后一张截图而是每轮结束后的稳定基线斜率。functionbaselineSlope(samples:MemorySample[]):number{constaftersamples.filter(xx.phaseafter-gc)if(after.length2)return0return(after.at(-1)!.rssKb-after[0].rssKb)/(after.length-1)}合理缓存可能使第一轮升高之后趋于平台真正泄漏通常保持正斜率。十、上线门禁固定复现脚本与采样阶段hiprofiler 时间线包含业务 Markerhidumper 同时覆盖 ArkTS、Native、GPU 与句柄每类重资源都有所有权和释放时机异常、取消、后台路径都验证释放修复后至少重复 20 轮观察基线回落诊断文件不包含不必要的用户数据。结语复杂应用的内存是一组相互关联的资源域。hiprofiler 负责告诉我们“增长发生在何时和何处”hidumper 帮助比较关键快照业务所有权表则把工具证据落到具体修复。只有跨堆观察并用重复回落证明才能真正关闭泄漏问题。官方参考Resource Leak 检测https://developer.huawei.com/consumer/cn/doc/doccenter-capabilities/resource-leak-guidelines2026 年 7 月开发者月刊https://developer.huawei.com/consumer/cn/monthly/202607