Skip to content

macOS: export startup can cost 4 s before the first frame, and it tracks memory pressure rather than the code #593

Description

@EtienneLescot

On an 8 GB Mac mini M1, a headless openscreen export spent 4.2 s between emitting started and composing its first frame — 18 % of a 60 s export's measured interval, and 71 % of a 5 s one. Then it stopped doing so, on the same binary, with nothing changed.

What was measured

Decomposed from the CLI's own JSON events plus timestamps inside the renderer:

while it reproduced now
started → first progress 4208–4502 ms 481 ms
renderer domInteractive 3887 ms 15–355 ms
the whole of runExport 24 ms 24 ms

Same shipped 1.10.0 application, untouched, hours apart. Everything after the module graph was always fast: loading the project is 4 ms, the two <video> metadata probes are 13 ms and 6 ms, and Compositor::new is 2.4 ms including runtime MSL compilation of shaders.metal.

What it is not

Three hypotheses were measured and all three were wrong:

  • Runtime Metal shader compilation — 2.4 ms for the whole compositor init.
  • <video> probes scaling with media size — a 1.7 MB / 5 s source gives the same 4197 ms as a 50 MB / 60 s one.
  • CPU work — neither process burns any. Both sit in kevent64 / __workq_kernreturn; 14 CPU-seconds for a 23 s export.

It is also not the CLI window loading the editor's entry point. That was tried (#590) and measured at −0.1 % against a proper baseline.

What it most likely is

Memory pressure. While it reproduced the machine was at 387M unused / 2613M compressor with ~6.5 M swapouts; it is now 564M unused / 1837M compressor, 57 % free, and the cost is gone. Faulting ~1.8 MB of module chunks out of a 274 MB app.asar while the compressor is thrashing looks precisely like what was observed: several seconds of wall clock, no CPU, independent of the work being asked for.

That is a hypothesis. Nobody has recreated the pressure deliberately and watched the cost come back.

Why it is worth chasing anyway

  • 8 GB is the entry-level Apple Silicon machine, and the export is exactly the moment the app is competing with a browser and an editor for RAM. If this is the cause, real users hit it and it is invisible in any profile — it does not show up as CPU.
  • It lands inside the measured interval. The CLI emits started as soon as the window is created, so any startup latency counts against the export in benchmarks and in the user's perception alike.
  • The app.asar is 274 MB, of which the renderer needs about 1.8 MB. Whether that size costs anything under pressure is testable.

How to settle it

Reproduce the pressure deliberately — pin memory until the compressor is near where it was, then measure started → first progress on the shipped app — and if it returns, try the same with a smaller asar (or with asar: false) to see whether archive size is the lever. Until someone does that, the cause is unproven and no fix should be attempted on the strength of it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions