name: Compile-time perf bench

# Cross-platform compile-time benchmark.  Validates the predictions
# made in doc/architecture/compile-time.md against the eulernest CI
# runner (Linux + g++ on ARM64).
#
# Specifically tests whether:
#   1. FAST_TEST_BUILD=ON delivers the ~40 % wall-time reduction on
#      Linux + g++ that was predicted from `-ftime-trace` profiling
#      (recall: on Apple clang + Apple M1 it was net-neutral).
#   2. ccache hit rate is in the predicted 80%+ range on a warm
#      rerun (where the macOS-local hit rate was 0 % due to
#      Apple-clang + PCH friction).
#
# When run:
#   * push to main (after PR #19 lands)
#   * workflow_dispatch (manual trigger for ad-hoc verification)
#
# NOT run on every PR — this is a perf data-collection job, not a
# correctness gate.  Pollutes the summary with timings but does not
# block merges.

# ─── DISABLED auto-trigger 2026-05-26 ──────────────────────────────────────
# Same precaution as `.gitea/workflows/doxygen-pages.yml`: while we work
# through the pages-branch + CI-push issue surfaced during the v0.10.0
# merge, every workflow that auto-fires on main is restricted to
# `workflow_dispatch` only.  Manual reruns from the Gitea UI continue
# to work; transient failures no longer clutter the run history.
#
# To re-enable: uncomment the `push:` block below.
#
# on:
#   push:
#     branches:
#       - main
#     paths:
#       - "code/CMakeLists.txt"
#       - "code/tests/**/CMakeLists.txt"
#       - "code/include/**"
#       - ".gitea/workflows/perf-compile-time.yml"
on:
  workflow_dispatch: {}

jobs:
  compile-time-matrix:
    runs-on: eulernest
    container:
      image: git.eulernest.eu/conformallab/ci-cpp:latest
      options: "--memory=2400m --memory-swap=2400m"

    steps:
      - uses: actions/checkout@v4

      - name: Install ccache (idempotent)
        run: |
          which ccache >/dev/null 2>&1 || apt-get install -y --no-install-recommends ccache

      # ─── Run 1: baseline (PCH OFF, Unity OFF, ccache cleared) ──────
      - name: "Run 1: cold baseline (no PCH, no Unity, no ccache)"
        run: |
          ccache -C >/dev/null 2>&1 || true
          rm -rf build-baseline
          cmake -S code -B build-baseline -G Ninja \
              -DWITH_CGAL_TESTS=ON \
              -DCONFORMALLAB_USE_PCH=OFF \
              -DCMAKE_UNITY_BUILD=OFF \
              -DCONFORMALLAB_USE_CCACHE=OFF
          start=$(date +%s)
          nice -n 19 cmake --build build-baseline --target conformallab_cgal_tests -j1
          end=$(date +%s)
          echo "PERF baseline_wall=$((end - start)) s"
          echo "PERF_BASELINE_WALL=$((end - start))" >> $GITHUB_ENV

      # ─── Run 2: PCH only ──────────────────────────────────────────
      - name: "Run 2: PCH only (Unity off, ccache off)"
        run: |
          ccache -C >/dev/null 2>&1 || true
          rm -rf build-pch
          cmake -S code -B build-pch -G Ninja \
              -DWITH_CGAL_TESTS=ON \
              -DCONFORMALLAB_USE_PCH=ON \
              -DCMAKE_UNITY_BUILD=OFF \
              -DCONFORMALLAB_USE_CCACHE=OFF
          start=$(date +%s)
          nice -n 19 cmake --build build-pch --target conformallab_cgal_tests -j1
          end=$(date +%s)
          echo "PERF pch_only_wall=$((end - start)) s"
          echo "PERF_PCH_WALL=$((end - start))" >> $GITHUB_ENV

      # ─── Run 3: default (PCH + Unity Build + #6 Dense→Core) ───────
      - name: "Run 3: default config (PCH + Unity + Dense→Core)"
        run: |
          ccache -C >/dev/null 2>&1 || true
          rm -rf build-default
          cmake -S code -B build-default -G Ninja \
              -DWITH_CGAL_TESTS=ON \
              -DCONFORMALLAB_USE_CCACHE=OFF
          start=$(date +%s)
          nice -n 19 cmake --build build-default --target conformallab_cgal_tests -j1
          end=$(date +%s)
          echo "PERF default_wall=$((end - start)) s"
          echo "PERF_DEFAULT_WALL=$((end - start))" >> $GITHUB_ENV

      # ─── Run 4: + FAST_TEST_BUILD (-O0 -g) ────────────────────────
      - name: "Run 4: default + FAST_TEST_BUILD=ON (-O0 -g for tests)"
        run: |
          ccache -C >/dev/null 2>&1 || true
          rm -rf build-fast
          cmake -S code -B build-fast -G Ninja \
              -DWITH_CGAL_TESTS=ON \
              -DCONFORMALLAB_FAST_TEST_BUILD=ON \
              -DCONFORMALLAB_USE_CCACHE=OFF
          start=$(date +%s)
          nice -n 19 cmake --build build-fast --target conformallab_cgal_tests -j1
          end=$(date +%s)
          echo "PERF fast_test_wall=$((end - start)) s"
          echo "PERF_FAST_WALL=$((end - start))" >> $GITHUB_ENV

      # ─── Run 5: ccache hit-rate validation ─────────────────────────
      - name: "Run 5: ccache hit-rate (rebuild build-default)"
        run: |
          ccache -C >/dev/null 2>&1 || true
          ccache --zero-stats >/dev/null
          # First rebuild: populate ccache.
          rm -rf build-cc
          cmake -S code -B build-cc -G Ninja \
              -DWITH_CGAL_TESTS=ON \
              -DCONFORMALLAB_USE_CCACHE=ON
          nice -n 19 cmake --build build-cc --target conformallab_cgal_tests -j1 >/dev/null
          ccache_first=$(ccache -s 2>&1 | grep -E "^\s*Hits" | head -1 | awk '{print $2}')
          # Second rebuild: expect cache hits.
          rm -rf build-cc-warm
          cmake -S code -B build-cc-warm -G Ninja \
              -DWITH_CGAL_TESTS=ON \
              -DCONFORMALLAB_USE_CCACHE=ON
          start=$(date +%s)
          nice -n 19 cmake --build build-cc-warm --target conformallab_cgal_tests -j1
          end=$(date +%s)
          warm_wall=$((end - start))
          ccache_stats=$(ccache -s 2>&1 | grep -E "Hits|Misses" | head -4)
          echo "── ccache stats after warm rebuild ──"
          echo "$ccache_stats"
          echo "PERF ccache_warm_wall=${warm_wall} s"
          echo "PERF_CCACHE_WARM_WALL=$warm_wall" >> $GITHUB_ENV

      # ─── Test correctness (last gate; perf data already collected) ─
      - name: Verify all configs produced working binaries
        if: always()
        run: |
          for build in build-baseline build-pch build-default build-fast; do
              if [ -d "$build" ]; then
                  ctest --test-dir "$build" -R "^cgal\." --output-on-failure --timeout 120 \
                      | tail -3
              fi
          done

      # ─── Final summary ─────────────────────────────────────────────
      - name: Compile-time perf summary
        if: always()
        run: |
          echo "══════════════════════════════════════════════════════"
          echo "  COMPILE-TIME PERF BENCH — Linux ARM64 / g++ / -j1"
          echo "══════════════════════════════════════════════════════"
          printf "  %-30s  %4s s\n" "Run 1: cold baseline"          "${PERF_BASELINE_WALL:-?}"
          printf "  %-30s  %4s s\n" "Run 2: + PCH"                  "${PERF_PCH_WALL:-?}"
          printf "  %-30s  %4s s\n" "Run 3: + PCH + Unity (default)" "${PERF_DEFAULT_WALL:-?}"
          printf "  %-30s  %4s s\n" "Run 4: + FAST_TEST_BUILD"      "${PERF_FAST_WALL:-?}"
          printf "  %-30s  %4s s\n" "Run 5: + ccache warm rerun"    "${PERF_CCACHE_WARM_WALL:-?}"
          echo "──────────────────────────────────────────────────────"
          echo "Predictions to validate vs Apple-M1 baseline:"
          echo "  ┃ FAST_TEST_BUILD: expected ~40 % faster than default"
          echo "  ┃ ccache warm:     expected ≤ 10 s (vs Apple's 55 s)"
          echo "──────────────────────────────────────────────────────"
          # Compute relative deltas
          if [ -n "${PERF_DEFAULT_WALL:-}" ] && [ -n "${PERF_FAST_WALL:-}" ]; then
              pct=$(awk -v d="${PERF_DEFAULT_WALL}" -v f="${PERF_FAST_WALL}" \
                  'BEGIN { printf "%.0f", 100.0 * (d - f) / d }')
              echo "  Δ FAST_TEST_BUILD vs default: ${pct} % wall reduction"
          fi
          if [ -n "${PERF_DEFAULT_WALL:-}" ] && [ -n "${PERF_CCACHE_WARM_WALL:-}" ]; then
              pct=$(awk -v d="${PERF_DEFAULT_WALL}" -v c="${PERF_CCACHE_WARM_WALL}" \
                  'BEGIN { printf "%.0f", 100.0 * (d - c) / d }')
              echo "  Δ ccache warm vs default:     ${pct} % wall reduction"
          fi
          echo "══════════════════════════════════════════════════════"
