Skip to content

[Perf] 目录跳章延迟:section 加载全程串行、同一份 XHTML 被解析三次、Loader 无缓存 #748

Description

@chy5301

Type

Suggestion

Description

从目录点击章节后有明显等待。两端从 view.goTo 起完全共用 vendored foliate-js,所以这是一个内核层问题,不是某一端的问题。

Paginator.#goTo(paginator.js:2895)有两条路:

  • 快路径(:2915-2963):目标 section 已在 #views 里,只换 primary,几十毫秒
  • 慢路径(:2965-2996):目录跳到非相邻章必然走这条

慢路径的 #display 一进来就 opacity = '0'(paginator.js:2682),到 :2737 才恢复 '1',中间全部串行 await:

步骤 位置 问题
zip 解压整章 view.js:32 等三处 useWebWorkers:false 跑在主线程
DOMParser 解析 epub.js:1081 第 1 次解析
9 组资源改写 epub.js:1119-1140 全部串行 await,可并发
XMLSerializer epub.js:1157 第 2 次(序列化)
iframe.srcdoc paginator.js:516-519 浏览器第 3 次解析同一份内容
背景图等待 paginator.js:485-491 最长 3000ms 硬等待
columnize + 逐图 getComputedStyle paginator.js:565-705
expand() 全章强制重排 paginator.js:713-745 一次跳章通常跑 2-3 次
同步预加载上一章 paginator.js:2717-2730 分页模式下短章还要等它

揭示之后还有 #fillVisibleArea(:2822)串行补最多 8 个 section,每个都完整重跑上面这条流水线 —— 这对应「正文出来了但一两秒内点不动」。

另一个关键点:Loader 没有 LRU

epub.js:996 引用计数归零就立刻 URL.revokeObjectURL + 删缓存,#cache / #cacheXHTMLContent 全文没有任何容量上限或逐出策略。而慢路径的 keep 只保留 index ±2(paginator.js:2974-2978),跨章跳转必然销毁其余 view。结果是来回跳章第二次仍然全量重解析,连全书共享的 style.css / 字体也被 revoke 掉。

建议(按性价比排序)

  1. 给 Loader 加容量固定的 LRU:unref 到 0 时不立刻 revoke,改为入队(XHTML 6-10 条 + CSS/字体常驻池)。loadItem 已有命中路径(epub.js:1021),只需让缓存活得更久。收益最直接。
  2. epub.js:1119-1140 的串行 await 改成 Promise.all 并发(需补 in-flight 去重)。
  3. paginator.js:489 的背景图 setTimeout(res, 3000) 降到 150-300ms —— img.onload 里已有兜底路径(:473-477)。
  4. paginator.js:2747#fillVisibleArea 推迟到首帧之后(rAF + setTimeout 0),让正文先可交互;:3060 的 await this.#fillPromise 改成带 50ms 超时的 race。
  5. expand() 结果按 layout 签名缓存;fonts.ready 与 ResizeObserver 两路 expand 合并去抖到同一帧。
  6. 桌面端 FoliateViewer.tsx:2088-2137 的整章 TreeWalker 挡在 opacity='1' 之前,直接计入白屏时长(详见 [Perf] 章内翻页固定多付 100ms,且一次翻页触发两次 relocate #749)。

说明

全部来自代码路径静态分析,没有实测 profile。 各步骤真实耗时占比(解压 vs DOMParser vs expand vs 宿主回调)未知,建议在 #display 的 opacity 0→1 之间打几个 performance.mark 实测一次再定优先级。

特别提醒:useCompressionStream 仍为 true,实际 inflate 走原生 DecompressionStream,所以「zip 解压在主线程」这条的收益可能远小于直觉,不建议当第一优先级。

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions