[Docs] (Performance): anland glmark2 before/after

This commit is contained in:
2026-10-10 08:18:17 -04:00
parent 79afd8a8e0
commit 5f9c3d6947
+181
View File
@@ -0,0 +1,181 @@
# glmark2 on anland: the P15 present-wait stack, before and after
Measured 2026-10-10 on the anland Plasma desktop of the Lenovo TB321FU (Adreno 750). **Single runs, one
per arm and configuration**: windowed light scenes move about +-15 % run to run (see the per-scene
tables), so only differences well beyond that mean anything. Method and traps:
[glmark2-handoff.md](glmark2-handoff.md).
## Arms
| arm | commit | notes |
|---|---|---|
| before | `a759b4b7` (the `origin/feat/disaggregated` of that day) | server and container client built from the same commit |
| after | `eb08b0b1` (branch `p15stack`) | present-wait levers, hot-path TLS cut, small-store drain, share-group dirty-bit fix. The pushed tip `bbd555fd` is `eb08b0b1` plus one test-only line in `MG_Test/Pipe/TrackerTest.cpp`, so the measured runtime code is the pushed code |
| after+x2 | `eb08b0b1` | Magma only, `MOBILEGL_MAGMA_EXTRA_SWAPCHAIN_IMAGES=2` in the server process |
| stock | the original anland app and its container | the stock kgsl driver stack, same glmark2 binaries |
Server: NDK RelWithDebInfo for `android-30` (native TLS segment present in both libs). Client: Release
cross build in WSL. The server and client of an arm are a matched pair: a client of one commit against the
other commit's server is refused (`Refuse{WireFingerprint}` for every session, black desktop), so the
arms were switched as pairs (libs swapped, container restarted, app reopened).
## Device state and validity
- CPU pinned to 1.80 / 2.25 / 2.25 / 2.25 GHz (policy0/2/5/7), GPU 680 MHz (kgsl `thermal_pwrlevel` 4
is that pin, no cap below it). The `msm_performance` requests were released, and thermal-engine, the
perf HAL, the vendor perf service, performance and hyperschedule were stopped for the whole session
(all restarted afterwards).
- Sampled every 2 s during every run (CPU cur/max per policy, GPU cur/max/pwrlevel, zone and battery
temperatures): **every sample of every run shows the pinned frequencies exactly** (min = max = pin,
GPU 680 MHz, no cap). Peak CPU zone 72-88 C, GPU zone 62-75 C, battery 36.5-40.7 C. Battery 93-94 %
throughout (USB attached).
- Before each run the clocks fell to their lowest OPP and the CPU/GPU zones had to be below 46 C
(at least 45 s). The "battery <= 33 C between reps" cool-down was **not** applied (the battery sat at
35-40 C and the job was told to start without waiting); the frequency samples above are what validate
the runs.
- Screen probes every 15 s (two screenshots 1 s apart): no black frame in any scored MobileGL run, nor
in the scored stock runs. Two more stock fullscreen runs (1365, 1322) showed the known 19838-byte black
desktop mid-run and were discarded; the scored stock fullscreen run (1325) had none.
- glmark2 reported Surface Size 800x600 windowed and 2560x1600 fullscreen on every arm (tablet in
landscape, auto-rotate untouched). The MobileGL app's `extra_keys_mode` was set to `with_keyboard` for
the session so its fullscreen size equals stock's (the default shows the keys bar: 2560x1412); restored
afterwards.
- One run per arm and configuration.
## Scores (glmark2-es2-wayland, `-b :duration=5`)
| | stock | Espryt before | Espryt after | Magma before | Magma after | Magma after+x2 |
|---|---:|---:|---:|---:|---:|---:|
| es2 window 800x600 | 1038 | 1900 | 1839 (-3 %) | 1278 | 1289 (+1 %) | 1343 (+5 %) |
| ratio to stock | 1.00 | 1.83 | 1.77 | 1.23 | 1.24 | 1.29 |
| es2 fullscreen 2560x1600 | 1325 | 521 | 518 (-1 %) | 428 | 423 (-1 %) | 426 (0 %) |
| ratio to stock | 1.00 | 0.39 | 0.39 | 0.32 | 0.32 | 0.32 |
**Reading:** no before/after difference is outside run-to-run noise. Fullscreen runs are steady (scene
by scene within about 5 %) and the stack changes nothing on either backend. Windowed, the whole-score
deltas are within +-5 % and the per-scene swings flip sign between arms (Magma "build vbo=true" is -35 %
after but the same scene is -6 % in the +x2 arm, linear texture +47 % and cel shading +47 % after), which is
noise in 5 s samples, not an effect.
## Per-scene FPS
**windowed 800x600** (FPS, one run each; `*` = after differs from before by more than 10 %)
| scene | stock | Espryt before | Espryt after | Magma before | Magma after | Magma after+x2 |
|---|---:|---:|---:|---:|---:|---:|
| build vbo=false | 1185 | 1340 | 1359 | 1660 | 1676 | 1447* |
| build vbo=true | 1237 | 2688 | 2472 | 1782 | 1150* | 1677 |
| texture nearest | 1153 | 2184 | 2331 | 1377 | 1628* | 1512 |
| texture linear | 1173 | 2405 | 2226 | 1168 | 1712* | 1678* |
| texture mipmap | 1391 | 2065 | 2330* | 1641 | 1367* | 1504 |
| shading gouraud | 1335 | 1912 | 2359* | 844 | 1152* | 1323* |
| shading blinn-phong-inf | 1210 | 2711 | 2254* | 1667 | 1463* | 1583 |
| shading phong | 1087 | 2411 | 2394 | 1322 | 1185* | 1648* |
| shading cel | 1229 | 2572 | 2436 | 1100 | 1613* | 1530* |
| bump high-poly | 1520 | 2369 | 2128* | 1738 | 1632 | 1600 |
| bump normals | 1023 | 2375 | 2424 | 1696 | 1835 | 1645 |
| bump height | 1310 | 2451 | 2277 | 1590 | 1485 | 1695 |
| effect2d kernel=0,1,0;1,-4,1;0,1,0; | 1168 | 2033 | 2147 | 1562 | 1512 | 1350* |
| effect2d kernel=1,1,1,1,1;1,1,1,1,1;1,1,1,1,1; | 1250 | 2147 | 2208 | 1739 | 1113* | 1501* |
| pulsar light=false:quads=5:texture=false | 1131 | 2196 | 2327 | 1616 | 1761 | 1717 |
| desktop blur-radius=5:effect=blur:passes=1:sep | 881 | 947 | 620* | 746 | 804 | 764 |
| desktop effect=shadow:windows=4 | 921 | 748 | 580* | 691 | 702 | 944* |
| buffer columns=200:interleave=false:update-dis | 394 | 592 | 548 | 733 | 793 | 786 |
| buffer columns=200:interleave=false:update-dis | 395 | 868 | 556* | 821 | 821 | 794 |
| buffer columns=200:interleave=true:update-disp | 432 | 400 | 564* | 602 | 792* | 829* |
| ideas speed=duration | 755 | 522 | 668* | 686 | 681 | 634 |
| jellyfish | 1230 | 2097 | 2079 | 1651 | 1597 | 1590 |
| terrain | 402 | 479 | 477 | 423 | 428 | 429 |
| shadow | 1049 | 1829 | 1736 | 1434 | 1468 | 1351 |
| refract | 734 | 1024 | 1025 | 653 | 820* | 797* |
| conditionals f-steps=0:v-steps=0 | 1160 | 2388 | 2157 | 1497 | 1525 | 1468 |
| conditionals f-steps=5:v-steps=0 | 1109 | 2475 | 2110* | 1207 | 1610* | 1626* |
| conditionals f-steps=0:v-steps=5 | 1030 | 2308 | 2326 | 1770 | 1530* | 1582* |
| function f-complexity=low:f-steps=5 | 1091 | 2321 | 1949* | 1440 | 1283* | 1384 |
| function f-complexity=medium:f-steps=5 | 1075 | 2704 | 2414* | 1519 | 1486 | 1605 |
| loop f-loop=false:f-steps=5:v-steps=5 | 1018 | 2252 | 2454 | 1232 | 1179 | 1467* |
| loop f-steps=5:f-uniform=false:v-steps=5 | 1032 | 2335 | 2505 | 1562 | 1331* | 1379* |
| loop f-steps=5:f-uniform=true:v-steps=5 | 1188 | 2601 | 2312* | 1040 | 1440* | 1518* |
| **score** | **1038** | **1900** | **1839** | **1278** | **1289** | **1343** |
**fullscreen 2560x1600** (FPS, one run each; `*` = after differs from before by more than 10 %)
| scene | stock | Espryt before | Espryt after | Magma before | Magma after | Magma after+x2 |
|---|---:|---:|---:|---:|---:|---:|
| build vbo=false | 1658 | 613 | 621 | 476 | 473 | 468 |
| build vbo=true | 1601 | 718 | 700 | 543 | 554 | 530 |
| texture nearest | 1817 | 613 | 552 | 493 | 525 | 527 |
| texture linear | 1743 | 646 | 646 | 474 | 484 | 489 |
| texture mipmap | 1838 | 649 | 571* | 541 | 495 | 509 |
| shading gouraud | 1687 | 555 | 602 | 501 | 504 | 495 |
| shading blinn-phong-inf | 1606 | 501 | 530 | 491 | 428* | 490 |
| shading phong | 1753 | 592 | 576 | 496 | 473 | 475 |
| shading cel | 1675 | 577 | 575 | 476 | 460 | 495 |
| bump high-poly | 1629 | 525 | 574 | 514 | 500 | 510 |
| bump normals | 1628 | 606 | 579 | 496 | 493 | 533 |
| bump height | 1582 | 616 | 713* | 508 | 538 | 539 |
| effect2d kernel=0,1,0;1,-4,1;0,1,0; | 1083 | 491 | 534 | 420 | 421 | 416 |
| effect2d kernel=1,1,1,1,1;1,1,1,1,1;1,1,1,1,1; | 544 | 399 | 402 | 359 | 365 | 359 |
| pulsar light=false:quads=5:texture=false | 1498 | 564 | 504* | 383 | 368 | 383 |
| desktop blur-radius=5:effect=blur:passes=1:sep | 494 | 349 | 437* | 334 | 338 | 318 |
| desktop effect=shadow:windows=4 | 865 | 583 | 459* | 379 | 372 | 382 |
| buffer columns=200:interleave=false:update-dis | 341 | 497 | 410* | 365 | 357 | 357 |
| buffer columns=200:interleave=false:update-dis | 416 | 502 | 511 | 407 | 401 | 417 |
| buffer columns=200:interleave=true:update-disp | 373 | 507 | 453* | 411 | 412 | 396 |
| ideas speed=duration | 827 | 440 | 431 | 313 | 316 | 315 |
| jellyfish | 1462 | 476 | 538* | 294 | 289 | 282 |
| terrain | 104 | 143 | 144 | 127 | 127 | 127 |
| shadow | 628 | 569 | 583 | 453 | 444 | 437 |
| refract | 217 | 206 | 207 | 208 | 208 | 207 |
| conditionals f-steps=0:v-steps=0 | 1545 | 525 | 547 | 460 | 455 | 442 |
| conditionals f-steps=5:v-steps=0 | 2024 | 546 | 548 | 474 | 463 | 459 |
| conditionals f-steps=0:v-steps=5 | 1558 | 530 | 533 | 458 | 461 | 478 |
| function f-complexity=low:f-steps=5 | 1850 | 531 | 508 | 466 | 447 | 454 |
| function f-complexity=medium:f-steps=5 | 1965 | 550 | 547 | 466 | 468 | 466 |
| loop f-loop=false:f-steps=5:v-steps=5 | 2005 | 535 | 542 | 451 | 457 | 458 |
| loop f-steps=5:f-uniform=false:v-steps=5 | 1849 | 545 | 547 | 468 | 455 | 447 |
| loop f-steps=5:f-uniform=true:v-steps=5 | 1894 | 549 | 518 | 465 | 457 | 460 |
| **score** | **1325** | **521** | **518** | **428** | **423** | **426** |
## Engagement of the present-wait levers
- **Magma presents through a VkSwapchain.** The server logs `Set minImageCount = 5 (surface min 5, max 64,
extra 0)` and `Swapchain created, extent = 1600x2560, swapchain imageCount = 6` for the compositor's
on-screen session (the display surface, pre-rotated), and `surface min 11` swapchains (800x600, 2560x1600,
664x438, 1x1, ...) for the clients' window surfaces. The clients' frames themselves go to shared images.
- **`MOBILEGL_MAGMA_EXTRA_SWAPCHAIN_IMAGES=2` applies**: `Set minImageCount = 7 (surface min 5, max 64, extra 2)`
for the display swapchain, `13 (surface min 11 ... extra 2)` for the others. How the server gets an
environment variable: the app's server process only takes what its own process environment holds (the app
sets its list with `Os.setenv`; the server never reads `debug.mobilegl.env` or the config files), so the knob
was injected with the Android wrap property
`setprop "wrap.com.anland.consumer.mobilegl:mobilegl" "NAME=value"` before the app starts the process (empty
string clears it). The +x2 arm scored +5 % windowed and 0 % fullscreen: within noise.
- **The Magma "off-screen work ahead of the acquire" lever never logged.** The line `a frame's off-screen work
goes to the queue ahead of its window pass` appeared **0 times** in all three Magma "after" arms (glmark2
runs, the compositor, a browser WebGL page, window hide/show). The pre-acquire flush with pending off-screen
work did not happen on anland: the compositor's frames draw straight into the display image with no
off-screen pass in front of it, and the clients present to shared images, not to a swapchain image.
- **Espryt does render to framebuffer 0 of an EGL window surface**: the server logs `this process owns a display
(ServerDisplay installed); a ServerOwned window surface is served on its window`. The once-per-frame flush
runs when a frame binds framebuffer 0 after a user framebuffer; it has no log line or counter, so its
firing was not observed directly (no tracing, by request). No score effect either way.
- Net: on anland these levers cannot show up in glmark2. The wait they target (the display release gating
the first swapchain / window-buffer use) sits on the compositor's presentation to the Android surface, which
glmark2 only reaches through KWin's composition of its window.
## Functional check of the after build
- **Espryt after**: cold start (kwin +4.0 s, plasmashell +5.1 s, desktop on screen +6.6 s), swipe-away and
reopen (0.2 s), a browser WebGL page at 114-120 fps, idle visible / hidden / locked at 319 % / 28 % / 29 %
phone CPU, lock and unlock, hide and show: no fatal signal, no crash, desktop and page correct in the
screenshots.
- **Magma after**: cold start, reopen, the WebGL page (150+ fps), idle visible and hidden, and every glmark2
run were fine. **After waking the locked screen with the animated browser page open, the Magma server's
memory ran away**: system swap fell from 11 GB free to under 1 GB within seconds, the server logged
`VkBufferObject::Create failed: vmaCreateBuffer returned -1` and `Magma wire decline [UniformBufferBinding]`,
the low-memory killer then killed it with signal 9, and the app's restart aborted with
`DirectVulkan: the initial surface could not be created` while the screen was off. **The same sequence on
the before build (`a759b4b7`) failed the same way** (one run each), so the stack did not cause it. It is
worth chasing separately before trusting a long Magma desktop session with animated clients across
lock/wake. The glmark2 measurements ran without the browser page and without lock cycles and never lost
the server.