perf: FsStore loads all CAS nodes into memory at startup #85

Closed
opened 2026-06-06 22:33:30 +00:00 by xiaoju · 0 comments
Owner

问题

packages/fs/src/store.tscreateFsStore() 在启动时调用 loadDir() 把目录下所有 .bin 文件全量反序列化(CBOR decode)到内存 Map<Hash, CasNode>

// store.ts:205-207
export function createFsStore(dir: string): FsCasStore {
  const data = new Map<Hash, CasNode>();
  loadDir(dir, data);  // 全量读取+解码

之后所有 get()has()listAll() 都走内存 Map,磁盘文件只在 put()delete() 时写入。

影响

  • 启动时间:节点数量线性增长
  • 内存占用:所有节点常驻内存,payload 可能很大
  • 当前 283 个节点无明显影响,但不可扩展

建议方案

改为按需加载(lazy loading):

  • get(hash) — 命中内存缓存则返回,否则读文件 + 缓存
  • has(hash) — 检查文件是否存在(existsSync 或维护 hash set)
  • listAll() — 读目录文件名(不需要解码 payload)
  • listByType() — 依赖 type index 文件,不需要全量加载
  • 可选 LRU 缓存控制内存上限

关联

  • #83 (export/import) — MemoryStore 方案在当前全量加载模式下不比 FsStore 差
  • #84 (nodes/ 子目录) — 布局改造时可顺带做 lazy loading
## 问题 `packages/fs/src/store.ts` 的 `createFsStore()` 在启动时调用 `loadDir()` 把目录下所有 `.bin` 文件全量反序列化(CBOR decode)到内存 `Map<Hash, CasNode>`: ```typescript // store.ts:205-207 export function createFsStore(dir: string): FsCasStore { const data = new Map<Hash, CasNode>(); loadDir(dir, data); // 全量读取+解码 ``` 之后所有 `get()`、`has()`、`listAll()` 都走内存 Map,磁盘文件只在 `put()` 和 `delete()` 时写入。 ## 影响 - 启动时间:节点数量线性增长 - 内存占用:所有节点常驻内存,payload 可能很大 - 当前 283 个节点无明显影响,但不可扩展 ## 建议方案 改为按需加载(lazy loading): - `get(hash)` — 命中内存缓存则返回,否则读文件 + 缓存 - `has(hash)` — 检查文件是否存在(`existsSync` 或维护 hash set) - `listAll()` — 读目录文件名(不需要解码 payload) - `listByType()` — 依赖 type index 文件,不需要全量加载 - 可选 LRU 缓存控制内存上限 ## 关联 - #83 (export/import) — MemoryStore 方案在当前全量加载模式下不比 FsStore 差 - #84 (nodes/ 子目录) — 布局改造时可顺带做 lazy loading
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: shazhou/ocas#85