Skip to content

Record each recipe's build time in the build jobs; pack the build jobs by time - #139

Merged
Tobias-Fischer merged 1 commit into
mainfrom
build-timings
Oct 23, 2026
Merged

Tobias-Fischer merged 1 commit into
mainfrom
build-timings

Conversation

@Tobias-Fischer

@Tobias-Fischer Tobias-Fischer commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

The build workflows cut each stage into jobs of 25 recipes in list order, so one heavy job often holds up its whole stage. In the jazzy full rebuild, a single job was running alone for 55% of the time on Linux.

vinca: the pin moves to RoboStack/vinca@c52ce0c, the merge of RoboStack/vinca#179 (--timings, --keep-file).

Recording: rs <distro> build-ci appends each recipe's build time to distros/<distro>/work/build_timings.jsonl, in GitHub Actions only. vinca-gha's new --keep-file keeps that file as each build job's artifact.

Collecting: robostack-bot update-build-timings merges the last week's artifacts into shared/build_timings/<platform>.json, as {recipe: {distro: seconds}}, and opens a PR.

  • It runs weekly on Mondays, together with the dependency reports.
  • It can also be triggered by a comment, the issue form or Actions › Run workflow.
  • Locally: pixi run python tools/build_timings.py.

Using: with times for the platform, rs <distro> gha passes vinca-gha --timings, using each recipe's average over the distributions. A recipe that's new to one distribution therefore still has a time.

  • vinca packs each stage's recipes into jobs by time, and builds each compatibility package right after its package.
  • Until a platform has times, its jobs are cut by count, as today.
  • A workflow over GitHub's 500 KiB limit is retried with fewer runners first.

Checked:

  • With the new vinca, rs jazzy gha --platform linux-64 on the full jazzy recipe set:
    • without times, it gives today's 117 jobs, each now ending with the artifact step;
    • with the measured jazzy times, it gives 219 jobs in 50 stages and a 440 KiB workflow.
  • Simulated with the measured times, that is 6.96 h → about 2.5 h on linux-64.
  • rs check and the 49 tool tests pass.

Also moves the vinca pin past the merged #176, #177 and #178:

  • #176: Windows exit codes;
  • #177: job names without the ros2- prefix;
  • #178: short CMake object paths on Windows.

None of these change build hashes. #178 makes the rosbag2_performance_benchmarking_msgs setting in shared/pkg_additional_info.yaml redundant; I'll remove that separately.

Labelled build:none: no packages change, so only the checks run.

🤖 Claude (AI assistant), on behalf of @Tobias-Fischer

🤖 Generated with Claude Code

…s by time

Each build-branch job records how long each recipe took to build (`rs
<distro> build-ci`, in distros/<distro>/work/build_timings.jsonl) and keeps
that file as an artifact (vinca-gha --keep-file). robostack-bot
update-build-timings (weekly, with the dependency reports) merges the last
week's into shared/build_timings/<platform>.json, {recipe: {distro: seconds}}.

With times for the platform, `rs <distro> gha` passes vinca-gha --timings
(each recipe's average over the distributions, so a recipe new to one
distribution still has a time): it packs each stage's recipes into jobs by
time and builds compatibility packages right after their package. Until then
the jobs are cut by count as before. A workflow over GitHub's size limit is
retried with fewer runners first.

The vinca pin moves to RoboStack/vinca@c52ce0c (#179: --timings, --keep-file).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tobias-Fischer added a commit that referenced this pull request Oct 23, 2026
vinca's Windows build scripts pass -DCMAKE_INTERMEDIATE_DIR_STRATEGY=SHORT for
every package since RoboStack/vinca#178 (pinned with #139, which has to be
merged before this PR).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Tobias-Fischer Tobias-Fischer added the build:none PR build: build no packages, only run the checks (tooling, CI or docs changes) label Oct 23, 2026
@Tobias-Fischer

Copy link
Copy Markdown
Collaborator Author

Thanks @baszalmstra @traversaro for the quick vinca review. Are you ok with this PR as well?

@baszalmstra

Copy link
Copy Markdown

yes! 👍

@Tobias-Fischer
Tobias-Fischer merged commit 8002b66 into main Oct 23, 2026
8 checks passed
@Tobias-Fischer
Tobias-Fischer deleted the build-timings branch October 23, 2026 06:05
@Tobias-Fischer

Copy link
Copy Markdown
Collaborator Author

Thanks both!

Tobias-Fischer added a commit that referenced this pull request Oct 23, 2026
* lyrical: on the shared conda-forge pinning, Qt6 mapping shared (from #82)

Drops the distribution's own conda-forge-pinning version and migrations: it uses
shared/pinning/conda_forge.yaml (2026.10.09.13.11.31), with the package fixes the new
pins needed. Other distributions keep their own pinning version until their PR; their
conda_build_config.yaml only gets the comment of the new shared openexr override
(the value, 3.4, is what they pin already).

shared/robostack.yaml maps the Qt5 rosdep keys to Qt6 (qt6-main, pyqt6), so lyrical's
per-package Qt workarounds go. humble and jazzy keep Qt5 through overrides that their
own sync PRs add: merge those first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* lyrical: rosdistro sync 2026-10-05

`rs lyrical update-snapshot`, with the fixes from the full-rebuild runs:
- lyrical: rtabmap without its tests (MSVC can't build test_optimizer_gtsam.cpp), as jazzy
- lyrical: python_qt_binding uses PyQt6 on macOS too (RoboStack/ros-lyrical#86)
- rcutils test: Python import only on humble and jazzy

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* lyrical: foxglove_bridge on Windows with /permissive

With C++20 (pulled in by lyrical's dependencies) MSVC enables /permissive-, which
rejects the Foxglove SDK 0.28's explicit specializations of ParameterView::get after
their first use (C2908/C3856 in parameter.hpp); humble/jazzy build it as C++17.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* lyrical: Rust message crates match the rosidl_buffer sequence layout [skip ci]

From Lyrical on, rosidl_runtime_c's primitive and string sequences carry two
trailing rosidl_buffer flags (ros2/rosidl#942), 32 instead of 24 bytes.
rosidl_runtime_rs 0.7 has the matching layout (ros2-rust/rosidl_runtime_rs#22),
and rclrs 0.8 uses it, but rosidl_generator_rs 0.5.0 still pins the generated
crates to 0.6, so every primitive-sequence field is misread: a Marker or
JointState round trip segfaults (RoboStack/ros-lyrical#17,
ros2-rust/ros2_rust#659). Pin 0.7. The generated code needs no other change.

Checked locally: the generated std_msgs crate pins 0.7, and with 0.7 the
visualization_msgs/Marker and sensor_msgs/JointState round trips are correct
(rmw Marker 480 bytes, as in C), while 0.6 segfaults.

Also point gz_ros2_control's plugin path hook at bin/ on Windows, where the
plugin DLL is installed (#104).

Evict the generator, every package that generates interfaces (each ships its
generated Rust crate) and gz_ros2_control from the PR build cache.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Update mutex_package configuration in vinca.yaml

Removed build number and upper bound for mutex_package.

* Clear evict_cache in ci.yaml

Reset evict_cache to an empty list.

* humble and rolling keep Qt5 for the Qt5 rosdep keys

This PR maps the Qt5 rosdep keys to Qt6 for every distribution. humble's own
override comes with its sync (#62), rolling moves to Qt6 with #99: until then
both get the override jazzy has (distros/<d>/robostack.yaml, layered over the
shared mapping with conda_index). Their generated recipes (humble linux-64,
win-64, osx-arm64; rolling linux-64, win-64) are identical to main's, except
for the new rcutils package test, which doesn't change any build hash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* rosbag2_performance_benchmarking_msgs: no own short-paths flag

vinca's Windows build scripts pass -DCMAKE_INTERMEDIATE_DIR_STRATEGY=SHORT for
every package since RoboStack/vinca#178 (pinned with #139, which has to be
merged before this PR).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Build branches: a newer run cancels the older one

A new push to a build branch (after a merge to main) brings the latest
recipes and workflow; the older run's plan is out of date. The new run skips
what the old one uploaded already, so only the packages its cancelled jobs
had built but not uploaded are built again. Re-run failed jobs only in the
newest run: re-running an older one would cancel the newer run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Build times from the jazzy full rebuild (linux-64, linux-aarch64, osx-arm64)

Per-recipe build times of the jazzy build-branch runs 39770179894,
39770118028 and 39770103102, from their job logs, so that this sync's
lyrical rebuild is already packed by time (osx-64 and win-64 weren't
finished yet). The weekly update-build-timings PR adds the times the build
jobs record from now on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Build times for all five platforms, also for lyrical's compatibility recipes

osx-64 and win-64 from the jazzy build-branch runs' job logs (39770120710 and
39907983469; 39770136120 and the finished jobs of 39907979075). Recipes those
runs didn't reach are estimated from their linux-64 time with a fit per
platform (osx-64: 37 s + 1.61 x; win-64: 77 s + 2.13 x; median error 33% and
20%), compatibility recipes at the platform's median (0.3-0.4 s).

Every ros-jazzy-<name> time is copied to ros-lyrical-<name> (under
"lyrical"), so that lyrical's compatibility recipes have a time until its own
build jobs record theirs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test_generate_gha: independent of the repository's build times

With shared/build_timings/win-64.json present, rs gha packs by time and first
retries an oversized workflow with fewer runners, so the batch-size retry test
now runs without timings; a new test covers the retry with timings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* rs gha: fall back to batching by count when a timed workflow stays too large

Packing by time keeps short stages apart (they share a job only up to two
minutes), so lyrical's win-64 workflow, whose jobs carry the long Windows
scripts, stayed at 621 KiB even with --runners 2. After the runner retries,
generate it without --timings; batching by count then merges the short
stages and the larger-batch retries shrink it as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* vinca with job budgets (RoboStack/vinca#180); rs gha without its own size retries

vinca-gha now keeps the workflow under GitHub's size limit itself (a job budget
spent where it shortens the workflow most, with or without build times), and
its Windows jobs call .scripts/build_win.bat instead of inlining it. rs gha
drops the retries with fewer runners and the fallback to batching by count;
larger batches remain the last resort when even the fewest jobs the batch
size allows don't fit. The check that the Windows workflow uses the
repository's build script looks for the call.

lyrical's full rebuild: win-64 149 jobs (483 KiB), linux-64 197 jobs (341 KiB).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Tobias Fischer <info@tobiasfischer.info>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Tobias-Fischer added a commit that referenced this pull request Oct 23, 2026
8282 times from the build-branch jobs' artifacts (tools/build_timings.py):
lyrical's full rebuild on all five platforms (632-1843 recipes each) and the
rest of jazzy's win-64 rebuild (338 recipes, replacing estimates from
linux-64).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tobias-Fischer added a commit that referenced this pull request Oct 23, 2026
…uild times since #139 (#143)

The build jobs now ride out the transient failures that interrupted lyrical's
and jazzy's rebuilds nine times on 2026-10-23:

- build-ci waits for the channel index also when rattler says "…, for which
  no candidates were found" (lowercase, wrapped over two lines), or "there are
  no viable options";
- build-ci retries downloads that break off ("error decoding response body");
- on_anaconda() retries network errors (e.g. a DNS failure on a macOS runner);
- uploads get five attempts, waiting 30 s, 1, 2 and 4 minutes (anaconda.org
  503s and Sigstore outages lasted minutes).

Also the build times recorded by the build-branch runs since #139: lyrical's
full rebuild on all five platforms and the rest of jazzy's win-64 rebuild.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build:none PR build: build no packages, only run the checks (tooling, CI or docs changes)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants