真机 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)。正式部署留主会话。
78 lines
3.0 KiB
C
78 lines
3.0 KiB
C
/* bench/mem_sim.c — 宿主内存测量 harness(OOM 瘦身验证)。
|
||
*
|
||
* 目的:把 ncm 相关块的匿名 RSS(RssAnon)拆开,验证封面降采样(meow_img_downscale)收益。
|
||
* 依赖:仅 host SDK 对象(meow_ui_init 装字库 + meow_img 解码),无需 App/core 对象。
|
||
* 用法:MEM_SIM=1 ./ncm_host
|
||
*
|
||
* 场景(各阶段 RssAnon,KB):
|
||
* [0] meow_ui_init 后基线(含字库 plane + back_buf + 启动堆)。
|
||
* [1] meow_img_load_file(全尺寸封面 1448x1448) —— 全尺寸 RGBA ≈ 8MB 驻留。
|
||
* [2] meow_img_downscale(480) + free 原图 —— RGBA 降到 ≤480x480 ≈ 0.9MB。
|
||
* 断言:RssAnon[1]-RssAnon[0] > 2MB(大封面确实驻留),RssAnon[2] < RssAnon[1]-4MB
|
||
* (降采样省 >4MB,可验证)。
|
||
*/
|
||
#include "../app/ncm_app_internal.h"
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
|
||
static long rss_anon_kb(void)
|
||
{
|
||
FILE *f = fopen("/proc/self/status", "r");
|
||
if (!f) return -1;
|
||
char line[256];
|
||
long v = -1;
|
||
while (fgets(line, sizeof line, f))
|
||
if (strncmp(line, "RssAnon:", 8) == 0) { v = atol(line + 8); break; }
|
||
fclose(f);
|
||
return v;
|
||
}
|
||
|
||
static int mem_sim_run(void)
|
||
{
|
||
meow_ui_opts o = { APP_W, APP_H };
|
||
if (meow_ui_init(&o) != 0) { printf("mem: meow_ui_init FAILED\n"); return 1; }
|
||
|
||
long r0 = rss_anon_kb();
|
||
printf("mem[0] baseline (font plane + back_buf + startup): RssAnon=%ldKB\n", r0);
|
||
if (r0 < 0) { printf("mem: cannot read RssAnon\n"); return 1; }
|
||
|
||
const char *cover = "/tmp/ncmfont/cover_current.jpg";
|
||
if (access(cover, F_OK) != 0) {
|
||
printf("mem: warning: %s not found; skip cover scenario\n", cover);
|
||
} else {
|
||
meow_img *f0 = meow_img_load_file(cover);
|
||
if (!f0) { printf("mem: cover load FAILED\n"); return 1; }
|
||
long r1 = rss_anon_kb();
|
||
printf("mem[1] cover full-res %dx%d loaded: RssAnon=%ldKB (delta=%ldKB)\n",
|
||
meow_img_w(f0), meow_img_h(f0), r1, r1 - r0);
|
||
|
||
meow_img *small = meow_img_downscale(f0, 480);
|
||
if (small) meow_img_free(f0);
|
||
long r2 = rss_anon_kb();
|
||
int w = small ? meow_img_w(small) : (f0 ? meow_img_w(f0) : 0);
|
||
int h = small ? meow_img_h(small) : (f0 ? meow_img_h(f0) : 0);
|
||
printf("mem[2] cover downscaled to %dx%d: RssAnon=%ldKB (delta_from_full=%ldKB)\n",
|
||
w, h, r2, r2 - r1);
|
||
|
||
int ok = (r1 - r0 > 2048) && (r1 - r2 > 4096) && (small != NULL) &&
|
||
(w <= 480 && h <= 480);
|
||
printf("mem: cover-downscale %s (full_delta=%ldKB, saved=%ldKB, size=%dx%d)\n",
|
||
ok ? "PASS" : "FAIL", r1 - r0, r1 - r2, w, h);
|
||
if (small) meow_img_free(small);
|
||
}
|
||
|
||
meow_ui_shutdown();
|
||
printf("mem: done\n");
|
||
return 0;
|
||
}
|
||
|
||
int main(void)
|
||
{
|
||
if (getenv("MEM_SIM") && getenv("MEM_SIM")[0] == '1') return mem_sim_run();
|
||
/* 未设 MEM_SIM:宿主页面测试走 test_ncm_app.c 的 driver(本文件被链时只占位)。 */
|
||
printf("mem_sim: set MEM_SIM=1 to run memory scenarios\n");
|
||
return 0;
|
||
}
|