Skip to content

Orca port 4B-2: startup splash phases + progress bar (#13667, #14155); full-set preset load determinism + benchmark - #683

Merged
aceRage merged 4 commits into
mainfrom
port/orca-pkg-4b2
Oct 24, 2026
Merged

aceRage merged 4 commits into
mainfrom
port/orca-pkg-4b2

Conversation

@aceRage

@aceRage aceRage commented Oct 24, 2026

Copy link
Copy Markdown
Owner

Package 4B-2 of the Orca upstream catch-up (tests/orca_port_plan_remaining.md, section 3 4B-2): parallel vendor loading and startup progress. 2 upstream PRs ported: OrcaSlicer#13667 only its splash half (its PresetBundle half was already on main), OrcaSlicer#14155 adapted. 0 skipped. 2 Edge commits (test hooks and tests).

Bottom line: no change to how presets load. Parallel vendor loading, the ordered merge, the held-open splash and the CBOR cache came in with perf/startup on 2026-09-13 (17206cb, bc3b7dd, 11e73c6). That leaves this PR with the splash phase lines, a progress bar, and the tests and benchmark the plan asked for. The cache default is untouched (the owner decides that in 4B-3a).

Base: origin/main 0b3af03. Main has not moved since.

Ports

Upstream What changes Status
OrcaSlicer#13667 perf: speed up startup and show progress in splash screen (5a136a25d1) PresetBundle: OrcaFilamentLibrary first, other vendors in parallel, merged in order. GUI: the splash stays up until the main window shows and names each startup phase PresetBundle half already on main (17206cb stages A/B/C match upstream steps 1/2/3; bc3b7dd adds parallel parsing per file plus the cache; 11e73c6 holds the splash open). Splash phase lines Adapted (below)
OrcaSlicer#14155 Add startup progress bar to loading screen (8d84204aeb) A progress bar on the splash, stepped 5/30/70/85/95 Adapted (below)

Deviations from upstream, and why

  1. Phase lines go through g_active_splash, not the local scrn. Our splash can close itself on user input during a wxYield, so scrn may already be gone. There's no extra wxYield: SetText repaints with Update(), and the animation tick puts the line back every frame. Chinese keeps its double dots. "Loading current preset" reuses our already translated "Loading current presets".
  2. The bar is drawn into the frame bitmap. Upstream draws it in a paint handler; ours is drawn in SetText(text, progress). AdvanceFrame() reapplies it every animation frame (progress -1 keeps the last value), and the bar never goes back.
  3. Bar shape and colour. It's a slim rounded track under the loading line, inset clear of the card's rounded corners. Upstream's full-width bottom strip would be clipped by our rounded window shape. It's filled in the wordmark red instead of Orca teal.
  4. No SetText(100) before Destroy(). close_startup_splash() takes the splash down right after the main window shows, so a 100% frame would never be seen.
  5. New untranslated strings: "Loading printer & filament profiles", "Creating main window", "Showing main window". They show in English until the next gettext run.

Edge commits

  • PresetBundle::set_sequential_load_override / set_parse_cache_override (+ sequential_load(), parse_cache_enabled()). The two function-local statics that read ORCA_PRESET_LOAD_SEQUENTIAL / ORCA_PRESET_CACHE now go through these. With no override set they read the environment exactly as before. They exist so one test process can compare the load modes.
  • test_preset_load_full_set.cpp:
    • [.][Preset][PresetLoadFullSet] (determinism, hidden). It copies the whole shipped resources/profiles (59 vendor manifests) into a scratch data dir's system/ and adds user presets: one on a BBL system filament, a detached parent in base/ with a child of it (Fix user presets built on a detached preset vanishing #653), a process and a printer. Then it runs load_presets() five times: sequential with no cache (the reference), parallel with a cold cache, parallel with a warm cache, and parallel with no cache twice. It compares, line for line, every preset of all three collections in order (name, alias, inherits, vendor, system/default/visible, setting/filament/base ids, renamed_from, FNV-1a hash of the resolved config), the filament alias table (every holder of each alias, in lookup order), the vendor/model/variant list, and the selection after load_selections. It's hidden because it takes about 144 s (the 13k-file copy plus hashing); run it with "[PresetLoadFullSet]". The small synthetic [PresetLoadDeterminism] cases still guard the default run.
    • [.][Benchmark][PresetLoadBenchmark] (hidden): times load_presets() in four modes, ORCA_BENCH_RUNS runs each (default 5).

Conflicts with our own work

Tests

  • Build: edgebuild job 484 (vm) at ee380e3. Targets: libslic3r_tests, slic3rutils_tests, the app, and an install to C:/Dev/EdgeSlicerTest/pkg_4b2. The test filter was ~[NotWorking]~[.],[PresetLoadBenchmark], so that run included the full-set test, which was not yet hidden.
  • libslic3r_tests: 2351 cases, 2348 passed, 3 failed as expected (402815 assertions). The 3 are the known [!shouldfail] cases in test_mixed_filament and test_wipe_tower_estimate. slic3rutils_tests: all 1403 cases passed (19274 assertions).
  • The full-set determinism test passed: sequential == parallel cold == parallel warm == parallel, and parallel == parallel.
  • The last commit only adds the [.] tag to the full-set test and was not rebuilt.

Timings (system + user preset load, load_presets(), full shipped set, VM, 5 runs each)

These are without the GUI, from the hidden benchmark.

Mode median min max
sequential, no cache (upstream before OrcaSlicer#13667) 8068 ms 8042 8237
parallel, ORCA_PRESET_CACHE=0 3008 ms 2738 3118
parallel, cache on, cold (parses and writes the cache) 3311 ms 2740 3600
parallel, cache on, warm (= today's default on unchanged profiles) 3550 ms 3505 3575

Branch vs main: the load code is the same except that the two env flags are now read through a function, so main's numbers are the same rows. The win that OrcaSlicer#13667 promises (8.1 s to 3.0 s, -63%) has been on main since 2026-09-13. The warm cache costs about +0.5 s over cache-off; that's 4B-3a's decision. 4B-1's startup log put preset_bundle->load_presets at 3.2-3.8 s on a 16-model set, which matches.

G-code gate

Baseline _baseline 1009229 (CLI, scratch datadir). Main past it has only #650, post-processing scripts. Candidate = test copy C:/Dev/EdgeSlicerTest/pkg_4b2, edgebuild --gate, estimates ignored.

case                result             lines    -del    +add  hunks   cfg  est
x1c_cube            IDENTICAL          12321       0       0      0     0  same
x1c_benchy          IDENTICAL          98486       0       0      0     0  same
u1_cube             IDENTICAL          11098       0       0      0     0  same
u1_benchy           IDENTICAL         128144       0       0      0     0  same
u1_2col             IDENTICAL         149526       0       0      0     0  same
u1_t4               IDENTICAL         107372       0       0      0     0  same
h2d_benchy_2n       IDENTICAL         153939       0       0      0     0  same
h2c_benchy_2n       IDENTICAL         158235       0       0      0     0  same
voron_cube          IDENTICAL          12295       0       0      0     0  same
voron_benchy        IDENTICAL         176776       0       0      0     0  same
GATE_RESULT identical=10 config_only=0 diff=0 expected=0 failed=0 missing=0

No G-code change was expected either: the only non-test code is the splash (GUI) and the reading of two env flags.

Owner hand test

Test copy: C:/Dev/EdgeSlicerTest/pkg_4b2

  1. Cold start. Close EdgeSlicer, start the test copy, and time it with a stopwatch or the log timestamps ("begin to show the splash screen" to "main frame firstly shown") against a main install. Expect the same time; this PR doesn't change loading. On the splash, the slicing animation keeps moving. The line under the logo goes "Loading configuration..." > "Loading printer & filament profiles..." > "Creating main window..." > "Loading current presets..." > "Showing main window...". A thin red bar under it fills in steps and never goes back, and the splash closes when the window appears.
  2. Click the splash during startup: it closes and startup carries on (no crash).
  3. Printer switching. Switch X1C > U1 > H2D > X1C: presets, filament slots and flow-variant combos look the same as on main.
  4. Project presets. Open a project with project presets: they're listed and selected. Then File > New Project: they're gone.
  5. User presets, including detached ones. Your own filament/process presets are listed. A detached user preset and any preset inheriting it both appear with their own values.
    No printer needed. Mac: not needed (no platform-specific code; the OSX wxYield in SetText is kept).

…gress in splash screen

Upstream 5a136a2. Two halves; only the splash half is new to us.

PresetBundle.cpp (parallel vendor loading): superseded, not ported. Our
load_system_presets_from_json already does what OrcaSlicer#13667 does and more:
- 17206cb (2026-09-13): OrcaFilamentLibrary first into *this*, the other
  vendors parsed in parallel (tbb::parallel_for, grain 1) into their own
  bundles with *this* as base_bundle, merged sequentially in vendor order.
  This is OrcaSlicer#13667's step 1/2/3 one for one, plus validation-mode exceptions
  rethrown per vendor in order and an ORCA_PRESET_LOAD_SEQUENTIAL escape hatch.
- bc3b7dd: per-file parallel parse inside each vendor (BBL is the critical
  path) and the per-vendor CBOR parse cache (#255 atomic writes), with a
  thread-local C numeric locale per worker chunk (#222).
- 11e73c6: the splash is held open through startup (timer stopped,
  closed explicitly by close_startup_splash) - the same fix as upstream's
  dropping wxSPLASH_TIMEOUT - and stage B runs off the calling thread while
  the GUI keeps the splash animation ticking.

GUI_App.cpp (splash phase lines): ported. The splash now names the phase:
"Loading printer & filament profiles", "Creating main window", "Loading
current presets" (our existing, already translated string instead of
upstream's "Loading current preset") and "Showing main window". Adapted:
the line goes through the active-splash pointer (set_startup_splash_phase)
rather than the local scrn, because our splash can be closed by user input
under a wxYield; no extra wxYield (SetText repaints with Update(), and the
animation tick re-applies the line every frame); Chinese keeps its double
dots like the first line.

Deft
… screen

Upstream 8d84204. The splash gets a progress bar that steps with the
startup phases OrcaSlicer#13667 named: 5 (loading configuration), 30 (printer &
filament profiles), 70 (creating main window), 85 (current presets),
95 (showing main window). Same step values as upstream; the bar never
moves back.

Adapted to our splash, which is a composed bitmap with a slicing animation
rather than upstream's paint handler:
- SetText(text, progress = -1) draws the bar into the frame bitmap next to
  the loading line. AdvanceFrame() re-applies the last line every frame
  with -1, so the bar survives every animation frame at its last value.
- The bar is a slim rounded track under the loading line, inset clear of
  the card's rounded corners (upstream's full-width bottom strip would be
  clipped by our rounded window shape), filled in the wordmark's red
  instead of Orca teal.
- SetText now composes and sets the bitmap once instead of setting the bare
  frame and then the labelled one.
- No final SetText(100) before Destroy(): close_startup_splash() takes the
  splash down right after the main frame is shown, so a 100% frame would
  never be seen.

Deft
…m test and load benchmark

Edge-only, for package 4B-2. No change to how the app loads presets.

- PresetBundle::set_sequential_load_override / set_parse_cache_override and
  sequential_load() / parse_cache_enabled(). The two function-local statics
  that read ORCA_PRESET_LOAD_SEQUENTIAL and ORCA_PRESET_CACHE once now go
  through these: same environment semantics by default, but a test can
  compare the sequential and parallel loads (and cache on/off) inside one
  process, which the cached statics made impossible.

- test_preset_load_full_set.cpp [PresetLoadFullSet]: copies the whole
  shipped resources/profiles into a scratch data dir's system/ folder, adds
  user presets (one on a BBL system filament, a detached parent in base/
  with a child of it (#653), a process and a printer), and loads it with
  load_presets() five times: sequential without cache (the reference),
  parallel with a cold cache (writes it), parallel with the warm cache,
  and twice parallel without cache. Every preset of every collection must
  match line for line (order, name, alias, inherits, vendor, system /
  default / visible flags, setting/filament/base ids, renamed_from, and a
  FNV-1a hash of the resolved config), plus the filament alias table, the
  vendor/model/variant list and the selection after load_selections.

- [.][Benchmark][PresetLoadBenchmark] (hidden): times load_presets() on the
  same data dir in four modes - sequential/no cache, parallel/no cache,
  parallel/cache cold, parallel/cache warm - ORCA_BENCH_RUNS times each
  (default 5) and prints PRESET_LOAD_BENCH lines with median/min/max.

Deft
It passed in edgebuild job 484 but took 144 s on the VM (copying the
13k-file profile set and hashing every preset five times). The small
synthetic [PresetLoadDeterminism] cases keep guarding the default run;
this one runs on request with "[PresetLoadFullSet]". Tag-only change,
not rebuilt.

Deft
@aceRage
aceRage marked this pull request as ready for review October 24, 2026 14:52
@aceRage
aceRage merged commit 09412ba into main Oct 24, 2026
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