Skip to content

Halve clang-tidy CI time: disable the implicitly-on analyzer, drop duplicate and dataflow checks#110

Merged
typeless merged 1 commit into
mainfrom
ci/tidy-speedup
Jul 18, 2026
Merged

Halve clang-tidy CI time: disable the implicitly-on analyzer, drop duplicate and dataflow checks#110
typeless merged 1 commit into
mainfrom
ci/tidy-speedup

Conversation

@typeless

Copy link
Copy Markdown
Owner

The tidy job takes ~10 min — second-longest in CI. Profiling (--enable-check-profile) found three compounding causes:

  1. clang-analyzer-* was never actually off. clang-tidy prepends its builtin default clang-diagnostic-*,clang-analyzer-* to any Checks list — omission does not disable, so the analyzer the config documents as omitted has been running in every CI tidy job. Now disabled explicitly (verify with clang-tidy --dump-config). clang-diagnostic-* stays: it's computed during parse anyway and keeps tidy aligned with -Wall -Werror.
  2. bugprone-unchecked-optional-access: dataflow-framework machinery, 38% of all matcher check time on representative TUs while emitting zero diagnostics here. Disabled, with a documented local invocation for optional-heavy changes.
  3. cert-* is mostly aliases of already-enabled bugprone/misc/readability checks, and an enabled alias runs the check againcert-dcl51-cpp + cert-dcl37-c tripled bugprone-reserved-identifier. The family is now cherry-picked to its 14 own-implementation checks (same pattern the config already uses for modernize/cppcoreguidelines).

Bonus correctness fix: the run-clang-tidy filter 'src/|test/' matches absolute paths, so any checkout under a path containing src/ (like ~/src/pup) swept third_party TUs into the run, where third_party/.clang-tidy's -* fails with no checks enabledmake tidy exited 1 locally while green on CI. The filter is now anchored to $(CURDIR)/(src|test)/.

Measured (local 8-core, full suite): wall 3m59s → 2m01s (−49%), CPU 1609s → 861s (−47%), exit 2 → 0. 4-TU A/B: 95.6s → 25.0s (−74%). Diagnostics on the profiled production TUs are byte-identical (43 = 43); only analyzer-family notes disappear, which is this config's long-stated intent. CI projection: tidy ~10 min → ~5 min.

🤖 Generated with Claude Code

https://claude.ai/code/session_01U5KUoGDhJEZYoiK9CkeXtz

Three findings, all profiled with --enable-check-profile:

1. clang-tidy prepends its builtin default 'clang-diagnostic-*,
   clang-analyzer-*' to any Checks list, so the analyzer this config
   documented as omitted has been running all along. Disable it
   explicitly. 4 representative TUs: 64s -> 25s wall.

2. bugprone-unchecked-optional-access is a dataflow-framework check
   costing 38% of all matcher check time (24s of 63s) while emitting
   nothing here. Disabled with a note to run it locally on
   optional-heavy changes.

3. cert-* is mostly aliases of already-enabled bugprone/misc/
   readability checks, and an enabled alias runs the check again
   (cert-dcl51-cpp + cert-dcl37-c tripled bugprone-reserved-identifier).
   Replaced the family with its 14 own-implementation checks.

Also anchor the run-clang-tidy file filter to $(CURDIR): the bare
'src/|test/' pattern matches absolute paths, so a checkout under a
path containing src/ (e.g. ~/src/pup) swept third_party TUs into the
run, where third_party/.clang-tidy's '-*' made clang-tidy fail with
'no checks enabled' - make tidy exited 1 locally while green on CI.

Full suite, local 8-core: 3m59s -> 2m01s wall (-49%), 1609s -> 861s
CPU (-47%), exit 2 -> 0. Diagnostics on production TUs are unchanged
(43 = 43 on the profiled set; only analyzer-family notes disappear).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U5KUoGDhJEZYoiK9CkeXtz
@github-actions

Copy link
Copy Markdown

PR metrics

Performance (gcc example, Linux)

Workload Instructions CPU time Page faults D1 miss LL miss Wall Peak RSS
parse n/a 0.44 s 14.1 k 1.1% 0.1% 0.461 s 32.8 MB
dry-run n/a 0.68 s 18.6 k 1.6% 0.1% 0.697 s 49.7 MB (+0.1MB)

Deterministic signals: page faults, peak RSS, and the cachegrind D1/LL miss rates (simulated cache, exact across runs). CPU time is user+sys from time(1); instructions read n/a on GitHub-hosted runners (virtualized, no PMU).

Test coverage (lines)

Overall Median file Min file Max file
85.1% 94.3% 0.0% include/pup/core/metrics.hpp 100.0% include/pup/core/arena.hpp

93 files · 13697/16104 lines covered

Deltas vs main@35e6b1d9e.

Updated for 19aa51f

@typeless
typeless merged commit 97fb186 into main Jul 18, 2026
11 checks passed
@typeless
typeless deleted the ci/tidy-speedup branch July 18, 2026 07:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant