Skip to content

build: parallelize static-library compilation; flat static_variant lookup - #229

Merged
On1x merged 2 commits into
masterfrom
build/parallel-static-libs
Nov 1, 2026
Merged

On1x merged 2 commits into
masterfrom
build/parallel-static-libs

Conversation

@chiliec

@chiliec chiliec commented Nov 1, 2026

Copy link
Copy Markdown
Member

Summary

Two build-time changes, one with a large wall-clock effect and one small frontend win, plus a test.

1. CMAKE_OPTIMIZE_DEPENDENCIES ON (root CMakeLists.txt, libraries/chain/CMakeLists.txt)

With the Unix Makefiles generator a target does not start compiling until every target it links is fully archived. For static libraries that is pure serialization: nothing in graphene_chain starts until fc and graphene_protocol are done, and no plugin starts until database.cpp (the longest TU, ~80 s at -O2) finishes alone on one core. Executables still wait for everything they link.

CMAKE_OPTIMIZE_DEPENDENCIES (CMake >= 3.19; CI runs 3.28) removes those edges for static libraries while keeping dependencies on custom-command outputs and anything declared through add_dependencies. Two things in libraries/chain were defeating it and are removed:

  • add_dependencies(graphene_chain graphene_protocol graphene_utilities ...): the library-to-library edges already come from target_link_libraries; only build_hardfork_hpp is a real build-order dependency.
  • the generated hardfork.hpp listed as a source of graphene_chain.

Resulting graph (checked in the generated Makefile2): graphene_protocol depends on project_secp256k1 only; graphene_chain and every plugin depend on project_secp256k1 and build_hardfork_hpp only; vizd keeps all 33 of its dependencies.

Cold make -j8 vizd cli_wallet, same tree, same flags, M1 laptop:

wall user cores busy
before 805 s 1762 s ~2.4
after 305 s 1375 s ~4.8

Caveats: a fanless laptop throttles under a long serialized tail, which inflates the baseline; 4-vCPU CI runners will gain less because they have less idle capacity to fill. The direction is not in doubt: the critical path was fc -> protocol -> database.cpp -> plugins -> link, and it is now database.cpp -> link.

Ninja users are unaffected (Ninja already orders static libraries this loosely).

2. fc submodule bump to VIZ-Blockchain/fc#6

static_variant's position/type_info helpers were recursive class templates, so every TU that names all 107 operation alternatives paid O(N²) instantiations in the frontend. They are now constexpr functions over a pack-expanded array. Dispatch is unchanged; operations.o is byte-identical before and after, and a round-trip digest over every alternative is identical. ops.cpp 8.4 s -> 6.7 s; database.cpp unchanged (it is backend-bound).

A jump-table dispatch was tried and rejected: it tripled operations.o and slowed database.cpp ~15%. Details in the fc PR.

3. tests/consensus_sim/scenarios/test_operation_variant.cpp

New operation_variant suite: for each of the 107 alternatives, set the tag, raw pack/unpack, to/from fc::variant, copy/move/assign, checking which() throughout; pins vote=0, transfer=2, validator_equivocation=count-1; out-of-range tags rejected via set_which and via raw unpack. This is the guard for any future change to static_variant or to the order of operations.hpp.

Checks

  • Full make of every target on the pruned graph: exit 0 (confirms no missing generated-file dependency).
  • ctest -E '^consensus_sim$': 13/13 pass.
  • consensus_sim_tests -t operation_variant: pass; whole binary links and lists 135 cases.
  • fc header check compiles with Apple clang 17 and GCC 13 at -std=c++14 -Wall -Wextra.
  • vizd --version from the optimized build runs.

Merge order

fc#6 first, then this PR (the submodule pointer here already targets the fc commit).

…ncy libraries

With the Makefile generator every target waits for the targets it links to
be fully archived before any of its own objects start. Static libraries do
not link, so this is pure serialization: nothing in graphene_chain starts
until fc and protocol finish, and no plugin starts until database.cpp (the
longest TU) finishes alone on one core.

CMAKE_OPTIMIZE_DEPENDENCIES drops those edges for static libraries while
keeping dependencies on custom-command outputs and anything added through
add_dependencies. graphene_chain therefore keeps only build_hardfork_hpp as
an explicit dependency; the protocol/utilities edges already come from
target_link_libraries and were defeating the optimization. The generated
hardfork.hpp is no longer listed as a source for the same reason.

Cold make -j8 vizd cli_wallet on an 8-core laptop: 805 s -> 305 s wall,
user time 1762 s -> 1375 s, i.e. ~2.4 -> ~4.8 cores kept busy. A full make
of every target, 13/13 fast ctest and consensus_sim_tests pass on the
pruned graph.
…rips

Bumps fc to the non-recursive static_variant position lookup (fc#6):
ops.cpp 8.4 s -> 6.7 s, objects byte-identical.

Adds an operation_variant consensus_sim suite that, for each of the 107
alternatives, sets the tag, raw-packs and unpacks, converts to and from
fc::variant, and copies/moves/assigns, checking which() throughout; pins
the tag numbers of vote (0), transfer (2) and validator_equivocation
(count-1); and checks that out-of-range tags are rejected both via
set_which and via raw unpack.
@chiliec

chiliec commented Nov 1, 2026

Copy link
Copy Markdown
Member Author

CI timing note: the job durations on this PR (Docker build 10 min; tests 15/15/10 min) match PR #227's run (14/15/10 min). CI job time is dominated by ccache state, test runtime and image layers, not by compile ordering, so the win reported above is for cold/uncached builds (local dev, Docker production image, cache misses after a header change). No regression on CI either.

@On1x On1x added check-arm64 Run the label-gated arm64 build (ubuntu-24.04-arm) on this PR check-boost-range Also run the distro Boost 1.83 range-floor build labels Nov 1, 2026
@On1x
On1x merged commit fdab64a into master Nov 1, 2026
12 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

check-arm64 Run the label-gated arm64 build (ubuntu-24.04-arm) on this PR check-boost-range Also run the distro Boost 1.83 range-floor build

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants