Skip to content

perf(linter): reduce unnecessary rule method executions to improve performance#8854

Closed
shulaoda wants to merge 4 commits intooxc-project:mainfrom
shulaoda:perf/reduce-unnecessary-rule-method-executions
Closed

perf(linter): reduce unnecessary rule method executions to improve performance#8854
shulaoda wants to merge 4 commits intooxc-project:mainfrom
shulaoda:perf/reduce-unnecessary-rule-method-executions

Conversation

@shulaoda
Copy link
Copy Markdown
Contributor

@shulaoda shulaoda commented Feb 3, 2025

We can make full use of should_run to avoid unnecessary iterations over nodes and rules.

@graphite-app
Copy link
Copy Markdown
Contributor

graphite-app bot commented Feb 3, 2025

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

@github-actions github-actions bot added A-linter Area - Linter C-performance Category - Solution not expected to change functional behavior, only performance labels Feb 3, 2025
@shulaoda shulaoda force-pushed the perf/reduce-unnecessary-rule-method-executions branch from e29e7b8 to 4470e6c Compare February 3, 2025 11:34
@shulaoda shulaoda marked this pull request as draft February 3, 2025 11:34
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Feb 3, 2025

CodSpeed Performance Report

Merging #8854 will improve performances by 8.67%

Comparing shulaoda:perf/reduce-unnecessary-rule-method-executions (e975e3a) with main (d6d13dd)

Summary

⚡ 3 improvements
✅ 30 untouched benchmarks

Benchmarks breakdown

Benchmark BASE HEAD Change
linter[RadixUIAdoptionSection.jsx] 2.6 ms 2.4 ms +7.62%
linter[cal.com.tsx] 1.2 s 1.1 s +8.04%
linter[checker.ts] 2.7 s 2.5 s +8.67%

@shulaoda
Copy link
Copy Markdown
Contributor Author

shulaoda commented Feb 3, 2025

Benchmarks breakdown

Benchmark BASE HEAD Change
linter[RadixUIAdoptionSection.jsx] 2.6 ms 2.3 ms +9.05%
linter[cal.com.tsx] 1.2 s 1.1 s +8.09%
linter[checker.ts] 2.8 s 3.5 s -20.85%

When running on my windows machine (13th Gen Intel(R) Core(TM) i5-13600KF 3.50 GHz), the performance of checker.ts significantly improved by 50%. I believe this is influenced by the configuration of each person's computer. At this point, I have not enabled the optimizations from #6600.

@shulaoda shulaoda force-pushed the perf/reduce-unnecessary-rule-method-executions branch from c4bb5b0 to a6c5dcd Compare February 3, 2025 14:39
@shulaoda
Copy link
Copy Markdown
Contributor Author

shulaoda commented Feb 3, 2025

Introducing bitflags did not result in a performance improvement, and in fact, it caused a slight decrease of around 2%. However, it benefits memory management and provides better maintainability, so I have decided not to roll it back.

@shulaoda shulaoda marked this pull request as ready for review February 3, 2025 15:05
@Dunqing Dunqing requested review from Boshen, camc314 and camchenry and removed request for Boshen, camc314 and camchenry February 5, 2025 03:00
Copy link
Copy Markdown
Member

@Boshen Boshen left a comment

Choose a reason for hiding this comment

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

I like the overall direction, but dislike requiring

    fn should_run(&self, _: &crate::ContextHost) -> crate::rule::ShouldRunMeta {
        crate::rule::ShouldRunMeta::IS_RUN_ONCE
    }

everywhere.

@shulaoda
Copy link
Copy Markdown
Contributor Author

shulaoda commented Feb 5, 2025

I like the overall direction, but dislike requiring

    fn should_run(&self, _: &crate::ContextHost) -> crate::rule::ShouldRunMeta {
        crate::rule::ShouldRunMeta::IS_RUN_ONCE
    }

everywhere.

By default, If use run, It shouldn’t require explicitly implementing should_run. Perhaps we can use a procedural macro to automate this? Do you have any good ideas?

@camchenry
Copy link
Copy Markdown
Member

Agreed with @Boshen: something like this is definitely worth doing, but maybe we can polish the experience a little bit more. My suggestion would be that maybe we can make it as part of the declare_oxc_lint! macro:

pub fn declare_oxc_lint(metadata: LintRuleMeta) -> TokenStream {

So maybe it would look more like this (without doc comments):

declare_oxc_lint!(
    SomeLintRule(IsRunOnSymbol),
    oxc,
    nursery
);

Not 100% sure how to parse it like that though, not too familiar with macros

@shulaoda
Copy link
Copy Markdown
Contributor Author

shulaoda commented Feb 6, 2025

So maybe it would look more like this (without doc comments):

declare_oxc_lint!(
    SomeLintRule(IsRunOnSymbol),
    oxc,
    nursery
);

Not 100% sure how to parse it like that though, not too familiar with macros

This doesn't seem feasible (because ( and ) cannot be parsed as a token), we can:

declare_oxc_lint!(
    SomeLintRule,
    oxc,
    nursery,
    IsRunOnSymbol,
);

or

#[derive(Debug, Default, Clone)]
#[should_run(is_run_once)]
pub struct PreferToBeObject;

@Boshen
Copy link
Copy Markdown
Member

Boshen commented Feb 6, 2025

Ok my decision is that the total amount of changes is not worth it for +8.67%, unless we find a better approach to get the same performance boost.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-linter Area - Linter C-performance Category - Solution not expected to change functional behavior, only performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants