perf(reader): M31 字体路径记忆化(开书字体查找 35 目录 walk → 1 次 stat)+ 「· 读」徽标即时刷新
字体:find_font_rec/resolve_font 从 reader.c 抽到 app/font_resolve.c 并加进程内记忆化。 只缓存成功路径;命中后仍做一次 access() 校验(字库被删即重扫);没找到不缓存, 用户之后拷入的字库下次开书即可找到。顶栏「刷新」额外调 font_cache_invalidate(), 给「新拷入字库、旧字库仍在」一条显式失效路径。宿主实测:35 目录树 walk 0.026~0.54ms (=300+ 次系统调用)vs 命中 0.001ms(1 次 access);开书路径每次省一次完整 walk。 徽标:副题格式化抽成 shelf_fmt_sub()(扫描与「刚读完置顶」共用一份实现), promote_just_read() 改 ts 后立即重算这本的 sub/sub_folder,「· 读」不再等下次全量刷新。 回归:test_reader_core 6846、shelf_group_smoke 63(+8)、font_resolve_smoke 14 全绿; build_reader.sh 0 warning;扫描缓存/进度语义未改。app.json 0.1.3/code4 → 0.1.4/code5。
This commit is contained in:
1 parent
0b30cdbafb
commit
dc9bfdbdaf
12 files changed
+460
-53
No files matched your search
@@ -0,0 +1,109 @@
|
||||
/* test/font_resolve_bench.c — M31 字体路径记忆化耗时对比(宿主,不依赖设备)。
|
||||
*
|
||||
* 同一棵树两种口径:
|
||||
* walk = 每次都重扫(= 加缓存前的 resolve_font 行为),由 font_cache_invalidate() 强制;
|
||||
* hit = 缓存命中 + access() 校验(= 加缓存后开书路径)。
|
||||
* 用法:./font_resolve_bench_host [目录] [迭代数],不传目录则先造一棵 35 目录的树。
|
||||
*/
|
||||
#include "font_resolve.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void mkdirs(const char *path)
|
||||
{
|
||||
char t[512];
|
||||
snprintf(t, sizeof t, "%s", path);
|
||||
for (char *p = t + 1; *p; p++) {
|
||||
if (*p == '/') { *p = 0; mkdir(t, 0755); *p = '/'; }
|
||||
}
|
||||
mkdir(t, 0755);
|
||||
}
|
||||
|
||||
static void write_file(const char *path, const char *body)
|
||||
{
|
||||
FILE *f = fopen(path, "wb");
|
||||
if (!f) return;
|
||||
fputs(body, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static void make_fonts_tree(const char *root, int ndirs, int files_per_dir)
|
||||
{
|
||||
char p[512];
|
||||
for (int i = 0; i < ndirs; i++) {
|
||||
snprintf(p, sizeof p, "%s/family_%02d/sub", root, i);
|
||||
mkdirs(p);
|
||||
for (int j = 0; j < files_per_dir; j++) {
|
||||
snprintf(p, sizeof p, "%s/family_%02d/readme_%d.txt", root, i, j);
|
||||
write_file(p, "x");
|
||||
}
|
||||
snprintf(p, sizeof p, "%s/family_%02d/sub/Font%02d.ttf", root, i, i);
|
||||
write_file(p, "x");
|
||||
}
|
||||
}
|
||||
|
||||
static double ms_now(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (double)ts.tv_sec * 1000.0 + (double)ts.tv_nsec / 1e6;
|
||||
}
|
||||
|
||||
typedef struct stat_res { double min, avg, max; } stat_res;
|
||||
|
||||
static stat_res run(const char *root, int iters, int invalidate_each)
|
||||
{
|
||||
stat_res r = { 1e9, 0, 0 };
|
||||
double sum = 0;
|
||||
for (int i = 0; i < iters; i++) {
|
||||
if (invalidate_each) font_cache_invalidate();
|
||||
double t0 = ms_now();
|
||||
(void)font_resolve(root);
|
||||
double dt = ms_now() - t0;
|
||||
if (dt < r.min) r.min = dt;
|
||||
if (dt > r.max) r.max = dt;
|
||||
sum += dt;
|
||||
}
|
||||
r.avg = iters ? sum / (double)iters : 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *root = (argc > 1) ? argv[1] : NULL;
|
||||
int iters = (argc > 2) ? atoi(argv[2]) : 200;
|
||||
char tmpbuf[512] = { 0 };
|
||||
|
||||
if (!root) {
|
||||
const char *base = getenv("TMPDIR");
|
||||
if (!base || !base[0]) base = "/tmp";
|
||||
snprintf(tmpbuf, sizeof tmpbuf, "%s/fontbench_XXXXXX", base);
|
||||
if (!mkdtemp(tmpbuf)) { printf("mkdtemp 失败\n"); return 2; }
|
||||
make_fonts_tree(tmpbuf, 35, 3);
|
||||
root = tmpbuf;
|
||||
}
|
||||
/* 预热(首轮含 dentry 冷缓存,不计入) */
|
||||
font_cache_invalidate(); font_resolve(root);
|
||||
font_resolve(root);
|
||||
|
||||
const char *p = font_resolve(root);
|
||||
printf("root=%s\n", root);
|
||||
printf("font=%s\n", p ? p : "(none)");
|
||||
stat_res w = run(root, iters, 1); /* 每次失效 = 旧行为:每次开书重 walk */
|
||||
stat_res h = run(root, iters, 0); /* 缓存命中 + access 校验 = 新行为 */
|
||||
printf("walk (每次重扫): min=%.3f avg=%.3f max=%.3f ms\n", w.min, w.avg, w.max);
|
||||
printf("hit (缓存+access): min=%.3f avg=%.3f max=%.3f ms\n", h.min, h.avg, h.max);
|
||||
if (h.avg > 0) printf("提速: %.1fx\n", w.avg / h.avg);
|
||||
|
||||
if (tmpbuf[0]) {
|
||||
char cmd[600];
|
||||
snprintf(cmd, sizeof cmd, "rm -rf '%s'", tmpbuf);
|
||||
if (system(cmd) != 0) { /* 忽略 */ }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user