Skip to content

Technische Details: Caching-Mechanismus und Leistungsoptimierung

Was Sie nach diesem Kurs können

  • Verstehen, wie der Caching-Mechanismus des Plugins die Leistung verbessert
  • Die Datenstruktur und Verwendung von widthCache beherrschen
  • Die Auslösebedingungen für die automatische Cache-Bereinigung kennen
  • Wissen, wie Sie die Wirkung der Leistungsoptimierung analysieren

Ihr aktuelles Problem

Sie fragen sich vielleicht:

Wie berechnet das Plugin Tabellenbreiten so schnell? Warum ist die Verarbeitung großer Tabellen immer noch flüssig? Wie ist der Caching-Mechanismus konzipiert?

Diese Lektion analysiert die interne Implementierung des Plugins im Detail und führt Sie durch die Designideen und Leistungsoptimierungsstrategien des Caching-Mechanismus.

Kernidee

Warum Caching verwenden?

Bei der Formatierung von Markdown-Tabellen muss das Plugin die Anzeigebreite (display width) jeder Zelle berechnen. Diese Berechnung umfasst:

  1. Entfernen von Markdown-Symbolen: wie **fett**, *kursiv*, ~~durchgestrichen~~
  2. Schützen von Inline-Code: Markdown-Symbole in `Code` bleiben unverändert
  3. Aufrufen von Bun.stringWidth(): Berechnen der Anzeigebreite von Unicode-Zeichen (einschließlich Emoji, chinesischen Zeichen)

Das Problem: Der gleiche Zelleninhalt kann mehrfach auftreten (z. B. Tabellenüberschriften), und jedes Mal diese Logik neu zu berechnen ist langsam.

Lösung: Verwenden Sie einen Cache (Map), um die Zuordnung "Textinhalt → Anzeigebreite" zu speichern und wiederholte Berechnungen zu vermeiden.

Cache-Datenstruktur

Das Plugin verwendet zwei globale Variablen zur Verwaltung des Caches:

widthCache

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

Zweck: Cache der Ergebnisse der Anzeigebreitenberechnung von Zeichenfolgen

Struktur:

  • Key: Der ursprüngliche Textinhalt der Zelle (einschließlich aller Markdown-Syntax)
  • Value: Die berechnete Anzeigebreite (Anzahl der Zeichen)

Beispiel:

Ursprünglicher Text (Key)Anzeigebreite (Value)Erklärung
**Name**4Breite nach Entfernen von ** ist 4
*Alter*4Breite nach Entfernen von * ist 4
`status`8Codeblock-Symbole werden ebenfalls in die Breite einbezogen
张三4Breite chinesischer Zeichen ist 1

cacheOperationCount

typescript
let cacheOperationCount = 0

Zweck: Aufzeichnen der Anzahl der Cache-Operationen, um die automatische Bereinigung auszulösen

Bereinigungsschwellenwerte:

  • Anzahl der Operationen > 100 oder
  • Cache-Einträge > 1000

Cache-Suchprozess

calculateDisplayWidth-Funktion

Wenn die Zellenbreite berechnet werden muss, ruft das Plugin die Funktion calculateDisplayWidth() auf und führt den folgenden Prozess aus:

📖 Vollständigen Code anzeigen
typescript
function calculateDisplayWidth(text: string): number {
  if (widthCache.has(text)) {
    return widthCache.get(text)!  // Cache-Treffer, direkt zurückgeben
  }

  const width = getStringWidth(text)  // Tatsächliche Breite berechnen
  widthCache.set(text, width)          // Im Cache speichern
  return width
}

Flussdiagramm:

Schrittanalyse:

SchrittOperationZeitkomplexität
1Prüfen widthCache.has(text)O(1)
2Cache-Treffer → Direkt zurückgebenO(1)
3Cache-Fehltreffer → Breite berechnenO(n)
4Im Cache speichernO(1)

Schlüsselpunkte:

  • Bei Cache-Treffer: Direkt zurückgeben, ohne Berechnung (O(1))
  • Bei Cache-Fehltreffer: Vollständige Breitenberechnungslogik ausführen (O(n))
  • Ursprünglichen Text speichern: Key ist der vollständige Markdown-Text, um eine genaue Übereinstimmung zu gewährleisten

Cache-Bereinigungsmechanismus

Warum den Cache bereinigen?

Caching kann zwar die Leistung verbessern, verbraucht aber Speicher. Wenn nicht bereinigt:

  • Speicherverbrauch wächst kontinuierlich: Jeder neue Zelleninhalt wird zwischengespeichert
  • Kann nutzlose Daten enthalten: Alter Tabelleninhalt wird möglicherweise nicht mehr benötigt

Auslösebedingungen für automatische Bereinigung

Nach Abschluss jeder Formatierung ruft das Plugin incrementOperationCount() auf, um den Operationszähler zu aktualisieren:

📖 Bereinigungscode anzeigen
typescript
function incrementOperationCount() {
  cacheOperationCount++

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

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

Auslösebedingungen (wird ausgelöst, wenn eine davon erfüllt ist):

BedingungSchwellenwertErklärung
Anzahl der Operationen> 100 FormatierungsvorgängeVermeidet häufiges Auslösen der Bereinigung
Cache-Einträge> 1000 ZellenVerhindert zu hohen Speicherverbrauch

Bereinigungsstrategie:

  • Vollständig leeren: widthCache.clear() löscht alle Caches
  • Zähler zurücksetzen: cacheOperationCount = 0

Bereinigungszeitpunkt

Die Cache-Bereinigung erfolgt nach Abschluss jeder Formatierung, nicht während der Formatierung. Dies unterbricht keine laufenden Formatierungsvorgänge.

Leistungsoptimierungseffekt

Cache-Trefferratenanalyse

Nehmen wir eine Tabelle mit 5 Spalten × 10 Zeilen an, wobei:

  • Wiederholter Inhalt: Tabellenüberschriften erscheinen 11-mal in der Trennzeile und den Datenzeilen
  • Eindeutiger Inhalt: Der Inhalt jeder Zelle ist unterschiedlich

Cache-Effekt:

SzenarioOhne CacheMit CacheLeistungssteigerung
5 Spalten × 10 Zeilen (keine Wiederholungen)50 Berechnungen50 BerechnungenKeine
5 Spalten × 10 Zeilen (wiederholte Überschriften)50 Berechnungen10 Berechnungen + 40 Cache-Treffer~80%

Tatsächliche Auswirkungen

Vorteile durch Caching:

  1. Berechnungsaufwand reduzieren: Vermeidet wiederholtes Entfernen von Markdown-Symbolen und Aufrufen von Bun.stringWidth()
  2. CPU-Auslastung senken: getStringWidth() beinhaltet Regex-Ersetzung und Unicode-Berechnung, was einen hohen Aufwand verursacht
  3. Reaktionsgeschwindigkeit verbessern: Besonders deutlich bei Tabellen mit vielen wiederholten Zellen

Beispielszenarien:

SzenarioCache-Effekt
KI-generierte Vergleichstabellen✅ Deutlich (wiederholter Inhalt in mehreren Spalten)
Einfache einzeilige Tabellen⚪ Mäßig (eindeutiger Inhalt)
Tabellen mit verschachteltem Markdown✅ Deutlich (hoher Aufwand beim Entfernen von Symbolen)

Leistungsoptimierungsempfehlungen

Empfehlungen für Entwickler

Wenn Sie die Leistung weiter optimieren müssen, können Sie Folgendes in Betracht ziehen:

  1. Cache-Schwellenwerte anpassen: Passen Sie die Schwellenwerte von 100 Operationen und 1000 Einträgen je nach tatsächlicher Tabellengröße an
  2. LRU-Cache: Verwenden Sie den Least Recently Used (LRU)-Algorithmus anstelle der Strategie zum vollständigen Leeren
  3. Leistungsüberwachung: Fügen Sie Protokolle hinzu, um die Cache-Trefferrate zu statistisieren und die tatsächliche Wirkung zu analysieren

Zusammenfassung dieser Lektion

Das Plugin verwendet den widthCache-Caching-Mechanismus zur Leistungsoptimierung:

  • Speicherstruktur: Map<string, number> bildet ursprünglichen Text auf Anzeigebreite ab
  • Suchprozess: Zuerst Cache prüfen → Bei Fehltreffer berechnen und speichern
  • Bereinigungsmechanismus: Automatische Bereinigung bei Operationen > 100 oder Einträgen > 1000
  • Leistungssteigerung: Reduziert wiederholte Berechnungen und senkt die CPU-Auslastung

Dieser Mechanismus sorgt dafür, dass das Plugin auch bei der Verarbeitung komplexer Tabellen flüssig bleibt und ist die Kernimplementierung der Leistungsoptimierung.

Vorschau auf die nächste Lektion

In der nächsten Lektion lernen wir Änderungsprotokoll: Versionsverlauf und Änderungsprotokoll.

Sie werden lernen:

  • Die Versionsentwicklung des Plugins
  • Neue Funktionen und Korrekturen
  • Wie Sie Plugin-Updates verfolgen

Anhang: Quellcode-Referenz

Klicken, um Quellcodepositionen anzuzeigen

Aktualisierungszeit: 2026-01-26

FunktionDateipfadZeilennummer
widthCache-Definitionsource/franlol/opencode-md-table-formatter/index.ts6
cacheOperationCount-Definitionsource/franlol/opencode-md-table-formatter/index.ts7
---------
---------
---------

Schlüsselkonstanten:

  • widthCache = new Map<string, number>(): Map-Struktur zum Caching der Anzeigebreite von Zeichenfolgen
  • cacheOperationCount = 0: Cache-Operationszähler

Schlüsselfunktionen:

  • calculateDisplayWidth(text: string): number: Berechnet die Anzeigebreite (mit Cache), prüft zuerst den Cache und berechnet dann
  • incrementOperationCount(): void: Erhöht den Operationszähler, löst bedingte Bereinigung aus
  • cleanupCache(): void: Leert widthCache und setzt den Zähler zurück