跳转至

Cache Strategies 专题

重要性:⭐⭐⭐(性能核心——5+ 类缓存策略、3 个 memoize 变体) 真实位置src/utils/memoize.ts + 全文 memoize* 调用 角色:避免重复计算 / IO / 网络,提升性能 关联topics/performance-history.md 分析版topics/prompt-cache.md


1. 5 大缓存策略

┌────────────────────────────────────────┐
│  1. memoize (永不过期)                  │
│  2. memoizeWithLRU (LRU 淘汰)         │
│  3. memoizeWithTTLAsync (时间过期)   │
│  4. sessionStorage 缓存                │
│  5. content hash 缓存                   │
└────────────────────────────────────────┘

5 类 —— 各有用途。


2. memoize 永不过期

2.1 用法

import { memoize } from './utils/memoize'

export const loadAllPlugins = memoize(async () => {
  return await loadAll()
})

单次 session —— 永不失效。

2.2 用途

  • 启动后不变的数据
  • 全文 search
  • Plugin 加载
  • Marketplace 加载

2.3 限制

  • 不跨 session —— 重启失效
  • 不更新 —— 数据变更不感知

3. memoizeWithLRU LRU 淘汰

3.1 用法

import { memoizeWithLRU } from './utils/memoize'

export const fetchToolsForClient = memoizeWithLRU(
  async (client, options) => fetchTools(client, options),
  // LRU size
  20  // MCP_FETCH_CACHE_SIZE
)

LRU 容量限制 —— 超过淘汰最旧。

3.2 用途

  • 多个 client 缓存
  • 动态对象 / 数组
  • 有限资源场景

3.3 限制

  • 频繁淘汰 → 命中率低
  • 容量需要调优

4. memoizeWithTTLAsync 时间过期

4.1 用法

import { memoizeWithTTLAsync } from './utils/memoize'

export const refreshAndGetAwsCredentials = memoizeWithTTLAsync(
  async () => refreshAwsCreds(),
  60 * 60 * 1000  // 1h
)

TTL 过期 —— 时间到重新计算。

4.2 用途

  • AWS / GCP 凭据(1h TTL)
  • Token 刷新
  • 配置定期更新

4.3 限制

  • TTL 到期后首次访问慢
  • 时钟依赖

5. sessionStorage 缓存

5.1 用途

  • session log
  • plugin 缓存
  • 提示历史
  • 设置变更

5.2 文件

// utils/sessionStorage.ts (5105 行)

sessionStorage —— 详细见 deep-dive。

5.3 缓存层

  • session 列表(Lite Session Info
  • plugin 缓存
  • skill 缓存
  • MCP 缓存

6. Content Hash 缓存

6.1 用法

generateTempFilePath('claude-settings', '.json', {
  contentHash: trimmedSettings  // 内容哈希
})

内容哈希 —— 同样内容同样路径。

6.2 用途

  • --settings JSON 字符串 → 临时文件
  • 避免 prompt cache 失效
  • 12x token 节省

6.3 关键 insight

path 一致 → prompt cache 命中


7. 4 个 memoize 变体(细节)

7.1 memoize

// 推测实现
function memoize<T extends Function>(fn: T): T {
  let cached: any
  let called = false
  return ((...args) => {
    if (!called) {
      cached = fn(...args)
      called = true
    }
    return cached
  }) as T
}

单 cache

7.2 memoizeWithLRU

function memoizeWithLRU<K, V>(fn, capacity) {
  const map = new Map<K, V>()
  return (key) => {
    if (map.has(key)) {
      // move to end
      const v = map.get(key)
      map.delete(key)
      map.set(key, v)
      return v
    }
    const v = fn(key)
    map.set(key, v)
    if (map.size > capacity) {
      map.delete(map.keys().next().value)  // delete oldest
    }
    return v
  }
}

LRU —— 推测实现。

7.3 memoizeWithTTLAsync

function memoizeWithTTLAsync<T>(fn, ttlMs) {
  let cached: T
  let expiresAt = 0
  return async () => {
    if (Date.now() > expiresAt) {
      cached = await fn()
      expiresAt = Date.now() + ttlMs
    }
    return cached
  }
}

TTL 异步

7.4 clearMemoizeCache

// 推测
function clearMemoizeCache(memo) { ... }

手动清 —— 某些情况下需要。


8. 缓存位置全景

8.1 启动层

// main.tsx
loadAllPlugins (memoize)
loadAllMarketplaces (memoize)

2 个启动级 memoize

8.2 MCP 层

// mcp/client.ts
connectToServer (memoize)  // 1 层
fetchToolsForClient (memoizeWithLRU, 20)  // 2 层
fetchResourcesForClient (memoizeWithLRU)  // 2 层
fetchCommandsForClient (memoizeWithLRU)  // 2 层
getMarketplace (memoize)

5 个 MCP memoize

8.3 凭据层

// auth.ts
refreshAndGetAwsCredentials (memoizeWithTTLAsync, 1h)
refreshGcpCredentialsIfNeeded (memoizeWithTTLAsync, 1h)
getApiKeyFromConfigOrMacOSKeychain (memoize)

3 个凭据 memoize

8.4 Plugin 层

// pluginLoader.ts
loadAllPlugins (memoize)
loadAllPluginsCacheOnly (memoize)

2 个 plugin memoize

8.5 Marketplace 层

// marketplaceManager.ts
getMarketplace (memoize)

1 个 marketplace memoize

总计 ~13 个 memoize 调用(推测)。


9. LRU 容量调优

9.1 MCP_FETCH_CACHE_SIZE = 20

20 个 client —— 典型项目 5-10 个 MCP。

9.2 Yoga CACHE_SLOTS = 4

4 个 layout cache —— 平衡。

9.3 API key helper TTL = 5min

5 分钟 —— helper 调用适度。

9.4 AWS / GCP TTL = 1h

1 小时 —— 凭据不过期。

9.5 OAuth auth cache = 15min

15 分钟 —— 短时记忆。


10. 5 类缓存 vs 性能影响

缓存 性能 内存 复杂度
memoize
memoizeWithLRU 中-高
memoizeWithTTLAsync
sessionStorage 中-高
content hash (cache 友好)

5 类对比 —— 选合适的。


11. Cache vs Stale Data

11.1 风险

缓存可能 stale —— 数据变了但缓存没更新。

11.2 缓解

  • TTL 过期
  • LRU 淘汰
  • 手动 clear cache
  • 启动时 invalidate

11.3 例子

// auth.ts
invalidateOAuthCacheIfDiskChanged()  // disk 变了清 cache

显式失效


12. 缓存监控

12.1 getYogaCounters

{ layouts, cacheHits, ... }

Yoga 监控

12.2 useFpsMetrics

// 推测:FPS 监控

UI 监控

12.3 logEvent

logEvent('tengu_cache_hit', { ... })

业务事件


13. 关键设计模式

13.1 3 个 memoize 变体

永不过期 / LRU / TTL —— 3 种场景。

13.2 容量可调

MCP=20, Yoga=4 —— 不同场景不同容量

13.3 TTL 阶梯

5min / 15min / 1h —— 3 档

13.4 content hash 是"魔法"

避免 prompt cache 失效 —— 12x 节省。

13.5 显式失效

invalidateOAuthCacheIfDiskChanged —— 防止 stale

13.6 双层缓存

MCP 2 层 memoize —— 细粒度

13.7 启动级 memoize

session 内永不失效


14. 关键洞察

14.1 3 个 memoize 变体

永不过期 / LRU / TTL —— 3 种策略

14.2 5 类缓存层

启动 / MCP / 凭据 / Plugin / Marketplace。

14.3 容量阶梯

4 / 20 / 5min / 15min / 1h —— 平衡

14.4 content hash 是"魔法"

避免 prompt cache 失效 —— 大节省

14.5 显式失效防 stale

invalidateOAuthCacheIfDiskChanged

14.6 双层缓存

MCP 2 层 —— 细粒度

14.7 启动级 memoize 0 风险

session 内数据稳定。

14.8 性能监控

getYogaCounters 等 metrics。

14.9 缓存 vs 复杂度 trade-off

越复杂 = 越可能 stale。

14.10 13+ memoize 覆盖

启动 / MCP / 凭据 / Plugin / Marketplace。


15. 改进方向

15.1 统一缓存接口

interface Cache<K, V> {
  get(key): V
  set(key, value): void
  clear(): void
}

统一抽象

15.2 LRU 配置化

new LRU({ capacity: 'auto' })

自适应

15.3 缓存指标

{ hits, misses, evictions }

完整 metrics

15.4 缓存预热

// 启动时预热

预热


16. 阅读建议

  1. utils/memoize.ts —— 3 个变体
  2. grep memoize 全文 —— 13+ 分布
  3. auth.ts 3 个 memoizeWithTTLAsync —— 凭据缓存
  4. mcp/client.ts 双层 memoize —— MCP 缓存

17. 与其他专题的关系

文件 关系
performance-history.md 性能整体
prompt-cache.md LLM cache
authentication.md 凭据缓存