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
This commit is contained in:
Levi Neely 2026-07-16 06:42:11 +02:00
parent a6a1a227c3
commit 6f351b77e4
2 changed files with 18 additions and 2 deletions

View File

@ -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', "<br>");
QString plain = code.toHtmlEscaped().replace('\n', "<br>");
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 += "<br>";
}
m_highlightCache.insert(cacheKey, html);
return html;
}

View File

@ -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<ChatBlock> m_blocks;
mutable QHash<QString, QString> m_highlightCache; // key: code+lang, value: html
};
#endif // CHAT_BLOCK_MODEL_H