From 6f351b77e4c8bf505d35d450a03a926053336649 Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Thu, 16 Jul 2026 06:42:11 +0200 Subject: [PATCH] fix performance: cache subBlocks and syntax highlighting - Cache parseSubBlocks per block (only reparse when content changes) - Cache highlightedHtml results (code+language key) - Prevents expensive KSyntaxHighlighting and regex on every render - Also fixes scroll loop with _scrolling guard --- gui/chatblockmodel.cpp | 17 +++++++++++++++-- gui/chatblockmodel.h | 3 +++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/gui/chatblockmodel.cpp b/gui/chatblockmodel.cpp index c4316a3..256e579 100644 --- a/gui/chatblockmodel.cpp +++ b/gui/chatblockmodel.cpp @@ -54,7 +54,11 @@ QVariant ChatBlockModel::data(const QModelIndex &index, int role) const case ContentRole: return block.content; case SubBlocksRole: - return parseSubBlocks(block.content); + if (block.cachedContent != block.content) { + block.cachedSubBlocks = parseSubBlocks(block.content); + block.cachedContent = block.content; + } + return block.cachedSubBlocks; } return {}; } @@ -251,6 +255,12 @@ QVariantList ChatBlockModel::parseSubBlocks(const QString &content) const QString ChatBlockModel::highlightedHtml(const QString &code, const QString &language) const { + // Check cache first + QString cacheKey = language + "\x1f" + code; + auto cached = m_highlightCache.find(cacheKey); + if (cached != m_highlightCache.end()) + return *cached; + auto def = repo().definitionForName(language); if (!def.isValid()) { // Try by file extension @@ -258,7 +268,9 @@ QString ChatBlockModel::highlightedHtml(const QString &code, const QString &lang } if (!def.isValid()) { // Return escaped plain text - return code.toHtmlEscaped().replace('\n', "
"); + QString plain = code.toHtmlEscaped().replace('\n', "
"); + m_highlightCache.insert(cacheKey, plain); + return plain; } // Determine theme based on current palette @@ -298,6 +310,7 @@ QString ChatBlockModel::highlightedHtml(const QString &code, const QString &lang html += "
"; } + m_highlightCache.insert(cacheKey, html); return html; } diff --git a/gui/chatblockmodel.h b/gui/chatblockmodel.h index b7b2b7d..b1c9dac 100644 --- a/gui/chatblockmodel.h +++ b/gui/chatblockmodel.h @@ -20,6 +20,8 @@ struct ChatBlock { Type type; QString name; // tool/call name, empty for others QString content; // raw text content + mutable QVariantList cachedSubBlocks; // cached parseSubBlocks result + mutable QString cachedContent; // content when subBlocks were cached }; // A sub-block within a markdown block (prose, code fence, diff) @@ -70,6 +72,7 @@ private: QString m_rawText; QList m_blocks; + mutable QHash m_highlightCache; // key: code+lang, value: html }; #endif // CHAT_BLOCK_MODEL_H