Skip to content

perf(StatusQ): run gentle incubation at a fixed 50% duty cycle - #22073

Open
alexjba wants to merge 2 commits into
perf/statusq-leaf-cost-extractfrom
perf/incubation-duty-cycle
Open

alexjba wants to merge 2 commits into
perf/statusq-leaf-cost-extractfrom
perf/incubation-duty-cycle

Conversation

@alexjba

@alexjba alexjba commented Aug 24, 2026

Copy link
Copy Markdown
Contributor
  • Gentle incubation pacing was derived from the screen's frame period, so the amount of work done per tick quietly differed between devices.
  • It now uses fixed constants — a 2 ms bite every 4 ms — so the pacing is the same everywhere and is something we can reason about when measuring.

Stacked on #22072.

@status-im-auto

status-im-auto commented Aug 24, 2026

Copy link
Copy Markdown
Member

Jenkins Builds

Click to see older builds (44)
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ a327e32 1 2026-08-24 19:01:35 ~14 min android/arm64 🤖apk 📲
✔️ a327e32 1 2026-08-24 19:01:42 ~14 min tests/nim 📄log
✔️ a327e32 1 2026-08-24 19:06:03 ~18 min tests/ui 📄log
✔️ a327e32 1 2026-08-24 19:08:21 ~20 min linux/x86_64 📦tgz
✖️ a327e32 13563 2026-08-24 19:14:00 ~5 min tests/e2e 📊rpt
✔️ a327e32 1 2026-08-24 19:14:53 ~27 min macos/aarch64 🍎dmg
✔️ a327e32 1 2026-08-24 19:22:48 ~35 min ios/aarch64 📱ipa 📲
✔️ a327e32 1 2026-08-24 19:31:20 ~43 min windows/x86_64 💿exe
✖️ a327e32 5287 2026-08-24 19:34:27 ~3 min tests/e2e-windows 📊rpt
✔️ 8b77efe 3 2026-09-01 15:09:13 ~11 min android/arm64 🤖apk 📲
✔️ 8b77efe 3 2026-09-01 15:29:43 ~31 min linux/x86_64 📦tgz
✔️ 8b77efe 3 2026-09-01 15:31:53 ~33 min windows/x86_64 💿exe
✖️ 8b77efe 13835 2026-09-01 15:38:07 ~14 min tests/e2e 📊rpt
✔️ 8b77efe 3 2026-09-01 15:46:16 ~47 min unknown 📱ipa 📲
✔️ 8b77efe 5518 2026-09-01 16:10:12 ~38 min tests/e2e-windows 📊rpt
✔️ 17c2973 6 2026-09-02 07:19:41 ~8 min android/arm64 🤖apk 📲
✔️ 17c2973 6 2026-09-02 07:31:27 ~19 min windows/x86_64 💿exe
✔️ 17c2973 6 2026-09-02 07:42:32 ~30 min linux/x86_64 📦tgz
✔️ 17c2973 6 2026-09-02 07:47:14 ~35 min unknown 📱ipa 📲
✔️ 17c2973 5538 2026-09-02 07:49:25 ~17 min tests/e2e-windows 📊rpt
✔️ caa277a 7 2026-09-04 13:08:56 ~26 min windows/x86_64 💿exe
✔️ caa277a 7 2026-09-04 13:20:53 ~38 min linux/x86_64 📦tgz
✔️ caa277a 13923 2026-09-04 13:29:21 ~14 min tests/e2e 📊rpt
✔️ caa277a 5624 2026-09-04 13:49:06 ~40 min tests/e2e-windows 📊rpt
✔️ caa277a 7 2026-09-04 14:59:59 ~2 hr 17 min unknown 📱ipa 📲
✔️ caa277a 8 2026-09-07 17:18:26 ~8 min android/arm64 🤖apk 📲
✔️ 5d430fa 9 2026-09-11 07:29:47 ~8 min android/arm64 🤖apk 📲
✔️ 5d430fa 8 2026-09-11 07:45:52 ~24 min unknown 📱ipa 📲
✔️ 5d430fa 8 2026-09-11 07:46:38 ~25 min linux/x86_64 📦tgz
✔️ 5d430fa 8 2026-09-11 07:46:39 ~25 min windows/x86_64 💿exe
✔️ 5d430fa 14056 2026-09-11 07:55:22 ~15 min tests/e2e 📊rpt
✔️ 5d430fa 5752 2026-09-11 08:21:04 ~34 min tests/e2e-windows 📊rpt
✔️ 131a022 9 2026-09-15 09:01:22 ~18 min windows/x86_64 💿exe
✔️ 131a022 9 2026-09-15 09:05:33 ~22 min unknown 📱ipa 📲
✔️ 131a022 9 2026-09-15 09:10:01 ~26 min linux/x86_64 📦tgz
✔️ 131a022 14107 2026-09-15 09:17:46 ~14 min tests/e2e 📊rpt
✔️ 131a022 5798 2026-09-15 09:19:56 ~18 min tests/e2e-windows 📊rpt
✔️ f995c03 11 2026-09-15 13:35:16 ~8 min android/arm64 🤖apk 📲
✔️ 5f6d574 12 2026-09-15 13:46:32 ~8 min android/arm64 🤖apk 📲
✔️ 5f6d574 11 2026-09-15 13:55:35 ~17 min windows/x86_64 💿exe
✔️ 5f6d574 11 2026-09-15 13:59:39 ~21 min unknown 📱ipa 📲
✔️ 5f6d574 11 2026-09-15 14:02:58 ~24 min linux/x86_64 📦tgz
✔️ 5f6d574 14119 2026-09-15 14:10:46 ~14 min tests/e2e 📊rpt
✔️ 5f6d574 5816 2026-09-15 14:16:28 ~20 min tests/e2e-windows 📊rpt
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ 7030c86 13 2026-09-15 14:52:12 ~8 min android/arm64 🤖apk 📲
✔️ 7030c86 12 2026-09-15 15:03:26 ~19 min windows/x86_64 💿exe
7030c86 12 2026-09-15 15:09:34 ~25 min linux/x86_64 📄log
✔️ 7030c86 12 2026-09-15 15:17:46 ~33 min unknown 📱ipa 📲
✔️ 7030c86 5826 2026-09-15 15:38:31 ~34 min tests/e2e-windows 📊rpt
✔️ 7f8c9a7 14 2026-09-15 16:02:31 ~8 min android/arm64 🤖apk 📲
7f8c9a7 13 2026-09-15 16:09:11 ~15 min unknown 📄log
✔️ 7f8c9a7 13 2026-09-15 16:10:51 ~16 min windows/x86_64 💿exe
✔️ 7f8c9a7 13 2026-09-15 16:19:53 ~25 min linux/x86_64 📦tgz
✔️ 7f8c9a7 14131 2026-09-15 16:27:21 ~14 min tests/e2e 📊rpt
✔️ 7f8c9a7 5829 2026-09-15 16:35:36 ~24 min tests/e2e-windows 📊rpt
7f8c9a7 14 2026-09-16 07:02:52 ~17 min unknown 📄log

@alexjba
alexjba marked this pull request as ready for review August 24, 2026 19:02
@alexjba
alexjba requested a balanced review from Copilot August 24, 2026 19:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@alexjba
alexjba force-pushed the perf/incubation-duty-cycle branch from a327e32 to 0378e66 Compare September 1, 2026 14:51
@alexjba
alexjba force-pushed the perf/incubation-duty-cycle branch from 0378e66 to 8b77efe Compare September 1, 2026 14:57
@alexjba
alexjba force-pushed the perf/incubation-duty-cycle branch from 8b77efe to 17c2973 Compare September 2, 2026 07:09
@alexjba
alexjba requested a review from a team as a code owner September 2, 2026 07:10
@alexjba
alexjba force-pushed the perf/incubation-duty-cycle branch from 6cb2680 to 17c2973 Compare September 2, 2026 07:11
@caybro
caybro requested a balanced review from Copilot September 2, 2026 09:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The regression test does not enforce the advertised exact cadence, and duplicated C declarations already exhibit signature drift.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 3
  • Review effort level: Balanced

Comment thread ui/StatusQ/tests/src/tst_incubationcadence.cpp
Comment thread ui/StatusQ/tests/src/tst_incubationcadence.cpp Outdated
Comment thread ui/StatusQ/tests/src/tst_incubationcadence.cpp Outdated
@alexjba
alexjba force-pushed the perf/incubation-duty-cycle branch from 17c2973 to caa277a Compare September 4, 2026 12:42
@alexjba
alexjba force-pushed the perf/incubation-duty-cycle branch from caa277a to 5d430fa Compare September 11, 2026 07:20
@alexjba
alexjba force-pushed the perf/incubation-duty-cycle branch from 5d430fa to 131a022 Compare September 15, 2026 08:42
@alexjba
alexjba requested a review from a team as a code owner September 15, 2026 13:26
@alexjba
alexjba force-pushed the perf/incubation-duty-cycle branch from 131a022 to f995c03 Compare September 15, 2026 13:26
@alexjba
alexjba force-pushed the perf/incubation-duty-cycle branch from f995c03 to 5f6d574 Compare September 15, 2026 13:38
The boosted incubation controller paced its gentle phase off the screen's
frame period: a bite of frameperiod/4 once per frame, which on the 60Hz the
bench process reports is 4ms every 16ms - a 24% duty cycle. Three quarters of
every metered load was the controller waiting for its next tick, and that
constant is what made preemptibility cost 4x and left a surface with 14ms of
work reading 56ms.

Neither quantity is a property of the refresh rate. The bite bounds how long a
posted event waits behind incubation; the interval bounds how much of the GUI
thread incubation takes. Both are absolute times, so they are constants now: a
2ms bite every 4ms.

Every measurement below comes from offscreen storybook benches that are not
part of this PR; they live on branch feat/storybook-wallet-loader.

Release, offscreen, whale profile, arms alternated between rounds, eight rounds
per arm at load average 3.5-6.2. Warm phase, before -> after:

  wallet section  t_first_asset_row  110.6-152.8 -> 51.0-74.2 (no overlap)
                  t_ready             92.7-130.3 -> 34.7-53.1
                  max_stall             9.6-16.2 -> 10.1-14.3
                  stalls_over_8ms    1-3 med 2   -> 1-3 med 1
  asset detail    t_content     53.7-89.8 med 65.1 -> 20.1-42.9 med 27.2
                  cold t_content 48.9-66.5 med 50.3 -> 29.0-35.4 med 34.7
                  max_stall       4.3-9.8 med 7.4 -> 5.3-7.0 med 6.6
                  cold max_stall 8.4-12.9 med 12.3 -> 9.2-11.3 med 9.8

Both surfaces are inside their wall-clock budgets for the first time, with an
object graph identical to before, run for run.

Halving the bite is not what did it: a bite is a lower bound on the block it
produces, because incubateFor() returns only after finishing the object it is
midway through creating. Across every arm measured, incubated blocks stayed in
the same 4-7ms band whether the budget was 2ms or 4ms. Only the duty cycle
moves the wall clock, which is why the two metrics stopped opposing each other.

The cadence paces every asynchronous Loader in the app, so it was also measured
away from the two wallet surfaces it was chosen on. A chat section load (1000
chats / 2000 messages, offscreen, eight rounds per arm alternated) reproduces
the result with no change in shape - warm t_first_message_row 196.7-382.1 med
254.2 -> 121.9-173.0 med 145.8, cold 607.9-701.9 med 653.6 -> 473.1-551.3 med
487.5, max_stall unmoved in both phases, objects_settled 19131 on all 32 rows
of both arms. An interaction bench scrolling a list through repeated section
loads with a gentle hint held, counting frames on QQuickWindow::afterAnimating
against control windows of the same scroll with nothing incubating, is better
or equal at every frame load against the old cadence on a 60Hz display; on a
120Hz display it costs 2-3.5 points of late-frame rate at light frame load,
with the late-frame count unmoved because the incubation window is 10-16%
shorter.

That is the complement of the load result: the duty cycle is the load time and
the bite is not, the bite is the frame cost and the duty is not. Halving the
bite at constant duty more than halves the late-frame rate; a third less duty
barely moves it. The new test pins all three constants with the reason each one
is what it is.

The gentle window, the hint mechanism, the boosted phase and the idle poll are
untouched; PR #21921 still owns those.
@alexjba
alexjba force-pushed the perf/incubation-duty-cycle branch from 5f6d574 to 7030c86 Compare September 15, 2026 14:43
…laration

The controller test declared the install function with three arguments
while the export takes four, so its boost gap was whatever sat in the
register. The cadence test now installs the shipped configuration and
compares the bite and interval exactly instead of by one-sided bounds.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.

4 participants