Skip to content

Optimize the rendering loop in the disassembler widget#263

Open
trufae wants to merge 11 commits intomasterfrom
optimize-disasm
Open

Optimize the rendering loop in the disassembler widget#263
trufae wants to merge 11 commits intomasterfrom
optimize-disasm

Conversation

@trufae
Copy link
Collaborator

@trufae trufae commented Jan 7, 2026

Checklist

  • Closing issues: #issue
  • Mark this if you consider it ready to merge
  • I've added tests (optional)
  • I wrote some documentation

Description

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR optimizes the rendering loop in the disassembler widget by implementing scroll coalescing, highlight throttling, and refactoring the document update mechanism to reduce UI flicker and improve performance.

Key changes include:

  • Added scroll coalescing using a QTimer to batch multiple scroll events into a single scroll operation
  • Implemented highlight throttling to defer expensive highlighting operations when the cursor position changes rapidly
  • Refactored refreshDisasm to build HTML content in a single string and set it once, rather than inserting HTML line-by-line

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 11 comments.

File Description
src/widgets/DisassemblyWidget.h Added timer members for scroll coalescing and highlight throttling, plus state tracking variables
src/widgets/DisassemblyWidget.cpp Implemented optimization timers, refactored document rendering to use bulk HTML setting, converted breakpoint lookups to QSet for O(1) performance, and replaced signal connect/disconnect pattern with guard flags

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 477 to 480
if (wordChanged || mLastHighlightedWord.isEmpty()) {
extraSelections.append(createSameWordsSelections(mDisasTextEdit, curHighlightedWord));
mLastHighlightedWord = curHighlightedWord;
}
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The optimization to skip recomputing same-word selections has a critical flaw. When a word is cached (mLastHighlightedWord is set), the extraSelections list does not include the previous same-word selections. This means calling setExtraSelections will remove all previously highlighted words. The same-word selections need to be either re-appended from a cache or always recomputed.

Copilot uses AI. Check for mistakes.
Comment on lines +164 to +169
[this](int count) {
mPendingScrollLines += count;
if (!mScrollCoalesceTimer.isActive()) {
mScrollCoalesceTimer.start(16); // ~1 frame
}
});
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The scroll coalescing timer restarts on every scroll event (line 167), but the timer interval is only 16ms. If continuous scroll events arrive faster than 16ms apart, the pending scroll will keep accumulating without ever executing. This could lead to a delayed or "jumpy" scroll experience. Consider using a different strategy such as immediate execution for the first scroll and throttling subsequent ones, or using a shorter fixed delay.

Copilot uses AI. Check for mistakes.
Comment on lines 333 to 336
// Block all signals and disable UI updates during document rebuild
const QSignalBlocker docBlocker(mDisasTextEdit->document());
const QSignalBlocker scrollBlocker(mDisasTextEdit->verticalScrollBar());
mDisasTextEdit->setUpdatesEnabled(false);
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QSignalBlocker is used on mDisasTextEdit->document() and the scrollbar, but the cursorPositionChanged signal comes from mDisasTextEdit itself (connected at line 176). This signal blocker won't prevent cursorPositionChanged from firing when the document is modified. The mIgnoreCursorPositionChanged flag should be set to true before these operations and reset to false afterward.

Copilot uses AI. Check for mistakes.
radare and others added 10 commits January 7, 2026 23:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants