fix(ncm §32): 内存瘦身修 OOM 被杀 —— 封面降采样(8.28MB→0.78MB) + 瞬态 rbuf 缩减 + 线程栈显式
真机 dmesg 实锤:OOM Kill ncm (score 460, anon-rss 26.9MB, 设备 56MB)。 画像:封面全分辨率 RGBA 8.28MB(1448x1448 原生解码驻留) 是最大可控块。 瘦身(按收益排序): 1. sdk meow_ui_img 新增纯增量 meow_img_downscale + cover.c cover_cap(≤480px) → 封面 8.28MB→0.78MB,-7.65MB(mem_sim 实测 PASS)。 2. ncm_api.c 瞬态响应 rbuf:song_url→64KB、lyric/song_detail/cloudsearch/user_playlist→256KB (detail/track_all 保 1MB)。 3. ncm_app_internal.h 新增 ncm_thread_create(显式 128KB 栈),替换全部 14 处 pthread_create。 4. 滑动窗口/meta 复核零回退(window_sim:608B/首,6000 首 280KB 恒定)。 验证:mem_sim 封面收益 PASS + host home/player 渲染 OK + stream_sim/player_flow_sim/ window_sim/search_sim/cache_evict_sim 全 PASS + test_ncm_core host+mipsel(qemu) PASS + build_ncm.sh -Wall -Wextra 0 warning。真机 scp 播放在跑确认(缓存曲,0 播放请求)。 新 ncm md5 44fa16fe(text 1015150/bss 1362500)。正式部署留主会话。
This commit is contained in:
1 parent
202caaf66b
commit
68ce46a5d8
19 files changed
+368
-19
No files matched your search
@@ -2724,3 +2724,85 @@ de4c5e1939c7571b90f75a80f48236c0 build_ncm_host.sh # SDK_SRC 补 meow_
|
||||
§20.3 档位链语义本身的验证属主会话(297 队列项)。
|
||||
- **bss +~95KB**:`s_pls[NCM_PLAYLIST_MAX]`(120×808 ≈ 95KB)staging,与既存 `s_build[16384]`
|
||||
(128KB) 同口径;设备 RAM 56MB 可承受(总 bss 1.36MB)。
|
||||
|
||||
## 32. 内存瘦身:真机 OOM 被杀修复 —— 封面降采样 + 瞬态缓冲缩减(2026-09-02,agent-308)
|
||||
|
||||
> 范围:`patch_v2/ncm_app/` + `patch_v2/sdk/meow_ui_img.c/.h`(新增一个纯增量 downscale API)。
|
||||
> 风控:真机验证用 autoplay 播**已缓存**曲目(0 播放请求);HOME 歌单列表走盘缓存
|
||||
> (`playlists.bin`,§26),首启一次网络刷新(少量真实请求,任务允许)。
|
||||
|
||||
### 32.1 动机(真机 dmesg 实锤)
|
||||
|
||||
2026-09-02 02:56 设备内核 OOM:`Out of memory: Kill process 1151 (ncm) score 460`,
|
||||
ncm `total-vm 97MB / anon-rss 26.9MB`,设备 56MB 总内存(系统+服务占完可用 ~20MB)。
|
||||
launcher `app_launcher.c:1647` 已有 OOM 护栏(`MemAvailable<24MB` → 大字库降 common),
|
||||
说明系统侧早已见过该类压力。本批把 ncm 的匿名 RSS 拆清算清,并把能砍的砍到常态 ≤16MB。
|
||||
|
||||
### 32.2 内存画像(拆到每块,宿主 mem_sim + 设备实测 + 源码审计)
|
||||
|
||||
| 块 | 实测/审计 | 说明 |
|
||||
|---|---|---|
|
||||
| **封面 RGBA(大头)** | 1448×1448 → **8.28MB**(mem_sim 实测 RssAnon 增量 8484KB) | `meow_img_load_file` 用 stbi 按**原生分辨率**解码为 RGBA 并驻留(`g_cover_img`)。网易云全尺寸封面即此规模。 |
|
||||
| 字库(fonts=common 档) | plane **2.44MB**(`default/regular/font.png` 1280×3996 depth4 灰度)+glyphs ~130KB | app.json `fonts:"common"`,launcher 注入 `MEOW_FONT_TIER=0`。plane 懒触达(绘制 glyph 才换页)。GBK 档约 17MB(launcher 注释),common 远小。 |
|
||||
| bss 静态数组 | **1.36MB** | `song_ids[16384]`128KB + `songs[256]`152KB + `search_songs[256]`156KB + `playlists[120]` + `qr_mods` + … |
|
||||
| back_buf(SDK) | **0.69MB** | 480×720×2(16bpp,mmap fb 之外仍 heap 分配一份 `g_back_buf`)。 |
|
||||
| 线程栈 | musl 静态默认 **128KB/线程** × ~5-8 线程 ≈ 0.6-1MB | 非 glibc 8MB/thread;实测调用链栈深 ≤~30KB。 |
|
||||
| mbedtls(每连接瞬态) | in/out 各 16KB(默认)+ CA bundle 解析 ~440KB | 每 `http_run` 加载 182KB CA + 解析 + 32KB ssl。播放+封面并发 ~2-3 连接。 |
|
||||
| API 响应 rbuf(瞬态) | 旧每 `api_post` 固定 **1MB** | song_url/lyric/song_detail/cloudsearch 响应实际 ≤100KB,1MB 严重超额;并发几 × 1MB 是可砍峰值。 |
|
||||
|
||||
**结论**:真正的大头是**封面全分辨率 RGBA(8.28MB)**,其次瞬态 1MB rbuf。字库(common 2.44MB)
|
||||
与 bss(1.36MB)不可由 ncm 轻易再砍(字库为系统字体档,bss 已是 §17 瘦身后)。
|
||||
|
||||
### 32.3 瘦身(按收益排序)
|
||||
|
||||
1. **封面降采样(-7.65MB)**:`patch_v2/sdk/meow_ui_img.c` 新增纯增量 `meow_img_downscale(img,maxdim)`
|
||||
(最近邻等比缩放到最长边 ≤maxdim,复用既有 `scale_buf`);声明进 `include/meow_ui_image.h`。
|
||||
`cover.c` 新增 `cover_cap()`(`NCM_COVER_DECODE_MAX=480`)在缓存命中/下载解码后统一降采样,
|
||||
释放原大图驻留小图。播放页黑胶方图 + 歌词页模糊铺底仅需 ≤480px,全尺寸属浪费。
|
||||
2. **瞬态 API rbuf 缩减**:`ncm_api.c` 新增 `RESP_SMALL(64KB)/RESP_MED(256KB)`——
|
||||
song_url→64KB、lyric/song_detail/cloudsearch/user_playlist→256KB;仅
|
||||
`playlist/detail`、`track/all`(全量 trackIds ≤16384)保留 1MB。
|
||||
3. **线程栈显式**:`ncm_app_internal.h` 新增 `ncm_thread_create()`(`pthread_attr_setstacksize` 128KB),
|
||||
替换全部 14 处 `pthread_create`。musl 默认即 128KB(本设备 0 收益),显式声明防未来
|
||||
libc/平台默认变大(如宿主 glibc 8MB/thread),并满足「按实际用量调小」要求。
|
||||
4. **滑动窗口/meta 复核**:`window_sim` 重跑确认零回退——`ncm_song_t`=608B(旧 1324B)、
|
||||
窗口=155904B(256 首)、trackIds 索引=131072B(16384 首);6000 首场景旧 1292KB→新 280KB(恒定)。
|
||||
|
||||
### 32.4 验证记录
|
||||
|
||||
| 项 | 方式 | 结果 |
|
||||
|---|---|---|
|
||||
| 封面收益 | **mem_sim**(新 bench,链 host SDK):init 基线 → 载全尺寸封面 → downscale 480 | **PASS**:全尺寸 RssAnon +8484KB → 降采样后 -7836KB(8.28MB→0.78MB),尺寸 480×480 |
|
||||
| 宿主渲染回归 | build_ncm_host_mem.sh + NCM_PAGE=home/player MEOW_UI_DUMP | rc=0、两页渲染正常(SDK img 改动无回归) |
|
||||
| 播放链路回归 | stream_sim 全矩阵 + resume / player_flow_sim P1-P12 | **ALL PASS** |
|
||||
| 大歌单/搜索/缓存 | window_sim / search_sim / cache_evict_sim | **ALL PASS**(含 6000 首滑动窗口内存断言、搜索分页、LRU 防淘汰+7 天回收) |
|
||||
| core 回归 | build_core.sh → test_ncm_core_host + qemu test_ncm_core_mipsel | **PASS**(host + mipsel+qemu) |
|
||||
| mipsel 构建 | build_ncm.sh(自有代码 -Wall -Wextra) | **0 warning**(set -e 下任何告警即失败) |
|
||||
| 真机播放 | autoplay 播已缓存曲(新 ncm 已上卡) | 音频开流/播放正常(log `play: start … audiod open ok`);常驻 ~6MB(HOME 不触发封面,封面收益由 mem_sim 证明) |
|
||||
|
||||
**真机峰值说明(诚实)**:裸启 ncm(不经 launcher)在拖入会话后偶收 GTP 复位产生的幽灵左滑 → `exit:swipe`
|
||||
退出,无法做长时驻留采样;封面在设备上的运行时 RSS 收益以宿主 mem_sim 的逐字节实测为准
|
||||
(封面解码路径 `meow_img_load_file` 宿主/设备同源,差异仅在字库背板)。
|
||||
|
||||
### 32.5 md5(本批产物)
|
||||
|
||||
```
|
||||
44fa16feba8e597d7dbe9535983f2629 ncm # mipsel 静态 App(text 1015150 / bss 1362500;未部署留主会话,仅真机播放在跑确认)
|
||||
34be096f196aa24b755629bd43a543f7 ncm_host # 宿主离屏二进制(重链)
|
||||
a9842284ecf9529ac1c39a9119561a20 mem_sim # 宿主内存测量 harness
|
||||
(REPORT §32;sdk/meow_ui_img.c + include/meow_ui_image.h 变更见 git)
|
||||
```
|
||||
|
||||
### 32.6 诚实出入 / 遗留
|
||||
|
||||
- **未部署**:新 ncm 已 scp 到设备 `/usr/data/mnt/sd_0/MeowAPPs/dev.player.ncm/ncm` 做真机播放在跑确认,
|
||||
正式部署/固件打包留主会话统一。
|
||||
- **字库(common 2.44MB)本批未动**:属系统字体档位,由 launcher 按 `MemAvailable` 护栏决定;
|
||||
ncm 无法(也不应)自行缩减。若需更低,只能走「GBK/Full」降档之外的字体裁剪(另立批)。
|
||||
- **mbedtls in/out(16KB/16KB)未缩**:改 `MBEDTLS_SSL_OUT_CONTENT_LEN` 需重编 mbedtls,收益 ~12KB/连接,
|
||||
低于风险,留主会话。
|
||||
- **封面 downscale 只作用于封面**:SDK `meow_img_downscale` 为纯增量 API,未改动其它 App 的图片路径
|
||||
(reader/hello/files 不引入)。若后续发现其它 App 大图驻留,可复用同一 API。
|
||||
- **真机长期峰值**:幽灵左滑导致无法持续采样,设备端「≤16MB」是「基线 ~6MB + 封面 0.78MB + 字库
|
||||
2.44MB」的推演上限(约 8-9MB),低于 16MB 目标;正式部署后建议主会话做一次带 launcher 的
|
||||
前台三场景采样复核。
|
||||
Reference in new issue
Block a user