Agent Skillslichtblick-suite/lichtblick › caching-internals

caching-internals

GitHub

解析Lichtblick预加载子系统的缓存内部机制,涵盖CachingIterableSource的LRU淘汰策略、内存预算管理及BlockLoader的优先级加载逻辑。

.github/skills/caching-internals/SKILL.md lichtblick-suite/lichtblick

Trigger Scenarios

询问Lichtblick缓存实现细节 分析数据预加载与内存管理策略 排查回放过程中的缓存命中或淘汰问题

Install

npx skills add lichtblick-suite/lichtblick --skill caching-internals -g -y
More Options

Non-standard path

npx skills add https://github.com/lichtblick-suite/lichtblick/tree/develop/.github/skills/caching-internals -g -y

Use without installing

npx skills use lichtblick-suite/lichtblick@caching-internals

指定 Agent (Claude Code)

npx skills add lichtblick-suite/lichtblick --skill caching-internals -a claude-code -g -y

安装 repo 全部 skill

npx skills add lichtblick-suite/lichtblick --all -g -y

预览 repo 内 skill

npx skills add lichtblick-suite/lichtblick --list

SKILL.md

Frontmatter
{
    "name": "caching-internals",
    "description": "Deep implementation details of caching strategies, memory budgets, block eviction, and buffered reading in the Lichtblick preloading subsystem."
}

Caching Internals Skill

CachingIterableSource Implementation

Cache Structure

class CachingIterableSource {
  #blocks = new Map<string, CacheBlock>();  // key: serialized range+topics
  #totalSize = 0;                           // current memory usage
  #cacheSizeBytes = 600 * 1024 * 1024;      // 600MB budget
  #maxBlockSize = 50 * 1024 * 1024;         // 50MB per block
  #accessOrder: string[] = [];              // LRU tracking
}

Cache Key Design

  • Key combines: startTime + endTime + sorted topic names
  • This means the same time range with different topic sets creates separate cache entries
  • Allows partial cache hits when subscription set changes

Eviction Algorithm

  1. When #totalSize + newBlockSize > #cacheSizeBytes:
  2. Find blocks behind current read position (already consumed)
  3. Evict LRU blocks until sufficient space is freed
  4. If no blocks behind read position exist, evict oldest block regardless

Block Lifecycle

EMPTY → LOADING → CACHED → EVICTED
                     │
                     └──► ACCESSED (moves to front of LRU)

BufferedIterableSource Implementation

Read-Ahead Configuration

// packages/suite-base/src/players/IterablePlayer/BufferedIterableSource.ts
const DEFAULT_READ_AHEAD_DURATION = { sec: 10, nsec: 0 };
// Overridable per-instance via opt.readAheadDuration; defaults to 10 s.

⚠️ There is no MCAP_READ_AHEAD_DURATION_SEC = 120 (or any 120-second MCAP-specific read-ahead). The only default is { sec: 10, nsec: 0 }, applied uniformly regardless of source format.

Producer-Consumer Coordination

Producer Thread (may be Worker):
  while (not at end && buffer not full) {
    message = await source.next();
    buffer.push(message);
    signal consumer;
  }
  wait for consumer to drain;

Consumer (IterablePlayer tick loop):
  messages = buffer.drain(upToTime);
  signal producer to refill;

Backpressure Mechanism

  • Producer fills buffer up to readAheadDuration worth of messages
  • When buffer is full, producer yields (awaits a drain signal)
  • Consumer pulls messages up to its tick budget time
  • After consuming, signals producer to resume filling

VecQueue Details

  • Backed by a plain array with start/end pointers
  • push(): appends to end, O(1)
  • drain(predicate): returns all items matching predicate from front, O(n) but bulk operation
  • Periodic compaction: when start pointer exceeds threshold, shifts array

BlockLoader Implementation

Block Division Strategy

  • Total time range divided into N blocks of equal duration
  • Block count determined by: Math.ceil(totalDuration / targetBlockDuration)
  • Target block duration balances granularity vs overhead

Loading Priority

  1. Block containing current playback time (immediate need)
  2. Blocks ahead of current time (upcoming data)
  3. Blocks behind current time (for seek-back scenarios)
  4. Never-accessed blocks (lowest priority)

Progress Reporting

interface Progress {
  fullyLoadedFractionRanges: Array<{ start: number; end: number }>;
  // Fraction 0..1 representing which portions of the time range are cached
}

Memory Optimization Patterns

  1. Shared ArrayBuffers: Message data stored as Uint8Array views into shared buffers where possible
  2. Lazy deserialization: Raw bytes cached, deserialized only when consumed
  3. Topic-scoped loading: Each block only contains data for requested topics
  4. Size estimation: Block size estimated before full load to prevent over-allocation

Version History

  • cab9317 Current 2026-07-24 12:16

Same Skill Collection

.github/skills/3d-rendering/SKILL.md
.github/skills/deserialization/SKILL.md
.github/skills/e2e-playwright-mcp/SKILL.md
.github/skills/electron-internals/SKILL.md
.github/skills/extensions-internals/SKILL.md
.github/skills/layouts-internals/SKILL.md
.github/skills/mcap-format/SKILL.md
.github/skills/message-path/SKILL.md
.github/skills/message-pipeline/SKILL.md
.github/skills/panel-extension-api/SKILL.md
.github/skills/panel-image/SKILL.md
.github/skills/panel-log/SKILL.md
.github/skills/panel-map/SKILL.md
.github/skills/panel-raw-messages/SKILL.md
.github/skills/panel-state-transitions/SKILL.md
.github/skills/panel-user-scripts/SKILL.md
.github/skills/performance/SKILL.md
.github/skills/player-internals/SKILL.md
.github/skills/plot-internals/SKILL.md
.github/skills/remote-caching/SKILL.md
.github/skills/test-conventions/SKILL.md
.github/skills/theme/SKILL.md
.github/skills/unit-testing/SKILL.md
.github/skills/web-workers/SKILL.md
.github/skills/websocket-connection/SKILL.md

Metadata

Files
0
Version
cab9317
Hash
481d479a
Indexed
2026-07-24 12:16

Accueil - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-07 14:35
浙ICP备14020137号-1 $Carte des visiteurs$