内存与设备证据

端侧 AI GC 压力测量:区分 ART 回收与原生内存

用一条时间线关联 GC、对象分配、任务阶段与 native/process 内存指标。

审核状态: 内容已校验;中文稿供用户审核 · 2026-10-04 · Fact IDs: MEMORY-01, BENCHMARK-01

直接回答

垃圾回收压力可能是本地 AI 流程暂停的一个原因,但推理附近出现 GC 事件,并不能证明模型导致暂停。应在同一时间线上记录托管分配、回收事件、任务时间戳及原生/进程内存。Android 内存文档描述 ART 托管堆和分代回收,也说明进程总内存还包括 Java/Kotlin、native、图形、共享等部分。LiteRT-LM 或其他原生运行时可能在托管堆之外分配,因此 Java heap 安静不代表进程总内存很低,GC 事件也不自动等于响应变慢的根因。 选择代表性固定工作负载,记录制品/运行时身份、应用构建、设备与系统、输入夹具、媒体预处理和生命周期。采集基线、任务开始、任务前后分配、GC 时间或 profiler 事件、完成、取消和清理。使用 Android Studio Memory Profiler 或其他明确命名的系统工具。指标要具体:Java/Kotlin heap 分配、native heap、PSS、RSS 或 GC 次数不能互换。工具无法观察运行时内部 native 分配时,应标出证据缺口,而不能按文件长度估算。 设计实验区分分配 churn 与持续保留。用同一媒体和提示重复同一任务,观察临时字符串、包装对象、复制缓冲或 UI 状态是否逐轮增长。之后一次只改变一个因素,例如图像预处理、转写长度或结果历史。托管分配上升后被回收,与仍驻留的 native 分配、有意缓存或被引用链保留的对象不同。不能在生产调用 System.gc(),也不能未经产品决策清空用户历史来“解决”GC 压力。 将暂停和任务行为对应起来。如果界面卡顿却没有相关 GC 事件,应分别检查主线程工作及原生阻塞。如果 GC 与分配突发重合,用 allocation recording 找出调用点及对象生命周期。如果 managed heap 稳定而进程内存增长,则检查 native 分配、位图、映射/驻留页和共享内存。任务取消时,托管包装对象和 native 资源都应按所有权契约清理。 公开结论只覆盖实际测试范围。项目没有完整真实设备基准集,因此本文是诊断协议,不给出 GC 停顿阈值、模型内存值或延迟主张。保留失败/中断运行、夹具版本、profiler 原始记录和环境条件。有效结论说明某个阶段附近是否观察到 GC、哪些分配点变化、哪些内容仍不可观察,以及恢复测试结果。 重复测试应固定构建和系统条件,避免同时升级 Android、模型及运行时。Profiler 自身采样也会影响操作节奏,所以报告要注明工具和配置。分配量下降不代表进程驻留内存立刻同比下降;已释放对象仍可能留在已提交堆区域。也要区分可由系统回收的共享映射页与仍有强引用的 Bitmap。每项指标都要写明单位和采集层级。 若问题来自临时对象过多,优先检查能否安全复用缓冲、缩短引用持有期或减少不必要的字符串/位图转换,但每项改变都要独立回归。如果证据指向 native 内存或 runtime buffer,就不能把托管分配优化宣传成解决方案。公开内容只写测试方法与测量边界,不提供未经验证的通用调优技巧或“零 GC”承诺。

重复图像分析时页面暂停,但模型内存来源不明

本地视觉应用反复处理同一张合成图片。用户报告暂停,managed heap 曲线上下波动,但原生运行时缓冲和解码位图副本尚未测量。

决策

将 GC 事件、托管分配点、native/进程指标和任务边界关联,再讨论可能原因。

预期结果

团队能把临时分配 churn、托管对象保留、原生内存与主线程阻塞列为不同假设。

需要收集的证据

只有将以下证据与同一模型文件和测试运行关联起来,结论才可复核:

  • MEMORY-01:峰值还受运行时缓冲、张量和分配器影响,下载大小不能推断进程内存。
  • BENCHMARK-01:定量结论需完整设备、制品、运行时、输入、计时、内存和失败原始记录。

设备兼容结论须绑定具体设备、系统、模型、运行时、后端和工作负载,不能靠参数量推测。

实施流程

Connect the allocation trace with the GC event timeline and the task latency sequence in order to record managed allocations, observe collection events, and compare them against observed task execution times, keeping the recorded evidence aligned across these items rather than extending interpretation into areas outside the prompt.

  1. 锁定任务和测量环境. 记录应用、制品、运行时、后端、设备/系统、合成输入、预处理、任务序列和生命周期。每轮复用同一夹具,并保留失败。
  2. 按名称采集托管与进程指标. 用 Android Studio Memory Profiler 或文档工具记录 Java/Kotlin 分配、GC 事件以及可用 native/进程指标。来源和单位分开,不合成一个笼统 RAM 值。
  3. 将 GC 与任务事件对齐. 为请求、预处理、推理、流、渲染、取消和清理打时间戳,再与回收事件对齐。判断暂停是与 GC、主线程工作还是原生阻塞同时发生。
  4. 区分分配 churn 和保留. 记录包装对象、字符串、位图副本及 UI 状态的分配点和生命周期。重复任务检查对象被回收、刻意缓存还是仍被引用;native 内存另行测量。
  5. 改变一个分配来源并回归. 固定模型任务,只改图片尺寸、历史保留或转换策略之一。为有界所有权与清理加断言;不要调用 System.gc() 或删除用户数据走捷径。

验收标准

  • GC、托管堆、native/进程内存与任务时序作为不同指标记录。
  • 卡顿归因有对齐轨迹支持或明确标未确认;时间相近不是因果证据。
  • 重复任务测试区分可回收 churn、引用保留、原生分配和有意缓存。
  • 没有设备原始记录时,不发布通用 GC 阈值、RAM 要求或推理延迟主张。

决策对照表

维度选择或证据解读方式
GC 事件时间线ART 回收时间及托管分配背景说明托管堆回收,不代表涵盖所有 native 或图形内存。
Native/进程内存定义明确的 profiler 或系统指标可揭示非托管增长,不能与 Java heap 或文件大小互换。
任务时序轨迹命名的开始、首输出和结束边界能展示用户可见时间,归因 GC 前还需相关证据。

需要避免的失败模式

  • 看到 GC 与卡顿时间接近就断言推理由 GC 导致。
  • 将 Java heap 稳定理解为 native runtime、位图和图形内存均稳定。

Restate the pitfalls of blaming every pause on the model and ignoring native memory, limiting release wording to the recorded evidence, with the noted boundary identifiers MEMORY-01 and BENCHMARK-01 marking the scope of what has been observed without introducing additional technical nouns, behaviors, or mechanisms beyond what is explicitly supplied.

最小复现记录

层级记录内容
设备厂商、型号、芯片、内存档位、操作系统版本
软件应用版本和 Git 提交号
模型系列、变体、版本、格式、文件长度、摘要、量化方式
运行时名称、版本、请求后端及实际后端证据
工作负载样例版本、输入摘要、提示词摘要、输出策略
结果完成、失败、取消、回退及保护隐私的诊断信息

发布检查表

  • ☐ 主要搜索问题已回答,且没有未经支持的数字。
  • ☐ 所有模型文件和运行时版本均已固定。
  • ☐ 代表性任务和失败处理策略均有说明。
  • ☐ 生命周期、取消、清理和回退均已测试。
  • ☐ 用户内容与网络边界均有说明。
  • ☐ 结论只适用于被记录的配置。
  • ☐ 新增测试结果时链接到原始方法或证据。

来源与相关证据

中文部署与排错专题见。奇连 AI 端侧专题。

常见问题

推理期间出现 GC 是否说明回收导致卡顿?

不能单凭此判断。将 profiler 事件与 UI/native 任务轨迹对齐,再检查暂停是否与阻塞重合。时间关联只是待验证假设;还要检查分配点及对象持有。

Java heap 稳定能证明模型内存稳定吗?

不能。原生运行时缓冲、位图、张量、映射页和共享页可能在托管堆外变化。工具可观测时要分别测量并命名,也记录进程级信号。

每次模型任务后都应调用 System.gc() 吗?

不要把强制回收用作生产清理策略。应正确管理引用和原生资源,再测重复任务;清除用户数据不是内存修复方案,应保留失败轮次。