真机真实布局暴露两处问题(评审 P1):
- Books/400+本高质量完本合集/<分类>/<作品>/<书名>.txt 在 depth 3-4,旧 depth≤2 让 413 本 3.8GB 不可见
→ SHELF_SCAN_MAX_DEPTH=2→6;report 新增 depth_skipped,超深书籍文件计数并在 g_notice 可见提示
(有 N 个文件因目录层数超过 6 层未显示),不再静默
- 按完整相对路径分组会把 413 本书炸成 410 个每条 1 书的段头
→ 分组键改为 Books/ 第一级目录(shelf_book.top);完整相对路径仍在 group[],
第一级之后的子路径(分类/作品)放进副题 sub(如 01、玄幻/01、斗破 · TXT · 2.1MB)
→ 真机书库只剩 3 组:400+本高质量完本合集 / kh / 轻小说
- 单测 50 断言:depth3/4 收录、depth7 计入 depth_skipped、四种真实路径的组名、
a/b 与 a/c 同组 a、副题含子路径、format 回归、根组未分类、path/进度不变
80 lines
3.3 KiB
C
80 lines
3.3 KiB
C
/* test/shelf_scan_bench.c — M27 扫描/排队计时(宿主 + 设备通用,纯 C)。
|
|
*
|
|
* 用法:./shelf_scan_bench <Books目录> [progress|noop] [轮数]
|
|
* progress = 每本书调 rdprog_load(生产路径,含 rdprog_dir 的 mkdir 循环 + fopen);
|
|
* noop = 不读进度(基线,只测 readdir/stat/快照)。
|
|
* 进度目录由 MEOW_DATA_DIR 决定(同 App:剥 /data → .../progress);未设则 /tmp/m27bench_data。
|
|
* 输出每轮 scan / build_rows(format+folder) 毫秒,末行 RESULT 汇总 min/avg。
|
|
*/
|
|
#include "shelf_model.h"
|
|
#include "progress.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
|
|
static char g_cfgdir[400];
|
|
const char *meow_config_dir(void) { return g_cfgdir; }
|
|
|
|
static shelf_book g_books[SHELF_MAX_BOOKS];
|
|
static shelf_row g_rows[SHELF_MAX_ROWS];
|
|
|
|
static uint64_t ts_of(const char *path)
|
|
{
|
|
rdprog p;
|
|
return rdprog_load(path, &p) == 1 ? p.ts : 0;
|
|
}
|
|
|
|
/* 取时用 /proc/uptime(整数、10ms 分辨率):zig mipsel musl 的 time64 ABI 在真机上
|
|
* 会让 clock_gettime/gettimeofday 的 timespec/timeval 布局失配(见 sdk/CLOCK_ABI.md),
|
|
* 且静态链接下浮点打印也不可靠 —— 全程只用整数微秒。 */
|
|
static int64_t now_us(void)
|
|
{
|
|
FILE *f = fopen("/proc/uptime", "r");
|
|
if (!f) return 0;
|
|
long sec = 0, cs = 0;
|
|
if (fscanf(f, "%ld.%ld", &sec, &cs) != 2) cs = 0;
|
|
fclose(f);
|
|
return (int64_t)sec * 1000000 + (int64_t)cs * 10000;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (argc < 2) {
|
|
fprintf(stderr, "用法: %s <Books目录> [progress|noop] [轮数]\n", argv[0]);
|
|
return 2;
|
|
}
|
|
const char *root = argv[1];
|
|
int use_prog = (argc > 2 && strcmp(argv[2], "progress") == 0);
|
|
int reps = (argc > 3) ? atoi(argv[3]) : 5;
|
|
if (reps < 1) reps = 1;
|
|
|
|
const char *env = getenv("MEOW_DATA_DIR");
|
|
snprintf(g_cfgdir, sizeof g_cfgdir, "%s", (env && env[0]) ? env : "/tmp/m27bench_data");
|
|
|
|
int n = 0, rows_f = 0, rows_d = 0, trunc = 0, skipped = 0;
|
|
int64_t best_scan = INT64_MAX, best_build = INT64_MAX, sum_scan = 0;
|
|
for (int r = 0; r < reps; r++) {
|
|
shelf_scan_report rep;
|
|
int64_t t0 = now_us();
|
|
n = shelf_scan_books(root, g_books, SHELF_MAX_BOOKS, use_prog ? ts_of : NULL, &rep);
|
|
int64_t t1 = now_us();
|
|
rows_f = shelf_build_rows(g_books, n, 0, g_rows, SHELF_MAX_ROWS);
|
|
rows_d = shelf_build_rows(g_books, n, 1, g_rows, SHELF_MAX_ROWS);
|
|
int64_t t2 = now_us();
|
|
int64_t s = t1 - t0, b = t2 - t1;
|
|
trunc = rep.truncated;
|
|
skipped = rep.depth_skipped;
|
|
sum_scan += s;
|
|
if (s < best_scan) best_scan = s;
|
|
if (b < best_build) best_build = b;
|
|
printf("run %d: scan %lld us, build_rows(format+folder) %lld us, books=%d rows_f=%d rows_d=%d trunc=%d skip=%d\n",
|
|
r + 1, (long long)s, (long long)b, n, rows_f, rows_d, rep.truncated, rep.depth_skipped);
|
|
}
|
|
printf("RESULT root=%s mode=%s reps=%d books=%d trunc=%d rows_format=%d rows_folder=%d "
|
|
"scan_min=%lldus scan_avg=%lldus build_min=%lldus depth_skipped=%d\n",
|
|
root, use_prog ? "progress" : "noop", reps, n, trunc, rows_f, rows_d,
|
|
(long long)best_scan, (long long)(sum_scan / reps), (long long)best_build, skipped);
|
|
return 0;
|
|
}
|