-
-
Notifications
You must be signed in to change notification settings - Fork 394
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
perf(linter): make all rules share a diagnostics vec #5806
perf(linter): make all rules share a diagnostics vec #5806
Conversation
Your org has enabled the Graphite merge queue for merging into mainAdd the label “0-merge” to the PR and Graphite will automatically add it to the merge queue when it’s ready to merge. Or use the label “hotfix” to add to the merge queue as a hot fix. You must have a Graphite account and log in to Graphite in order to use the merge queue. Sign up using this link. |
fa2534a
to
52696ff
Compare
CodSpeed Performance ReportMerging #5806 will not alter performanceComparing Summary
|
Just to check my understanding of the linter is correct:
Do I have that right? If so, this change does make some sense. But... benchmarks seem to show this actually making things slightly slower rather than faster (-0.2% to -0.5% change). It's hard to tell if that's just noise in benchmarks. You may want to add a dummy commit to re-run the benchmarks, and then revert the commit to run them again. If the perf drop shows consistently across 3 runs, then it's probably real. 0.5% is not much, so it's no big deal either way. But it seems counter-productive to make a change specifically to improve perf, if it actually does the opposite. If the perf drop is real, explanation may be that the additional cost of Presumably in real world usage, most rules will report 0 errors on 99% of files, because the programmer will fix (or disable) any lint errors pretty quickly. And if there are no errors, then there's no memory to copy, so this change doesn't gain anything, but on negative side it incurs the cost of (We could have our cake and eat it by replacing PS: Unrelated, but I also wonder if initial capacity of 128 is too high. Do files in general produce that many errors? If I'm right that 0 is the most common number of errors, it might be better not to allocate any initial capacity at all. |
Yes
I'll investigate those regressions. Locally, I was seeing a 7% perf improvement on the RadixUIAdoptionSection benchmark. Maybe it has to do with the number of rules?
I'll play around with the numbers and see what works best |
52696ff
to
09a4b31
Compare
I got a ~0.8% improvement by increasing the initial capacity to 512. This makes sense, as before each rule got a list with an initial capacity of 128. |
...And now it's even worse in CI... that's odd, I'll keep looking into it. |
Merge activity
|
## What This PR Does Each time a lint rule is run on a file, it will now store diagnostics in a shared vec instead of having its own list. This is done by moving `diagnostics` from `LintContext` to `ContextHost`. The motivating line of code can be found in `Linter::run` in `oxc_linter/src/lib.rs#145` ```rust rules.into_iter().flat_map(|(_, ctx)| ctx.into_message()).collect::<Vec<_>>() ``` Each `LintContext` allocates a new vec, and pushes diagnostics into it. After all run-related methods have been run, a new vec is created and those diagnostics are copied into it. This is `O(n+1)` allocations and `O(n)` copies, not to mention that allocations for the original vecs cannot be re-used since those vecs aren't dropped until after the new one is created.
09a4b31
to
3725d5d
Compare
@DonIsaac I'm not sure if you intended this to be merged, given that you were still investigating.
This is really odd, and worth investigating. If our CodSpeed benchmarks are that far off reality, we should try to fix that (or at least understand in what circumstances it happens). When you ran it locally, did you run with the same rules enabled as on CI? (i.e. was it exact like-for-like comparison?) How many errors does running all the rules on RadixUIAdoptionSection produce? If my assumption is correct that in real world most commonly the linter will produce 0 errors, and our benchmark fixtures produce loads, then perhaps we need new benchmark fixtures! |
## [0.9.6] - 2024-09-18 ### Features - 3bf7b24 linter: Make `typescript/no-duplicate-enum-values` a `correctness` rule (#5810) (DonIsaac) - 7799c06 linter/react: Implement `no-danger-with-children` rule (#5420) (Cam McHenry) ### Bug Fixes - f942485 linter: Remove all* remaining "Disallow <foo>" messages (#5812) (DonIsaac) - b5ad518 linter: Improve diagnostic messages for various lint rules (#5808) (DonIsaac) - 858f7af linter: Plugin prefix name for eslint-plugin-node (#5807) (DonIsaac) - 737ba1d linter: Fix some cases on ```AssignmentExpression``` for ```unicorn/consistent-function-scoping``` (#5675) (Arian94) - 148c7a8 linter: Replace bitwise AND (&) with logical AND (&&) in explici… (#5780) (kaykdm) - b4ed564 linter/no-unused-vars: Writes to members triggering false positive (#5744) (Dunqing) - e9c084a linter/no-unused-vars: False positive when a variable used as a computed member property (#5722) (Dunqing) ### Performance - 3725d5d linter: Make all rules share a diagnostics vec (#5806) (DonIsaac) - e978567 linter: Shrink size of `DisableDirectives` (#5798) (DonIsaac) - 1bfa515 linter: Remove redundant clone of diagnostics in context (#5797) (DonIsaac) - e413cad linter: Move shared context info to `ContextHost` (#5795) (DonIsaac) ### Refactor - 6dd6f7c ast: Change `Comment` struct (#5783) (Boshen) - 7caae5b codegen: Add `GetSpan` requirement to `Gen` trait (#5772) (Boshen) - 026ee6a linter: Decouple module resolution from import plugin (#5829) (dalaoshu) - 50834bc linter: Move `override_rule` to `OxlintRules` (#5708) (DonIsaac) - a438743 linter: Move `OxlintConfig` to `Oxlintrc` (#5707) (DonIsaac) - f61e8b5 linter: Impl serde and schemars traits for `LintPlugins` (#5706) (DonIsaac) - 20a7861 linter: Shorten `Option` syntax (#5735) (overlookmotel) - d8b612c oxc_linter: Prefer pass Enum instead of str `no_plus_plus` (#5730) (IWANABETHATGUY) - cc0408b semantic: S/AstNodeId/NodeId (#5740) (Boshen) --------- Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
What This PR Does
Each time a lint rule is run on a file, it will now store diagnostics in a
shared vec instead of having its own list. This is done by moving
diagnostics
from
LintContext
toContextHost
.The motivating line of code can be found in
Linter::run
inoxc_linter/src/lib.rs#145
Each
LintContext
allocates a new vec, and pushes diagnostics into it. Afterall run-related methods have been run, a new vec is created and those
diagnostics are copied into it. This is
O(n+1)
allocations andO(n)
copies,not to mention that allocations for the original vecs cannot be re-used since
those vecs aren't dropped until after the new one is created.