Skip to content

perf(esp32): compile all stages (lib_deps, framework libs, core, sketch, local libs) in one shared job pool like PlatformIO #1559

Description

@zackees

Problem

PlatformIO (SCons) builds every translation unit (libraries, framework libraries, core, sketch) as nodes of one dependency graph at -j N, so any ready compile runs. fbuild's ESP32 orchestrator (crates/fbuild-build-esp/src/esp32/orchestrator/build.rs) runs them as serial stages. Each stage ends with a partly idle tail, and the next stage cannot start until it finishes.

# Stage (build.rs line on main) Serialization
1 Toolchain check → framework install check → log_toolchain_version (229, 240, 249) sequential awaits; spawns gcc --version every build
2 lib_deps compile, ensure_libraries (388) must finish before anything else compiles
3 …inside it, library_manager.rs:130 for lib in &installed one library at a time; files parallel within a library only
4 LDF / framework library selection (437) waits for stage 2, but needs only lib_deps sources, not objects
5 Project-as-library (526) separate serial step
6 Framework libraries (WiFi, FS, SPI…; 544; framework_libs.rs:136 loop) one library at a time; must finish before core starts
7 Core + sketch (750–776) the only stage already on a shared pool (#1545), with boot artifacts overlapped (#1548)
8 Local lib/ libraries (826) runs after core/sketch, not alongside
9 embed_files (851), compile DB (867) small, serial before link
10 Link → convert/size matches PlatformIO (the link must wait)

bench/blink has no libraries, so stages 2–6 and 8 are empty and the benchmark does not show this. A FastLED project pays for all of it on every cold build: ~30 FastLED unity TUs one library at a time, then 5 framework libraries one at a time, then core + sketch.

Proposal

Extend the #1545 pattern (compile_phases::compile_core_and_sketch with one Arc<Semaphore>) to the whole build:

  1. Resolve first, compile later. Collect every library's sources and include dirs (lib_deps, project-as-lib, LDF-selected framework libs, local libs), then run library selection on sources. It does not need lib_deps objects.
  2. One job pool. Submit every TU from every stage to a single FIFO semaphore, capped globally by the zccache per-core gate (perf: let the daemon's zccache run one compiler per core #1546), and ordered by dispatch_rank (C++ first, perf(build): dispatch C++ translation units before C and assembly #1553/fix(build): take compile permits in dispatch order #1558). Within that, put the longest TUs first, e.g. the FastLED unity files.
  3. Archive per library as soon as its objects are done. Each archive depends only on its own objects. The link waits on all archives, the core objects and the sketch.
  4. Remove the per-library for loops in library_manager.rs and framework_libs.rs, or turn them into producers that feed the pool.
  5. Small items: run the toolchain and framework ensure_installed concurrently, and cache the gcc --version probe per toolchain path.

Correctness constraints to keep:

  • Per-library flags and include dirs, and library.json build flags.
  • Library-selection shadowing rules.
  • Archive order on the link line.
  • .cmdhash rebuild signatures.
  • Fail-fast on the first compile error, with the join/drain soundness in parallel.rs.

Expected impact

For FastLED sketches on ESP32, the cold build should approach one parallel phase bounded by (total TU CPU ÷ cores). Today it is the sum of each stage's makespan plus its idle tail. For blink, nothing changes.

Acceptance

  • A FastLED example cold build (e.g. DemoReel100, esp32s3) with FBUILD_PERF_LOG_JSON shows a single compile phase, and a process sampler shows ≥ N-1 compilers busy throughout.
  • Before/after wall-time numbers are recorded (median of 3, 4 cores), alongside PlatformIO's phases from the benchmark's pio run -v breakdown (bench: break PlatformIO cold builds into phases for A/B with fbuild #1557).
  • The same firmware as before: identical selected libraries and link inputs.

Follow-up to #1537.

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

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions