perf(ui): render frames on demand instead of continuously
While theme effects were on (the default) the main loop drew every frame it could. Where vsync is off (offscreen, some drivers, remote sessions) an idle wallet spun at ~3,000 fps, 88% of a core; with vsync it still drew every refresh. Frames are now paced by what needs them: - full rate while there is input, a held key, a window appearing or settling, a smooth scroll or the UI sweep; - ambient (30 fps focused, 10 fps unfocused) for theme effects, the acrylic backdrop, avatar animations and notifications; - progress (10 fps focused, 4 fps unfocused) for UI that changes without input. The updater and bootstrap downloads, console commands, lite-wallet operations, seed migration, the loading overlay and the lock-screen countdowns ask for it with material::RequestProgressFrame(); - otherwise idle, as before: wait for events, with a housekeeping wake every 2 s (5 s unfocused). A software frame cap (0.9x the display refresh) bounds the loop where vsync is off, and hidden, occluded or minimized windows get no ambient frames. Reduce Motion freezes the theme-effect clock (ThemeEffects::setMotionFrozen), so it needs no ambient frames either. The displayed-balance roll goes through one clamped StepDisplayLerp (balance_lerp.h). An idle-length frame pushed dt*speed past 1, so the roll overshot, and under Reduce Motion's speed of 999 it diverged to inf/NaN. The classic layout had its own copy of the old code. Idle CPU, Lite build, offscreen (no vsync): 88% -> 5% of a core with effects on, and 91% -> 3% with effects saved off (with the previous commit). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
#include "services/wallet_security_workflow_executor.h"
|
||||
#include "ui/explorer/explorer_block_cache.h"
|
||||
#include "ui/windows/balance_address_list.h"
|
||||
#include "ui/windows/balance_lerp.h"
|
||||
#include "ui/windows/balance_recent_tx.h"
|
||||
#include "ui/windows/console_input_model.h"
|
||||
#include "ui/windows/console_model.h"
|
||||
@@ -77,6 +78,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <cstdlib>
|
||||
@@ -9300,6 +9302,45 @@ void testWalletIndex()
|
||||
#endif // !_WIN32
|
||||
}
|
||||
|
||||
// The displayed-balance roll must never overshoot, must land on the target after an idle-length
|
||||
// frame, and must survive Reduce Motion and non-finite values (it used to flip between two wrong
|
||||
// values at dt*speed == 2 and diverge to inf/NaN under Reduce Motion's speed of 999).
|
||||
void testBalanceDisplayLerp()
|
||||
{
|
||||
using dragonx::ui::StepDisplayLerp;
|
||||
for (float dt : {1.0f / 240.0f, 1.0f / 60.0f, 0.25f}) {
|
||||
double disp = 0.0;
|
||||
const double target = 123.45678901;
|
||||
bool overshot = false;
|
||||
for (int i = 0; i < 4000 && disp != target; ++i) {
|
||||
StepDisplayLerp(disp, target, dt, 8.0f, false);
|
||||
if (disp > target) overshot = true;
|
||||
}
|
||||
EXPECT_FALSE(overshot);
|
||||
EXPECT_EQ(disp, target);
|
||||
}
|
||||
|
||||
double idle = 10.0;
|
||||
EXPECT_FALSE(StepDisplayLerp(idle, 20.0, 0.25f, 8.0f, false));
|
||||
EXPECT_EQ(idle, 20.0);
|
||||
|
||||
double instant = 1.0;
|
||||
EXPECT_FALSE(StepDisplayLerp(instant, 5.0, 1.0f / 60.0f, 8.0f, true));
|
||||
EXPECT_EQ(instant, 5.0);
|
||||
|
||||
double bad = std::numeric_limits<double>::quiet_NaN();
|
||||
StepDisplayLerp(bad, 7.0, 1.0f / 60.0f, 8.0f, false);
|
||||
EXPECT_EQ(bad, 7.0);
|
||||
|
||||
for (double target : {1.2e7, 2.1e8}) {
|
||||
double disp = 0.0;
|
||||
int steps = 0;
|
||||
while (StepDisplayLerp(disp, target, 1.0f / 60.0f, 8.0f, false) && steps < 10000) ++steps;
|
||||
EXPECT_TRUE(steps < 10000);
|
||||
EXPECT_EQ(disp, target);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
testConnectionConfig();
|
||||
@@ -9319,6 +9360,7 @@ int main()
|
||||
testParseDaemonRescanOutput();
|
||||
testNetworkRefreshRpcCollectors();
|
||||
testNetworkRefreshResultModels();
|
||||
testBalanceDisplayLerp();
|
||||
testOperationStatusPollParsing();
|
||||
testSecureVaultScope();
|
||||
testWalletSecurityController();
|
||||
|
||||
Reference in New Issue
Block a user