- M7 launcher 重写 5 期(虚拟化宫格/meow_theme 单一权威/横幅动画/自定义 PIN 键盘) - OOM 通用化(cachegov 上收 SDK)、自动切歌根治、meowpanel jv_free 泄漏修复、Hello 滚动卡顿修复 - ncm 歌词 UI / 媒体通知封面 / 封面分辨率 640 - 5 bug 修复:ncm 后台化 UI 叠层+点击穿透、再进 ncm 桌面叠层、播放页新旧 UI 叠层抢刷脏区(meow_ui_gfx 恢复边沿整帧重画)、PIN 亮屏亮度跳(keys.c meow_panel_on 按 settings_brightness_clamped 恢复)、通知中心封面显歌单封面(cover.c save_cover_raw 加 is_song + 命中块守卫) - 四 App 统一重链新 meow_ui.a 51caee4a;M6.19=0.8.19 固件 2d2331f2 推卡自刷验收全绿
121 lines
5.2 KiB
C
121 lines
5.2 KiB
C
/* bench/mem_release_sim.c — 宿主「彻底释放」路径验证(agent 32bit OOM 专项)。
|
||
*
|
||
* 目的:验证「32bit(>16bit)→S32 解码 播完/切歌 是否真正释放」——ncm_dec_open(整文件)→
|
||
* ncm_dec_read 全量(dr_flac S32 满幅路径)→ ncm_dec_close(dr_flac_close + stream_src_close)
|
||
* 循环 N 次,断言进程匿名 RSS(RssAnon,OOM 高危口径)**不单调累积**(播完回落基线),
|
||
* 且解码中峰值有界(32bit 解码缓冲存在但有限,非 40MB 级)。
|
||
*
|
||
* 依赖:仅 app/play 解码层(decoder.c + stream_src.c + dr_flac_impl + minimp3_impl),
|
||
* 无 core/SDK/app.c——本 sim 是解码链路的最小区块,直接量「解码器 buff 播完 free」。
|
||
* 编译(ncm_app 目录下):
|
||
* gcc -O2 -Wall -Wextra -DJSMN_HEADER -I. -Icore -I../sdk -I../meow_launcherd \
|
||
* -Ivendor/jsmn -Ivendor/minimp3 -Ivendor/dr_flac -Ivendor/mbedtls/include \
|
||
* -c bench/mem_release_sim.c -o /tmp/mr.o
|
||
* gcc -O2 -Wall -Wextra ... -c app/play/stream_src.c -o /tmp/mr_ss.o
|
||
* gcc -O2 -Wall -Wextra ... -c app/play/decoder.c -o /tmp/mr_dec.o
|
||
* gcc -O2 -c -Ivendor/minimp3 app/play/minimp3_impl.c -o /tmp/mr_mp3.o
|
||
* gcc -O2 -c -Ivendor/dr_flac app/play/dr_flac_impl.c -o /tmp/mr_flac.o
|
||
* gcc -O2 -o mem_release_sim /tmp/mr.o /tmp/mr_ss.o /tmp/mr_dec.o /tmp/mr_mp3.o /tmp/mr_flac.o -lpthread -lm
|
||
* 运行:./mem_release_sim <flac 24bit 路径> [iters] (iters 默认 5)
|
||
* 断言(PASS 才 exit 0):
|
||
* - RssAnon[最后] - RssAnon[基准] < 256KB(播完回落,无累积);
|
||
* - 解码中峰值有界(peak - 基准 < 8MB,32bit 解码缓冲不是 40MB 级);
|
||
* - 总帧数 > 0 且 bits==32(确实走了 S32 满幅路径——本 sim 只受 24bit 输入触发)。
|
||
*/
|
||
#include "../app/play/decoder.h"
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
|
||
#define READ_CHUNK_FRAMES 4096
|
||
#define ITER_DEFAULT 5
|
||
#define SETTLE_TOLERANCE_KB (256) /* 播完回落允许抖动(<256KB 视为无累积) */
|
||
#define PEAK_BOUND_KB (8 * 1024) /* 解码中峰值必须 <8MB(区别于 40MB 级异常) */
|
||
|
||
/* 静默 meow_log(本 sim 不链 core;decoder/stream_src 不调它,仅占位防漏链) */
|
||
void meow_log(int lvl, const char *fmt, ...) { (void)lvl; (void)fmt; }
|
||
|
||
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)) { v = atol(line + 8); break; }
|
||
fclose(f);
|
||
return v;
|
||
}
|
||
|
||
int main(int argc, char **argv)
|
||
{
|
||
if (argc < 2) {
|
||
printf("usage: mem_release_sim <flac_path> [iters]\n");
|
||
return 2;
|
||
}
|
||
const char *path = argv[1];
|
||
int iters = (argc > 2) ? atoi(argv[2]) : ITER_DEFAULT;
|
||
if (iters < 2) iters = 2;
|
||
|
||
long base = rss_anon_kb();
|
||
if (base < 0) { printf("FAIL cannot read RssAnon\n"); return 1; }
|
||
printf("mem_release[0] baseline RssAnon=%ldKB\n", base);
|
||
|
||
int first_dec_ok = 0;
|
||
long prev_after = 0, last_after = 0; /* 最近两次播完 close 后的 RssAnon */
|
||
for (int i = 0; i < iters; i++) {
|
||
ncm_decoder_t *dec = NULL;
|
||
int rate = 0, ch = 0, bits = 0;
|
||
int64_t tf = 0;
|
||
if (ncm_dec_open(&dec, path, &rate, &ch, &bits, &tf) != 0) {
|
||
printf("FAIL iter%d ncm_dec_open (%s)\n", i, path);
|
||
return 1;
|
||
}
|
||
if (i == 0) {
|
||
printf("mem_release: fmt=%s %dHz/%dch/%dbit total_frames=%lld (S32 path=%d)\n",
|
||
ncm_dec_format(dec), rate, ch, bits, (long long)tf, bits > 16);
|
||
first_dec_ok = 1;
|
||
}
|
||
|
||
/* 全量读(S32 满幅路径),测解码中匿名峰值 */
|
||
static int32_t buf[READ_CHUNK_FRAMES * 2];
|
||
long peak = 0;
|
||
int64_t frames = 0, got = 0;
|
||
do {
|
||
got = ncm_dec_read(dec, buf, READ_CHUNK_FRAMES);
|
||
frames += got;
|
||
long r = rss_anon_kb();
|
||
if (r > peak) peak = r;
|
||
} while (got > 0);
|
||
|
||
printf("mem_release[%d] after decode: frames=%lld peak_RssAnon=%ldKB\n",
|
||
i + 1, (long long)frames, peak);
|
||
|
||
ncm_dec_close(dec); /* drflac_close + stream_src_close(整文件静态源) */
|
||
long r = rss_anon_kb();
|
||
prev_after = last_after;
|
||
last_after = r;
|
||
printf("mem_release[%d] after close RssAnon=%ldKB (delta=%ldKB)\n",
|
||
i + 1, r, r - base);
|
||
|
||
/* 解码中峰值有界:32bit 解码缓冲不是 40MB 级 */
|
||
if (peak - base > PEAK_BOUND_KB) {
|
||
printf("FAIL iter%d decode peak %ldKB - base %ldKB = %ldKB > %dKB (异常高)\n",
|
||
i, peak, base, peak - base, PEAK_BOUND_KB);
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
/* 累积断言:最后两次播完后的 RssAnon 相对基线的增量都 < 容忍(无单调上升) */
|
||
long d1 = last_after - base;
|
||
long d2 = prev_after - base;
|
||
int no_accum = (d1 < SETTLE_TOLERANCE_KB) && (d2 < SETTLE_TOLERANCE_KB);
|
||
printf("mem_release: settle delta last=%ldKB prev=%ldKB -> %s\n",
|
||
d1, d2, no_accum ? "PASS(无累积)" : "FAIL(有残留)");
|
||
|
||
int ok = first_dec_ok && no_accum;
|
||
printf("mem_release: %s\n", ok ? "PASS" : "FAIL");
|
||
return ok ? 0 : 1;
|
||
}
|