clangd: Don't run slow clang-tidy checks

misc-const-correctness shows an extreme slowdown on large files, causing a >10x regression of clangd reparse time when enabled. Checks are often inadventently enabled e.g. by misc-* globs, as much as we wish this weren’t the case. I blocked this check in e78165f0ba1e2fbf72b36a36c8560645b69a168a, but a more systematic approach is needed.

Goals:

  1. don’t let slow checks into releases. We can’t assume check authors care about clangd.
  2. minimize feature churn between releases
  3. minimize maintenance toil
  4. document some fairly objective standard of “fast” that users and check authors can understand

Plan:

  • only run “fast checks” by default, as an additional filter applied to checks specified in .clang-tidy etc
  • keep a static “fast check” list, not a “slow check” list, per goal 1.
  • maintain this list by benchmarking on a known complex file (suggest clang/lib/SemaExpr.cpp) - addresses goal 4
  • “fast” means “regresses ParsedAST::build()” by less than 10%
  • benchmarking is done by a new mode in clangd --check, precise within <5%. Script updates the fast list (goal 3).
  • avoid noise by using some debounce: add a check to fast list if measurement <8%, remove it if measurement >13%. Addresses goal 2

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 16 (3 by maintainers)

Commits related to this issue

Most upvoted comments

https://github.com/clangd/clangd/issues/1337#issuecomment-1770214885

Ah, good point, they can use EnableSlowChecks: true while disabling the ones they don’t want with ClangTidy: Remove:. Seems like that use case is covered then!

That would require users to have a list available of which checks are slow. Maybe the documentation in https://clang.llvm.org/extra/clang-tidy/checks/list.html could have an extra column added for Good, Slow (with some measure of how slow maybe) or Unstable (crashes)

I’d very much like to add specific slow checks while disabling the bulk of them.

I run clang-tidy on cpp files manually inside CI, but running it is very slow. I’d like to know which checks are slowing down the check. Is there a list or way to do that?

The list of clang-tidy checks considered to be slow by clangd can be found here: https://github.com/llvm/llvm-project/blob/main/clang-tools-extra/clangd/TidyFastChecks.inc. clang-tidy also offers a flag to enable timing profiles per check to be printed with clang-tidy --enable-check-profile, which would probably be better in telling you which checks are slowing down your use-case specifically.

Sorry for leaving this thread unattended for a long while. We iterated over this with @sam-mccall couple times offline, but forgot to leave any artifacts.

Our final conclusions were towards:

  • Only let people to enable slow checks, and never the crashy checks.
  • Do this by having a new config option ClangTidy.EnableSlowChecks boolean, that defaults to False. (if need be we can have an orthogonal option to enable crashing-checks).

The rationale for never enabling crashy checks is, in practice that just causes support requests on clangd side that we can’t maintain and degrades experience for average user to the point of having an unusable clangd until they do a through investigation (or ask for support).

This still needs us to have a separate list of “slow” checks, @sam-mccall is going to be working on getting that piece landed this week.

What do you folks think about this?

The main issue seems to be that the slow check is automatically enabled by the glob which can be a surprise to users that don’t explicitly check all the options. Is there a way to get the check moved to a non-glob group or something like that, to allow for users that want the check (and the downside) to opt-in to it?

Perhaps this could take the form of a new Allowlist subkey under ClangTidy in the clangd config file, which does not allow globs, and explicitly enables the listed checks, overriding the performance section of the built-in blocklist.