Skip to content

Commit 81d43ed

Browse files
committed
feat(oxc_linter): reuse allocators
1 parent 8fb53b6 commit 81d43ed

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

crates/oxc_linter/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ mod globals;
1414
mod module_graph_visitor;
1515
mod module_record;
1616
mod options;
17+
mod pool;
1718
mod rule;
1819
mod service;
1920
mod utils;

crates/oxc_linter/src/pool.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use std::collections::VecDeque;
2+
use std::sync::{Arc, Mutex};
3+
4+
pub struct Pool<T> {
5+
items: Arc<Mutex<VecDeque<T>>>,
6+
factory: Arc<dyn Fn() -> T + Send + Sync>,
7+
}
8+
9+
pub struct PoolGuard<T: PoolDrop> {
10+
item: Option<T>,
11+
pool: Arc<Mutex<VecDeque<T>>>,
12+
}
13+
14+
impl<T: PoolDrop + Send> Pool<T> {
15+
pub fn new<F>(factory: F) -> Self
16+
where
17+
F: Fn() -> T + Send + Sync + 'static,
18+
{
19+
Self { items: Arc::new(Mutex::new(VecDeque::new())), factory: Arc::new(factory) }
20+
}
21+
22+
pub fn get(&self) -> PoolGuard<T> {
23+
let item = {
24+
let mut items = self.items.lock().unwrap();
25+
items.pop_front().unwrap_or_else(|| (self.factory)())
26+
};
27+
28+
PoolGuard { item: Some(item), pool: Arc::<Mutex<VecDeque<T>>>::clone(&self.items) }
29+
}
30+
}
31+
32+
impl<T: PoolDrop> std::ops::Deref for PoolGuard<T> {
33+
type Target = T;
34+
35+
fn deref(&self) -> &Self::Target {
36+
self.item.as_ref().unwrap()
37+
}
38+
}
39+
40+
impl<T: PoolDrop> std::ops::DerefMut for PoolGuard<T> {
41+
fn deref_mut(&mut self) -> &mut Self::Target {
42+
self.item.as_mut().unwrap()
43+
}
44+
}
45+
46+
pub trait PoolDrop {
47+
fn drop_pool(&mut self);
48+
}
49+
50+
impl PoolDrop for oxc_allocator::Allocator {
51+
fn drop_pool(&mut self) {
52+
self.reset();
53+
}
54+
}
55+
56+
impl<T: PoolDrop> Drop for PoolGuard<T> {
57+
fn drop(&mut self) {
58+
if let Some(mut item) = self.item.take() {
59+
item.drop_pool();
60+
let mut items = self.pool.lock().unwrap();
61+
items.push_back(item);
62+
}
63+
}
64+
}

crates/oxc_linter/src/service/runtime.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use crate::{
2828
fixer::PossibleFixes,
2929
loader::{JavaScriptSource, LINT_PARTIAL_LOADER_EXTENSIONS, PartialLoader},
3030
module_record::ModuleRecord,
31+
pool::{self, Pool},
3132
utils::read_to_string,
3233
};
3334

@@ -42,6 +43,8 @@ pub struct Runtime<'l> {
4243
resolver: Option<Resolver>,
4344

4445
pub(super) file_system: Box<dyn RuntimeFileSystem + Sync + Send>,
46+
47+
allocator_pool: Pool<Allocator>,
4548
}
4649

4750
/// Output of `Runtime::process_path`
@@ -95,7 +98,7 @@ unsafe impl Send for ModuleContent {}
9598

9699
struct ModuleContentOwner {
97100
source_text: String,
98-
allocator: Allocator,
101+
allocator: pool::PoolGuard<Allocator>,
99102
}
100103

101104
/// source text and semantic for each source section. They are in the same order as `ProcessedModule.section_module_records`
@@ -165,6 +168,7 @@ impl<'l> Runtime<'l> {
165168
Self::get_resolver(options.tsconfig.or_else(|| Some(options.cwd.join("tsconfig.json"))))
166169
});
167170
Self {
171+
allocator_pool: Pool::new(Allocator::default),
168172
cwd: options.cwd,
169173
paths: options.paths.iter().cloned().collect(),
170174
linter,
@@ -771,7 +775,9 @@ impl<'l> Runtime<'l> {
771775
};
772776
let mut records = SmallVec::<[Result<ResolvedModuleRecord, Vec<OxcDiagnostic>>; 1]>::new();
773777
let mut module_content: Option<ModuleContent> = None;
774-
let allocator = Allocator::default();
778+
779+
let allocator = self.allocator_pool.get();
780+
775781
if self.paths.contains(path) {
776782
module_content =
777783
Some(ModuleContent::new(ModuleContentOwner { source_text, allocator }, |owner| {

0 commit comments

Comments
 (0)