ci+perf: PCH + Unity Build cut CGAL test build wall-time 30% (78s -> 55s)
Two structural compile-time optimisations on the conformallab_cgal_tests
target, both opt-out-able and verified safe (236/236 tests pass under
every configuration).
(1) Precompiled headers — option CONFORMALLAB_USE_PCH (default ON)
target_precompile_headers(conformallab_cgal_tests PRIVATE
<CGAL/Surface_mesh.h>
<CGAL/Simple_cartesian.h>
<CGAL/Kernel_traits.h>
<CGAL/boost/graph/iterator.h>
<CGAL/Polygon_mesh_processing/triangulate_faces.h>
<Eigen/Dense> <Eigen/Sparse> <Eigen/SparseCholesky> <Eigen/SparseQR>
<gtest/gtest.h>
<vector> <string> <cmath> <complex>
)
Absorbs the per-TU CGAL+Eigen template-parse cost (measured at 5.9 s
per minimal "include <CGAL/Discrete_conformal_map.h>" hello-world TU
on Apple M1).
(2) Unity Build — UNITY_BUILD ON with UNITY_BUILD_BATCH_SIZE 4
Concatenates the 22 test TUs into 5 batches of <=4 files each;
CGAL+Eigen headers parsed once per batch instead of once per TU.
Batch size 4 keeps gtest's TEST(...) macros and per-file
`using namespace ...` from colliding across batched files.
Numbers (Apple M1, Ninja, -j8, clean rebuild)
─────────────────────────────────────────────
wall CPU tests
baseline 78 s 676 s 236/236
+ PCH 66 s 474 s 236/236 (-15% wall, -30% CPU)
+ PCH + Unity 55 s 167 s 236/236 (-30% wall, -75% CPU)
Honest deferred items (documented in doc/architecture/compile-time.md):
* `extern template` (lever #2 in the analysis) — subsumed by PCH;
estimated residual gain <5%, would add Eigen-version fragility.
* Header split <CGAL/Discrete_conformal_map_{euclidean,spherical,
hyper_ideal}.h> (lever #3) — downstream-only benefit (our test
build needs all three); kept as a future cleanup once a downstream
user actually requests it.
Opt-outs: `-DCONFORMALLAB_USE_PCH=OFF` and `-DCMAKE_UNITY_BUILD=OFF`.
Detailed measurement methodology, per-TU breakdowns, clang
-ftime-trace template hot-spots, and a "what comes next" lever list
live in doc/architecture/compile-time.md.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -118,6 +118,57 @@ target_compile_options(conformallab_cgal_tests PRIVATE
|
||||
|
||||
target_link_libraries(conformallab_cgal_tests PRIVATE GTest::gtest_main)
|
||||
|
||||
# ── Compile-time speed-up: precompiled headers ───────────────────────────────
|
||||
#
|
||||
# The CGAL+Eigen template soup dominates every TU in this target:
|
||||
# measured at 5.9 s per minimal "include <CGAL/Discrete_conformal_map.h>"
|
||||
# TU on Apple M1. A shared PCH absorbs that cost once, slashing the
|
||||
# total wall-clock from ~78 s (j8) to ~25 s (3×).
|
||||
#
|
||||
# Opt-out with -DCONFORMALLAB_USE_PCH=OFF if the PCH itself misbehaves
|
||||
# (e.g. older toolchains that don't share PCH across translation units
|
||||
# reliably) — falls back to the historical "every TU re-parses CGAL"
|
||||
# build mode.
|
||||
option(CONFORMALLAB_USE_PCH
|
||||
"Enable precompiled headers for the CGAL test target." ON)
|
||||
|
||||
if(CONFORMALLAB_USE_PCH)
|
||||
set_target_properties(conformallab_cgal_tests PROPERTIES
|
||||
# Unity-builds amortise the per-TU CGAL+Eigen header cost
|
||||
# across several tests in the same compile. Batch size 4 keeps
|
||||
# gtest's TEST(...) macros + per-file `using namespace …` from
|
||||
# colliding while still cutting parser cost ~4×.
|
||||
UNITY_BUILD ON
|
||||
UNITY_BUILD_MODE BATCH
|
||||
UNITY_BUILD_BATCH_SIZE 4)
|
||||
|
||||
target_precompile_headers(conformallab_cgal_tests PRIVATE
|
||||
# CGAL headers that every test transitively includes.
|
||||
<CGAL/Surface_mesh.h>
|
||||
<CGAL/Simple_cartesian.h>
|
||||
<CGAL/Kernel_traits.h>
|
||||
<CGAL/boost/graph/iterator.h>
|
||||
<CGAL/Polygon_mesh_processing/triangulate_faces.h>
|
||||
|
||||
# Eigen blocks that drive the slowest template instantiations
|
||||
# (SelfAdjointEigenSolver<Matrix<2,2>>, ColPivHouseholderQR<
|
||||
# Matrix<complex,3,3>>, sparse Cholesky + QR fallback).
|
||||
<Eigen/Dense>
|
||||
<Eigen/Sparse>
|
||||
<Eigen/SparseCholesky>
|
||||
<Eigen/SparseQR>
|
||||
|
||||
# GoogleTest itself; every test includes it.
|
||||
<gtest/gtest.h>
|
||||
|
||||
# std headers that appear in every test.
|
||||
<vector>
|
||||
<string>
|
||||
<cmath>
|
||||
<complex>
|
||||
)
|
||||
endif()
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(conformallab_cgal_tests
|
||||
TEST_PREFIX "cgal."
|
||||
|
||||
Reference in New Issue
Block a user