Skip to content

Technical Details: Caching Mechanism & Performance Optimization

What You'll Learn

  • Understand how the plugin's caching mechanism improves performance
  • Master the data structure and usage of widthCache
  • Learn the trigger conditions for automatic cache cleanup
  • Know how to analyze the effectiveness of performance optimization

Your Current Challenge

You may be wondering:

How does the plugin quickly calculate table widths? Why does it remain smooth when handling large tables? How is the caching mechanism designed?

This lesson provides an in-depth analysis of the plugin's internal implementation, helping you understand the design philosophy behind the caching mechanism and performance optimization strategies.

Core Concepts

Why Use Caching?

When formatting Markdown tables, the plugin needs to calculate the display width of each cell. This calculation involves:

  1. Stripping Markdown syntax: Such as **bold**, *italic*, ~~strikethrough~~
  2. Preserving inline code: Markdown syntax within `code` blocks remains unchanged
  3. Calling Bun.stringWidth(): Calculates the display width of Unicode characters (including Emoji, Chinese characters)

The problem: The same cell content may appear multiple times (e.g., header column names), and recalculating these operations each time is slow.

The solution: Use a cache (Map) to store the mapping of "text content → display width", avoiding redundant calculations.

Cache Data Structure

The plugin uses two global variables to manage the cache:

widthCache

typescript
const widthCache = new Map<string, number>()

Purpose: Cache the calculation results of string display width

Structure:

  • Key: The original text content of the cell (including all Markdown syntax)
  • Value: The calculated display width (character count)

Examples:

Original Text (Key)Display Width (Value)Description
**姓名**4Width is 4 after stripping **
*年龄*4Width is 4 after stripping *
`status`8Code block symbols are also counted in width
张三4Chinese character width is 1

cacheOperationCount

typescript
let cacheOperationCount = 0

Purpose: Records the number of cache operations, used to trigger automatic cleanup

Cleanup thresholds:

  • Operations > 100 or
  • Cache entries > 1000

Cache Lookup Process

calculateDisplayWidth Function

When the plugin needs to calculate cell width, it calls the calculateDisplayWidth() function, which executes the following flow:

📖 View Complete Code
typescript
function calculateDisplayWidth(text: string): number {
  if (widthCache.has(text)) {
    return widthCache.get(text)!  // Cache hit, return directly
  }

  const width = getStringWidth(text)  // Calculate actual width
  widthCache.set(text, width)          // Store in cache
  return width
}

Flowchart:

Step Breakdown:

StepOperationTime Complexity
1Check widthCache.has(text)O(1)
2Cache hit → Return directlyO(1)
3Cache miss → Calculate widthO(n)
4Store in cacheO(1)

Key Points:

  • On cache hit: Return directly without any calculation (O(1))
  • On cache miss: Execute the complete width calculation logic (O(n))
  • Store original text: Key is the complete Markdown text, ensuring exact matching

Cache Cleanup Mechanism

Why Clean the Cache?

While caching improves performance, it consumes memory. Without cleanup:

  • Memory usage grows continuously: Each new cell content gets cached
  • May contain useless data: Old table content may no longer be needed

Automatic Cleanup Trigger Conditions

The plugin calls incrementOperationCount() to update the operation counter after each formatting completion:

📖 View Cleanup Code
typescript
function incrementOperationCount() {
  cacheOperationCount++

  if (cacheOperationCount > 100 || widthCache.size > 1000) {
    cleanupCache()
  }
}

function cleanupCache() {
  widthCache.clear()
  cacheOperationCount = 0
}

Trigger conditions (triggered when either condition is met):

ConditionThresholdDescription
Operation count> 100 formatting operationsAvoid frequent cleanup triggers
Cache entries> 1000 cellsPrevent excessive memory usage

Cleanup strategy:

  • Complete clear: widthCache.clear() removes all cached entries
  • Reset counter: cacheOperationCount = 0

Cleanup Timing

Cache cleanup happens after each formatting completes, not during formatting. This ensures ongoing formatting operations are not interrupted.

Performance Optimization Effects

Cache Hit Rate Analysis

Assume a 5-column × 10-row table where:

  • Duplicate content: Header column names appear 11 times (header row, separator row, and data rows)
  • Unique content: Each cell has different content

Cache effectiveness:

ScenarioWithout CacheWith CachePerformance Improvement
5 columns × 10 rows (no duplicates)50 calculations50 calculationsNone
5 columns × 10 rows (duplicate headers)50 calculations10 calculations + 40 cache hits~80%

Real-world Impact

Advantages brought by caching:

  1. Reduce computation overhead: Avoid repeatedly stripping Markdown syntax and calling Bun.stringWidth()
  2. Lower CPU usage: getStringWidth() involves regex replacement and Unicode calculations, which are expensive
  3. Improve response speed: More noticeable effects for tables with many duplicate cells

Example scenarios:

ScenarioCache Effectiveness
------
Simple single-row tables⚪ Moderate (unique content)
Tables with nested Markdown✅ Significant (high symbol stripping overhead)

Performance Optimization Suggestions

Recommendations for Developers

If you need to further optimize performance, consider:

  1. Adjust cache thresholds: Tune the 100 operation and 1000 entry thresholds based on actual table sizes
  2. LRU cache: Use Least Recently Used (LRU) algorithm instead of complete clearing strategy
  3. Performance monitoring: Add logging to track cache hit rates and analyze actual effectiveness

Summary

The plugin uses the widthCache caching mechanism to optimize performance:

  • Storage structure: Map<string, number> maps original text to display width
  • Lookup process: Check cache first → Calculate and store on miss
  • Cleanup mechanism: Auto-cleanup when operations > 100 or entries > 1000
  • Performance improvement: Reduce redundant calculations and lower CPU usage

This mechanism keeps the plugin smooth when handling complex tables and is the core implementation of performance optimization.

Coming Up Next

In the next lesson, we'll learn Changelog: Version History & Change Records.

You'll learn:

  • The plugin's version evolution history
  • New features and fix records
  • How to track plugin updates

Appendix: Source Code Reference

Click to expand source code locations

Last updated: 2026-01-26

FeatureFile PathLine Number
widthCache definitionsource/franlol/opencode-md-table-formatter/index.ts6
cacheOperationCount definitionsource/franlol/opencode-md-table-formatter/index.ts7
calculateDisplayWidth functionsource/franlol/opencode-md-table-formatter/index.ts151-159
incrementOperationCount functionsource/franlol/opencode-md-table-formatter/index.ts219-225
cleanupCache functionsource/franlol/opencode-md-table-formatter/index.ts227-230

Key constants:

  • widthCache = new Map<string, number>(): Map structure for caching string display widths
  • cacheOperationCount = 0: Cache operation counter

Key functions:

  • calculateDisplayWidth(text: string): number: Calculates display width (with caching), checks cache before calculating
  • incrementOperationCount(): void: Increments operation count, triggers conditional cleanup
  • cleanupCache(): void: Clears widthCache and resets counter