FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

feat(linter): add per-rule timings for type-aware linting (#22488) · oxc-project/oxc@0a75682 · GitHub

Commit 0a75682

Browse files
committed
feat(linter): add per-rule timings for type-aware linting (#22488)
Adds support for collecting rule timings from tsgolint. Adds a new kind of payload that contains timing information. Threads the `timing` state variable down through the lint runner builders for consistency with other similar pieces of state. I've updated the timing store merging code to be generic, so we can accept just about anything that can produce timing records. Then, we utilize that in the `tsgolint` code.
1 parent e0b35a1 commit 0a75682

7 files changed

Lines changed: 199 additions & 71 deletions

File tree

‎apps/oxlint/src/lint.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ impl CliRunner {
479479
.with_silent(misc_options.silent)
480480
.with_fix_kind(fix_options.fix_kind())
481481
.with_type_check_only(type_check_only)
482+
.with_timings(debug_timings)
482483
.build()
483484
{
484485
Ok(runner) => runner,

‎crates/oxc_linter/src/lib.rs‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -495,9 +495,16 @@ impl Linter {
495495

496496
let result = (diagnostics, disable_directives);
497497
if TIMINGS {
498-
rule_timing_store
499-
.expect("missing rule timing store")
500-
.merge(timing_recorder.expect("missing rule timing recorder"));
498+
let timing_recorder = timing_recorder.expect("missing rule timing recorder");
499+
rule_timing_store.expect("missing rule timing store").merge(
500+
timing_recorder.into_timings().into_iter().map(|(key, stat)| RuleTimingRecord {
501+
source: key.source,
502+
plugin_name: key.plugin_name.into_owned(),
503+
rule_name: key.rule_name.into_owned(),
504+
duration: stat.duration,
505+
calls: stat.calls,
506+
}),
507+
);
501508
}
502509
result
503510
}

‎crates/oxc_linter/src/lint_runner.rs‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ pub struct LintRunnerBuilder {
144144
silent: bool,
145145
fix_kind: FixKind,
146146
type_check_only: bool,
147+
timings: bool,
147148
}
148149

149150
impl LintRunnerBuilder {
@@ -156,6 +157,7 @@ impl LintRunnerBuilder {
156157
silent: false,
157158
fix_kind: FixKind::None,
158159
type_check_only: false,
160+
timings: false,
159161
}
160162
}
161163

@@ -189,6 +191,12 @@ impl LintRunnerBuilder {
189191
self
190192
}
191193

194+
#[must_use]
195+
pub fn with_timings(mut self, timings: bool) -> Self {
196+
self.timings = timings;
197+
self
198+
}
199+
192200
/// # Errors
193201
/// Returns an error if the type-aware linter fails to initialize.
194202
pub fn build(self) -> Result<LintRunner, String> {
@@ -200,7 +208,12 @@ impl LintRunnerBuilder {
200208
self.regular_linter.config.clone(),
201209
self.fix_kind,
202210
) {
203-
Ok(state) => Some(state.with_silent(self.silent).with_type_check(self.type_check)),
211+
Ok(state) => Some(
212+
state
213+
.with_silent(self.silent)
214+
.with_type_check(self.type_check)
215+
.with_timings(self.timings),
216+
),
204217
Err(e) => return Err(e),
205218
}
206219
} else {
@@ -258,6 +271,7 @@ impl LintRunner {
258271
tx_error,
259272
fs,
260273
diff_manager,
274+
rule_timing_store,
261275
)?;
262276
} else {
263277
drop(tx_error);

‎crates/oxc_linter/src/timing.rs‎

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ impl RuleTimingSource {
2424
}
2525

2626
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
27-
struct RuleTimingKey {
28-
source: RuleTimingSource,
29-
plugin_name: Cow<'static, str>,
30-
rule_name: Cow<'static, str>,
27+
pub struct RuleTimingKey {
28+
pub source: RuleTimingSource,
29+
pub plugin_name: Cow<'static, str>,
30+
pub rule_name: Cow<'static, str>,
3131
}
3232

3333
impl RuleTimingKey {
@@ -38,6 +38,17 @@ impl RuleTimingKey {
3838
rule_name: Cow::Borrowed(rule_name),
3939
}
4040
}
41+
42+
fn from_record(record: RuleTimingRecord) -> (Self, RuleTimingStat) {
43+
(
44+
Self {
45+
source: record.source,
46+
plugin_name: Cow::Owned(record.plugin_name),
47+
rule_name: Cow::Owned(record.rule_name),
48+
},
49+
RuleTimingStat { duration: record.duration, calls: record.calls },
50+
)
51+
}
4152
}
4253

4354
#[derive(Debug, Clone, Copy, Default)]
@@ -97,7 +108,7 @@ impl RuleTimingRecorder {
97108
self.timings.entry(RuleTimingKey::native(plugin_name, rule_name)).or_default().add(stat);
98109
}
99110

100-
fn into_timings(self) -> FxHashMap<RuleTimingKey, RuleTimingStat> {
111+
pub(crate) fn into_timings(self) -> FxHashMap<RuleTimingKey, RuleTimingStat> {
101112
self.timings
102113
}
103114
}
@@ -112,15 +123,19 @@ impl RuleTimingStore {
112123
Self::default()
113124
}
114125

115-
pub(crate) fn merge(&self, recorder: RuleTimingRecorder) {
116-
let local_timings = recorder.into_timings();
117-
if local_timings.is_empty() {
126+
pub(crate) fn merge<I>(&self, local_timings: I)
127+
where
128+
I: IntoIterator<Item = RuleTimingRecord>,
129+
{
130+
let mut local_timings = local_timings.into_iter().peekable();
131+
if local_timings.peek().is_none() {
118132
return;
119133
}
120134

121135
let mut timings = self.timings.lock().expect("rule timing store mutex poisoned");
122-
timings.reserve(local_timings.len());
123-
for (key, stat) in local_timings {
136+
timings.reserve(local_timings.size_hint().0);
137+
for record in local_timings {
138+
let (key, stat) = RuleTimingKey::from_record(record);
124139
timings.entry(key).or_default().add(stat);
125140
}
126141
}

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL