Skip to content

Limit var analysis #1674

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 29, 2022
Merged

Limit var analysis #1674

merged 7 commits into from
Apr 29, 2022

Conversation

mainej
Copy link
Contributor

@mainej mainej commented Apr 29, 2022

This PR adds config options to limit the amount of analysis that is done.

  • :var-usages false excludes var-usages from the analysis output
  • :var-definitions {:shallow true} includes var-definitions, but skips analysis of their bodies

If both options are set analysis is a little over 80% faster. This will be helpful for clojure-lsp, which can use them when scanning deps.

This PR also moves the :analysis config option to the top-level of :config, out of :output. Docs and tests have been updated to reflect this new location. To maintain backward compatibility, the code still accepts :analysis in the :output config.

Finally, this PR clarifies the meanings of :analysis and :skip-lint. The output will include :analysis only when the config includes :analysis. The :findings will be non-empty only if the config doesn't include :skip-lint. The code tries to minimize the work performed based on these settings.

I experimented with a :var-definitions false setting. It was easy to implement, and I have the code if you'd like it, but it doesn't affect performance much. The true performance gain comes from skipping the definition bodies, not from skipping their signatures.

Please answer the following questions and leave the below in as part of your PR.

mainej added 6 commits April 28, 2022 16:46
If you set {:output {:analysis {:var-definitions {:shallow true}}}}, the
names (and optionally metadata and arglists) of vars will be analyzed, but
their bodies will be skipped.

This is useful to analyze the skeleton of a namespace, without getting
any details. It is an expert option, and if you use it, you should not
expect linters to behave correctly anymore.

More specifically, the bodies of these forms are skipped:

- def
- defn
- defrecord
- defmethod
- plumatic schema; fn, def, defn, defmethod, defrecord
- protocol-impls
- fn
- letfn
- fn*
- bound-fn
@@ -18,7 +18,12 @@
subject to change."
[{:keys [:config :findings :summary :analysis]}]
(let [output-cfg (:output config)
fmt (or (:format output-cfg) :text)]
fmt (or (:format output-cfg) :text)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unclear to me why this code was moved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'll put this back... it was part of an intermediate refactoring where the logic for when to show the analysis got complicated and I didn't want to duplicate it. Now, the presence or absence of analysis is all that's needed so it'll be ok to duplicate.

:interop? interop?
:resolved-core? resolved-core?
:in-def (:in-def ctx)}))
(when (:analyze-var-usages? ctx)
Copy link
Member

@borkdude borkdude Apr 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make sense to me. The :analyze-*? flags are intended for "is clj-kondo used with the analysis option and which one exactly?". But this option is usually off, when clj-kondo is not being called from clojure-lsp. However, reg-var-usage! is necessary for linting.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:analyze-var-usages? is true by default, so this is really a check for whether the user has explicitly turned off var-usages. That means reg-var-usage! will still be run when linting. If you'd prefer a different name for this flag, let me know... I picked :analyze-var-usages? because it's consistent with the other existing :analyze-*? flags.

Copy link
Member

@borkdude borkdude Apr 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can make this more clearer because I'm pretty it will confuse me in the future. What about (not (:shallow-var-usages? ctx))? Or (:non-shallow-var-analysis? ctx)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying of a better name, but trying to avoid (:analyze-...? ctx) since that kind of implies that :analysis true was used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe (not (:skip-var-usage-analysis? ctx)) would be clearest? ("shallow" applies to var-defs, not var-usages.)

@@ -1876,7 +1883,8 @@
expanded (assoc expanded :visited [resolved-namespace resolved-name])]
;;;; This registers the original call when the new node does not
;;;; refer to the same call, so we still get arity linting
(when-not same-call?
(when (and (:analyze-var-usages? ctx)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

:config config
:expr %)))
opt-expr-children)
(when (:analyze-var-usages? ctx)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

;; save some memory
:expr (when-not dependencies expr)
:resolved-core? resolved-core?})))))
(when (:analyze-var-usages? ctx)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

@borkdude borkdude merged commit d012ab5 into clj-kondo:master Apr 29, 2022
mainej added a commit to mainej/clojure-lsp that referenced this pull request Apr 29, 2022
This decreases uncached startup time by 60-70%. See
clj-kondo/clj-kondo#1674.

This also triples the batch size of the dep analysis, since clj-kondo
seems to analyze about 3 times as many files in the same amount of time.
I don't have numbers on how much memory was being saved by batching
analysis, so that needs to be double-checked.

This also skips all linting, and analysis of var-usages for deps since
we don't use those. The performance gain is almost exclusively from
skipping var bodies, however, so that's the interesting part.
mainej added a commit to mainej/clojure-lsp that referenced this pull request Apr 29, 2022
This decreases uncached startup time by 60-70%. See
clj-kondo/clj-kondo#1674.

This also triples the batch size of the dep analysis, since clj-kondo
seems to analyze about 3 times as many files in the same amount of time.
I don't have numbers on how much memory was being saved by batching
analysis, so that needs to be double-checked.

This also skips all linting, and analysis of var-usages for deps since
we don't use those. The performance gain is almost exclusively from
skipping var bodies, however, so that's the interesting part.
ericdallo added a commit to clojure-lsp/clojure-lsp that referenced this pull request Apr 30, 2022
* Skip var bodies when analyzing deps

This decreases uncached startup time by 60-70%. See
clj-kondo/clj-kondo#1674.

This also triples the batch size of the dep analysis, since clj-kondo
seems to analyze about 3 times as many files in the same amount of time.
I don't have numbers on how much memory was being saved by batching
analysis, so that needs to be double-checked.

This also skips all linting, and analysis of var-usages for deps since
we don't use those. The performance gain is almost exclusively from
skipping var bodies, however, so that's the interesting part.

* Add clojure.test and re-frame details to full-project and referenced-file analysis

Co-authored-by: Eric Dallo <ericdallo06@hotmail.com>
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.

2 participants