general improvement and bug fixes, cursor scaling, DMA-BUF routing and nested backend recovery
ignore performance-baseline.md more improvement and code quality fixes
This commit is contained in:
1 parent
405c74af9f
commit
73f21e20ce
23 files changed
+2287
-457
No files matched your search
@@ -1,155 +0,0 @@
|
||||
# Performance measurements
|
||||
|
||||
Use release builds and a fixed workload when comparing performance. Record the
|
||||
commit, output size, scale, refresh rate, graphics driver, and whether the session
|
||||
is nested or direct. Keep the nested preview visible: host occlusion changes
|
||||
rendering behavior.
|
||||
|
||||
## Collect a sample
|
||||
|
||||
```sh
|
||||
cargo build --release --locked -p ferese -p ferese-shell -p feresectl
|
||||
FERESE_TRACE_PERFORMANCE=1 target/release/ferese --backend nested \
|
||||
--grant-effects --grant-shell-control -- target/release/ferese-shell
|
||||
```
|
||||
|
||||
Measure idle, several windows, overview, Settings navigation, translucent popovers
|
||||
and screen capture separately. Wait for startup to settle, then repeat each sample.
|
||||
Record process CPU, child-process CPU, RSS, render attempts and damaged frames.
|
||||
Do not build or run unrelated workloads during the sample.
|
||||
|
||||
CPU percentages below use one core as 100%. These short samples describe observed
|
||||
behavior; they are not guarantees or hardware-session benchmarks.
|
||||
|
||||
## Direct frame timing
|
||||
|
||||
The DRM backend schedules each output against its own predicted presentation
|
||||
time. Render cost and a safety margin determine when compositing starts. Idle
|
||||
outputs wake on demand; callback-only updates are paced to the output refresh
|
||||
cycle without submitting unchanged buffers. Animation forecasts are restored
|
||||
before processing input or rendering another output.
|
||||
|
||||
For a direct session, enable `FERESE_TRACE_PERFORMANCE=1` and
|
||||
`RUST_LOG=ferese::render=debug` before starting Ferese. The timing records include
|
||||
the planned render start, actual render start, timer lateness, presentation
|
||||
target, DRM presentation timestamp, and request-to-presentation duration.
|
||||
Missed deadlines are counted against submitted frames' presentation targets;
|
||||
idle gaps do not count. Request-to-presentation timing starts at the compositor's
|
||||
redraw request. It does not include device input latency, client rendering before
|
||||
the request or the display's pixel response. Render cost measures CPU preparation
|
||||
and queueing. Feedback-driven margins allow conservatively for asynchronous GPU work.
|
||||
|
||||
Check sustained animation, idle wakeup, callback-only clients, and mixed-refresh
|
||||
outputs separately. Nested sessions do not exercise the DRM scheduler.
|
||||
|
||||
## Redraw and animation fallback counters
|
||||
|
||||
With the same environment variables, direct sessions report `redraw requests`
|
||||
by source file and line, with call counts, requested outputs and connected outputs.
|
||||
`render performance` adds per-output redraw requests and counts requests made
|
||||
while a render timer was scheduled or a frame was in flight. Compare these with
|
||||
`frames`, `no_damage_frames`, render time and missed deadlines; requests can
|
||||
coalesce and are not themselves rendered frames.
|
||||
|
||||
`animation fallback scheduling` reports watchdog arms, cancellations, wakeups,
|
||||
recovery requests and animations whose normal frame chain is intact. Ferese emits
|
||||
summaries every five seconds during redraw activity and on normal exit, resetting
|
||||
the fallback counters each time. When an animation loses its output's frame chain,
|
||||
the watchdog deadline is two refresh intervals later. Recovery keeps a requested
|
||||
final frame even if another output settles the animation while scheduling is
|
||||
unavailable. Idle, powered-off and disconnected outputs do not set that deadline.
|
||||
The watchdog is suppressed when a render is already scheduled or a page flip is
|
||||
pending. It does not replace DRM error recovery or diagnose a permanently lost flip.
|
||||
|
||||
The regression replays use a 60 Hz animation beside an idle 240 Hz output.
|
||||
The old fallback rule produces 60 unnecessary wakes in one simulated second;
|
||||
the new rule produces zero while the normal chain remains intact. Three cursor
|
||||
moves within one output require three output requests rather than the old six.
|
||||
These counts come from deterministic scheduling replays. They do not measure live
|
||||
DRM CPU use, latency or battery consumption. Measure those separately with the same
|
||||
hardware workload before claiming power savings.
|
||||
|
||||
## Settled overview damage
|
||||
|
||||
On 2026-10-02, a release-build comparison against `6f2951c` used four parked
|
||||
foot terminals in a private nested desktop: 1418 × 1692 pixels, 2× scale, 60 Hz,
|
||||
Intel Core Ultra 7 258V and Mesa 26.2.3. Ten-second process samples measured
|
||||
5.9% CPU before and 1.9% after stabilizing caption/thumbnail drawing order and
|
||||
removing forced full damage from unchanged rounded thumbnails.
|
||||
|
||||
A settled five-second interval changed from 300 damaged frames to zero.
|
||||
The nested backend still makes about 300 no-damage render attempts per interval.
|
||||
The change skips unchanged submissions; it does not alter nested scheduling.
|
||||
These short samples exclude host compositor CPU and do not measure battery
|
||||
discharge or direct DRM performance.
|
||||
|
||||
The opt-in regression checks a full settled interval, a real client content
|
||||
commit, and settling again. It fails against the original release.
|
||||
|
||||
```sh
|
||||
FERESE_TEST_OVERVIEW_DAMAGE=1 FERESE_TEST_BINARY=target/release/ferese \
|
||||
FERESE_TEST_CTL=target/release/feresectl \
|
||||
python3 scripts/tests/test_overview_damage_isolated.py
|
||||
```
|
||||
|
||||
## Idle shell audio polling
|
||||
|
||||
On 2026-10-02, the installed release shell was compared with the audio-event
|
||||
cache in private nested desktops on the same machine. Each release had ten
|
||||
seconds to settle, followed by three twenty-second samples without `perf`.
|
||||
CPU includes waited child processes; one core is 100%.
|
||||
|
||||
| Measurement | Periodic audio queries | Persistent audio watcher |
|
||||
| --- | --- | --- |
|
||||
| Combined CPU, sample range | 2.25–3.15% | 0.90% |
|
||||
| Combined CPU, median | 3.10% | 0.90% |
|
||||
| Shell CPU, median | 0.75% | 0.75% |
|
||||
| Child-process CPU, median | 2.35% | 0.15% |
|
||||
| Shell RSS | 32.3–32.4 MiB | 34.9 MiB |
|
||||
|
||||
A separate twenty-second `perf` sample recorded twenty `wpctl` executions before
|
||||
and zero afterward. The new connection observes sink properties, device routes,
|
||||
and default-sink metadata. Relevant events and control actions invalidate the
|
||||
cached reading; the existing `wpctl` reader preserves volume and device semantics.
|
||||
Disconnected subscriptions retain bounded polling, and missing sinks retry.
|
||||
Brightness and other status polling remain unchanged.
|
||||
|
||||
These short nested samples exclude the host compositor and do not measure battery
|
||||
discharge. Raw measurements and profiles were saved locally in
|
||||
`/tmp/ferese-shell-profile-20261002`.
|
||||
|
||||
The subscription regression starts its own PipeWire server, changes default
|
||||
metadata, mute and volume, removes a sink, restarts the server, and checks shutdown.
|
||||
It does not change the desktop's audio server.
|
||||
|
||||
```sh
|
||||
cargo test --release --locked -p ferese-shell native_subscription -- --ignored
|
||||
```
|
||||
|
||||
## Historical results
|
||||
|
||||
On 2026-09-27 at `08a5866`, two nested runs used a 1422 × 1696 output at 2× scale,
|
||||
reporting 60 Hz on a 120 Hz host. Samples lasted 5–10 seconds.
|
||||
|
||||
| Scenario | Compositor CPU, two runs | Shell CPU, two runs |
|
||||
| --- | --- | --- |
|
||||
| Idle, no application window | 5.3% / 5.8% | 1.5% / 1.6% |
|
||||
| Overview with one terminal | 18.6% / 16.2% | 1.3% / 1.4% |
|
||||
| After transitions | 6.6% / 6.4% | 1.5% / 1.4% |
|
||||
|
||||
Compositor RSS increased from about 81–82 MiB to 91–92 MiB during the exercise.
|
||||
These samples do not establish a leak or long-term stability. A follow-up had
|
||||
lower rendering rates, so the original observations did not prove duplicate scheduling.
|
||||
|
||||
A 20-second status-worker comparison removed five commands per poll (15 to 10).
|
||||
Total measured CPU time including child processes fell from 2.41 to 1.90 seconds.
|
||||
The timing wrapper was included, and this was one comparison.
|
||||
|
||||
For push status delivery (`4bf0757` to `b0583eb`), a synthetic transport test
|
||||
measured median delivery delay of 129.398 ms before and 0.130 ms after. It excluded
|
||||
queries, UI dispatch, and painting. Visible shell samples suggested lower typical
|
||||
CPU, but an after-run spike raised the mean; they did not establish a robust
|
||||
average CPU saving.
|
||||
|
||||
These results predate later changes. Run fresh comparisons for current claims,
|
||||
and validate direct rendering and multiple monitors separately.
|
||||
+5
-2
@@ -42,8 +42,11 @@ remembered InputCapture grants are not supported. InputCapture forwards local
|
||||
input; it does not inject remote input.
|
||||
|
||||
Wallpaper approval copies the image into Ferese's data directory and updates the
|
||||
config. Set `theme.background.lock-path` for a separate lock-screen image; otherwise
|
||||
it follows the desktop wallpaper.
|
||||
active light or dark appearance in the config. The other appearance keeps its
|
||||
wallpaper. A desktop-only change keeps the current lock-screen image, and a
|
||||
lock-screen-only change keeps the desktop image. Set `theme.background.lock-path`
|
||||
for a shared lock-screen image, or override it under `theme.light.background` and
|
||||
`theme.dark.background`. Without a lock-screen path, it follows the desktop wallpaper.
|
||||
|
||||
Global shortcuts cannot replace Ferese bindings or reserved escape/console keys.
|
||||
They stop when the app session closes. They never activate on the lock screen.
|
||||
|
||||
Reference in new issue
Block a user