Skip to content

perf(remote-gui): batch remote log delivery + rendering - #451

Merged
got3nks merged 1 commit into
amule-org:masterfrom
got3nks:fix/remote-log-batch
Jul 11, 2026
Merged

perf(remote-gui): batch remote log delivery + rendering#451
got3nks merged 1 commit into
amule-org:masterfrom
got3nks:fix/remote-log-batch

Conversation

@got3nks

@got3nks got3nks commented Jul 11, 2026

Copy link
Copy Markdown

On a remote GUI first sync the daemon replays the whole logfile, and the GUI rendered it one line at a time: CamuleDlg::AddLogLine rebuilt the wxTE_RICH2 default style and scrolled to the end on every line with no Freeze/Thaw, and the daemon throttled to 200 log lines per stats poll. For a large backlog (#445 — ~10k queue) the "aMule Log" tab took ~5 minutes to catch up with the GUI frozen throughout. (The server-info log already had a diff optimization; the app log never got one.)

Keeps the full-log-on-connect behaviour, just fast:

  • Daemon: per-poll cap 200 → 5000 (EC_LOG_LINES_PER_MESSAGE), so a large backlog drains in a few polls instead of ~50. The wire format imposes no limit (ec_taglen_t is uint32, tag count is uint32-extensible) — the cap is purely per-poll responsiveness, since the log shares the response with live stats.
  • GUI: batch each poll's lines into one repaint + one scroll via CamuleDlg::BeginLogBatch()/EndLogBatch() (Freeze/Thaw), and call the costly SetDefaultStyle() only when the bold state actually changes, not per line.

Verification: amuled + amulegui build clean; clang-format + clang-tidy (Tier-1 & Tier-2) clean. End-to-end speed-up to be confirmed by the reporter on his 10k queue.

Refs #445

…project#445)

On a remote GUI first sync the daemon replays the whole logfile, and the
GUI rendered it one line at a time: CamuleDlg::AddLogLine rebuilt the
RichEdit default style and scrolled to the end on every line with no
Freeze/Thaw, and the daemon throttled to 200 log lines per stats poll.
For a large backlog (issue amule-project#445: ~10k download queue) the "aMule Log"
tab took ~5 minutes to catch up with the GUI frozen throughout.

Keep the full-log-on-connect behaviour, but make it fast:

- Daemon: raise the per-poll cap 200 -> 5000 (EC_LOG_LINES_PER_MESSAGE),
  so a large backlog drains in a few polls instead of ~50. The wire
  format imposes no limit (ec_taglen_t is uint32, tag count is
  uint32-extensible); the cap is purely per-poll responsiveness, since
  the log shares the response with live stats.
- GUI: batch each poll's lines into one repaint + one scroll via
  CamuleDlg::BeginLogBatch()/EndLogBatch() (Freeze/Thaw), and only call
  the costly SetDefaultStyle() when the bold state actually changes
  rather than per line.

Refs amule-project#445
@got3nks
got3nks merged commit aa991bd into amule-org:master Jul 11, 2026
13 checks passed
@got3nks
got3nks deleted the fix/remote-log-batch branch July 11, 2026 17:40
got3nks added a commit that referenced this pull request Jul 13, 2026
…445) (#471)

The per-poll log batching added in #451 scrolls the "aMule Log" text ctrl
(EndLogBatch) while it is still frozen, then thaws. On Windows, ShowPosition()
on a frozen wxTE_RICH2 control doesn't lay out the visible region, so after
Thaw the view comes back blank -- only the last line pinned at the top -- until
a manual scroll forces a repaint. Since every stats poll carrying new daemon
log lines runs through this path, the log window blanked on each new line.

Thaw the control before scrolling so ShowPosition operates on a live control.
Keeps the batching win (Freeze still spans the appends); macOS/GTK, which
tolerate scroll-while-frozen, are unaffected either way.
got3nks added a commit that referenced this pull request Jul 14, 2026
…ist rows blanking on scroll/keyboard (#478) (#477)

* fix(remote-gui): stop the log view blanking on Windows by dropping Freeze/Thaw (#445)

#471 tried to fix the "log view goes blank on every new line" Windows
regression by thawing before scrolling, but it made no difference: the
AppendText still ran while the control was frozen. Appending to a frozen
wxTE_RICH2 (RichEdit) on Windows leaves its line/scroll metrics stale, so on
Thaw the view renders blank with the newest line pinned to the top until a
manual scroll forces a recompute. The Freeze()/Thaw() that #451 wrapped the
per-poll appends in is the actual culprit, not the scroll order.

Drop the Freeze()/Thaw() and append on a live control (as the pre-#451 code
did). Keep the two real wins from #451: the daemon's 5000-lines-per-poll cap
and the conditional SetDefaultStyle, plus one coalesced ShowPosition per poll
instead of per line (m_logBatching still suppresses the per-line scroll). The
per-line SetDefaultStyle was the dominant first-sync cost, so responsiveness is
retained without the frozen-append rendering corruption.

macOS/GTK recompute metrics regardless and were unaffected either way.

* fix(remote-gui): repaint list rows on scroll & keyboard nav on Windows (#478)

#348 replaced the vendored wxListMainWindow::OnScroll's synchronous
HandleOnScroll(event) with event.Skip() -- HandleOnScroll became a private
member in wx 3.3.3, so the macOS/Linux CI (on wx 3.3.x) stopped compiling. On
wxMSW the resulting deferred-scroll path (wxScrollHelperBase::HandleOnScroll ->
ScrollWindow) blits the retained rows and only invalidates the newly exposed
strip, which is then left unpainted: rows go blank on mouse-wheel, scrollbar and
pagination scrolling until a redraw is forced. Verified in the wx 3.2.10 and
3.3.x sources that the scroll+repaint mechanism is identical, so this is a wxMSW
platform behavior, not a wx-version one.

Rather than gate on platform or wx version (both fragile -- the former needs the
now-private HandleOnScroll, the latter breaks once Windows ships wx 3.3.3),
reimplement the synchronous scroll using only the public wxScrollHelper API
(GetViewStart / GetScrollLines / GetScrollPageSize / Scroll), mirroring
HandleOnScroll()/CalcScrollInc(): translate the scroll event into a target
position in scroll units and scroll to it.

Factor the "scroll + repaint" sequence into a shared ScrollListTo(x, y) helper
(Update() to flush pending paints so the blit is clean, Scroll(), then
ResetVisibleLinesRange() so the exposed rows repaint) and route both OnScroll
(scrollbar/wheel) and MoveToItem (keyboard nav) through it. This also fixes the
keyboard HOME/END/PgUp/PgDn blanking, which was the same bug from a different
path: MoveToItem only reset the visible-line range after Scroll() under
__WXMAC__, so on Windows the range stayed stale and keyboard scrolls came up
blank. The reset now runs on every platform via the shared helper, and the old
__WXMAC__-only workaround is gone.

Not skipping the event means the base scroll helper won't also scroll, so no
double-scroll. Works on every supported wx (>= 3.2.0) and every platform with no
version or platform guard; compiles against wx 3.3.3.

Refs #478
got3nks added a commit that referenced this pull request Jul 22, 2026
The amuleGUI log panes used a wxTE_RICH2 (RichEdit) control, which holds the
whole document and reflows O(n) on scroll, so a remote-GUI first-sync backlog
of tens of thousands of daemon-log lines made scrolling crawl and mispaint
(only the tail visible until a manual scroll).

Replace the three log/info panes (aMule Log, aMuleGUI Log, server info) with a
new CMuleLogCtrl backed by wxStyledTextCtrl (Scintilla), which renders only the
visible lines: full history is kept and scrolling stays O(visible) at any size,
with character-level selection/find preserved. Lines word-wrap; critical lines
are bold via per-line styles. Tail-scroll only fires when already at the bottom;
a scroll requested while the pane is hidden is deferred to the first idle once
it is on screen (in the base control, so all three panes share it). Removes the
RichEdit workaround stack (per-poll batching, the Freeze/Thaw lineage of
#451/#471/#477). The stc component ships with every platform's wxWidgets and is
requested only for the GUI library; the Windows portable bundles its DLL via the
existing GET_RUNTIME_DEPENDENCIES install step. Reported in #547.
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.

1 participant