# 诊断工作流与 AI 调用

## 1. 内存不足或大块分配失败

先获取事实，不要先猜测泄漏，不要通过清理工作集改变现场。

```aardio
import process.memoryMap;
var mm = process.memoryMap;
var report,err = mm.diagnose(,{
    requestBytes = 128 * 1048576;
    resolveNames = true;
    top = 5;
});
if(!report) return {error=err};
return {text=mm.format(report); request=report.request; findings=report.findings};
```

顺序：

1. 核对 `target.pid` 和 `collectorPid`。
2. 检查 `complete`、`stopReason`、`scanRange.fullAddressSpace`。
3. 看 `request.status`；未发现时再区分总量不足、碎片和对齐限制。
4. 看分配榜单，确定地址空间主要分布在哪里。
5. 将区域提交量与 `counters` 分开理解。候选存在仍可能因系统提交限额、配额、堆内部机制等原因分配失败。

## 2. 保存操作前后的快照

下面两个脚本用于独立采集进程，启动参数 `--pid=目标PID` 必须明确指定。样例路径位于采集程序的应用目录下。

操作前：

```aardio
import process.memoryMap;
import JSON;
var pid = tonumber(_ARGV.pid);
if(!pid) return {error="请指定 --pid=目标PID，不能省略目标。"};
var before,err = process.memoryMap.snapshot(pid);
if(!before) return {error=err};
if(!before.complete) return {error="扫描不完整"; detail=before.stopReason};
var ok = JSON.save("/memory-diagnostics/before.json",before,true);
return {saved=ok; target=before.target};
```

完成需要观察的操作后：

```aardio
import process.memoryMap;
import JSON;
var mm = process.memoryMap;
var pid = tonumber(_ARGV.pid);
if(!pid) return {error="请指定 --pid=目标PID。"};
var before,err = JSON.load("/memory-diagnostics/before.json");
if(!before) return {error=err};
var after,err = mm.snapshot(pid);
if(!after) return {error=err};
var delta,err = mm.diff(before,after,{top=10});
if(!delta) return {error=err};
JSON.save("/memory-diagnostics/after.json",after,true);
JSON.save("/memory-diagnostics/diff.json",delta,true);
return {text=mm.format(delta); delta=delta.delta};
```

加载器、线程池、缓存和运行库可能延迟释放资源。要排查增长，建议观察：基线 → 操作一次 → 释放 → 重复多次 → 等待稳定。**持续增长是线索，不是泄漏证明。**

若必须在目标内采集，第二次快照会包含第一份快照仍驻留所造成的影响。库会提示 `SELF_OBSERVATION`；不要把快照对象自身误认为业务泄漏。

## 3. 离线重看同一现场

```aardio
import process.memoryMap;
import JSON;
var saved,err = JSON.load("/memory-diagnostics/before.json");
if(!saved) return {error=err};
var report,err = process.memoryMap.analyze(saved,{
    requestBytes = 64 * 1048576;
    top = 8;
});
if(!report) return {error=err};
return process.memoryMap.format(report);
```

更改分析选项不重新扫描目标，因此可用同一份快照分别评估 64 MiB、128 MiB 等请求。

## 4. 解释错误日志中的地址

```aardio
import process.memoryMap;
var pid = tonumber(_ARGV.pid);
var address = tonumber(_ARGV.address);
if(!pid || address===null) return {error="请提供 --pid 和 --address。"};
var info,err = process.memoryMap.query(pid,address,{resolveNames=true});
if(!info) return {error=err};
return {text=process.memoryMap.format(info); detail=info};
```

这里不解引用地址，不触发 PAGE_GUARD。查询结果也不保证之后能安全读取该地址。

## 5. Autos 的 execute_code process 模式

- process 模式创建独立进程。省略目标调用 `diagnose()`，诊断的就是**这个新进程**。
- 要看 Autos 宿主，先在宿主取得 `GetCurrentProcessId()`，再将该 PID 显式传给子进程。
- process 模式不自动收集 `return`，必须显式写入文件或通过 IPC 回传；不要假设工具会自动回传报告。
- 跨工具使用文件时注意应用基准目录：建议独立采集代码指定 `appBaseDirectory="/"`，让代码内的 `/文件` 与工具读取的工作区 `/文件` 对应。

可在子进程运行的采集脚本（启动时传 `--pid`、`--output`）：

```aardio
import process.memoryMap;
import JSON;
var pid = tonumber(_ARGV.pid);
var output = _ARGV.output;
if(!pid || !#output) return;
var report,err = process.memoryMap.diagnose(pid,{top=5});
JSON.save(output,{report=report; error=err},true);
```

报告包含实际 `target.pid`，接收端仍应核对目标与创建时间，不能只根据文件名推测诊断对象。

## 6. 给 AI 的检索描述

可把下列短描述加入自己的库清单或工具知识索引；不需要修改基础 `process`：

> process.memoryMap：进程内存诊断。排查内存不足、连续分配失败、虚拟地址空间碎片、保留区过大及内存增长；支持当前/指定 x86 进程、LAA 高地址、保护页分配、快照对比。首先查询库参考，再用 diagnose；保存现场用 snapshot。只查询元信息，不读写内存内容。

不需要安装多个含义相近的别名库，也不要依赖某个固定进程 PID 或某次扫描的统计值。
