Skip to content
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

chore: Reduce contention when using EszipV2 from multiple threads #108

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 21 additions & 20 deletions src/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::future::Future;
use std::mem::size_of;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::RwLock;
use std::task::Poll;
use std::task::Waker;

Expand Down Expand Up @@ -36,7 +37,7 @@ enum HeaderFrameKind {
/// source maps.
#[derive(Debug, Default)]
pub struct EszipV2 {
modules: Arc<Mutex<HashMap<String, EszipV2Module>>>,
modules: Arc<RwLock<HashMap<String, EszipV2Module>>>,
pub ordered_modules: Vec<String>,
}

Expand All @@ -57,7 +58,7 @@ pub enum EszipV2SourceSlot {
Pending {
offset: usize,
length: usize,
wakers: Vec<Waker>,
wakers: Mutex<Vec<Waker>>,
},
Ready(Arc<Vec<u8>>),
}
Expand Down Expand Up @@ -155,7 +156,7 @@ impl EszipV2 {
EszipV2SourceSlot::Pending {
offset: source_offset as usize,
length: source_len as usize,
wakers: vec![],
wakers: Mutex::new(vec![]),
}
};
let source_map = if source_map_offset == 0 && source_map_len == 0 {
Expand All @@ -164,7 +165,7 @@ impl EszipV2 {
EszipV2SourceSlot::Pending {
offset: source_map_offset as usize,
length: source_map_len as usize,
wakers: vec![],
wakers: Mutex::new(vec![]),
}
};
let module = EszipV2Module::Module {
Expand Down Expand Up @@ -216,7 +217,7 @@ impl EszipV2 {
})
.collect::<HashMap<_, _>>();

let modules = Arc::new(Mutex::new(modules));
let modules = Arc::new(RwLock::new(modules));
let modules_ = modules.clone();

let fut = async move {
Expand Down Expand Up @@ -246,7 +247,7 @@ impl EszipV2 {
read += length + 32;

let wakers = {
let mut modules = modules.lock().unwrap();
let mut modules = modules.write().unwrap();
let module = modules.get_mut(&specifier).expect("module not found");
if let EszipV2Module::Module { source, .. } = module {
let slot = std::mem::replace(
Expand All @@ -255,7 +256,7 @@ impl EszipV2 {
);

if let EszipV2SourceSlot::Pending { wakers, .. } = slot {
wakers
wakers.into_inner().unwrap()
} else {
panic!("already populated source slot");
}
Expand Down Expand Up @@ -292,7 +293,7 @@ impl EszipV2 {
read += length + 32;

let wakers = {
let mut modules = modules.lock().unwrap();
let mut modules = modules.write().unwrap();
let module = modules.get_mut(&specifier).expect("module not found");
if let EszipV2Module::Module { source_map, .. } = module {
let slot = std::mem::replace(
Expand All @@ -301,7 +302,7 @@ impl EszipV2 {
);

if let EszipV2SourceSlot::Pending { wakers, .. } = slot {
wakers
wakers.into_inner().unwrap()
} else {
panic!("already populated source_map slot");
}
Expand Down Expand Up @@ -338,7 +339,7 @@ impl EszipV2 {
source: EszipV2SourceSlot::Ready(source),
source_map: EszipV2SourceSlot::Ready(Arc::new(vec![])),
};
let mut modules = self.modules.lock().unwrap();
let mut modules = self.modules.write().unwrap();
if modules.get(&specifier).is_none() {
modules.insert(specifier.clone(), module);
}
Expand All @@ -364,7 +365,7 @@ impl EszipV2 {
let mut sources: Vec<u8> = Vec::new();
let mut source_maps: Vec<u8> = Vec::new();

let modules = self.modules.lock().unwrap();
let modules = self.modules.read().unwrap();

let mut ordered_modules = self.ordered_modules.clone();
let seen_modules: HashSet<String> =
Expand Down Expand Up @@ -602,7 +603,7 @@ impl EszipV2 {
}

Ok(Self {
modules: Arc::new(Mutex::new(modules)),
modules: Arc::new(RwLock::new(modules)),
ordered_modules,
})
}
Expand All @@ -613,7 +614,7 @@ impl EszipV2 {
pub fn get_module(&self, specifier: &str) -> Option<Module> {
let mut specifier = specifier;
let mut visited = HashSet::new();
let modules = self.modules.lock().unwrap();
let modules = self.modules.read().unwrap();
loop {
visited.insert(specifier);
let module = modules.get(specifier)?;
Expand Down Expand Up @@ -643,8 +644,8 @@ impl EszipV2 {
specifier: &str,
) -> Arc<Vec<u8>> {
poll_fn(|cx| {
let mut modules = self.modules.lock().unwrap();
let module = modules.get_mut(specifier).unwrap();
let modules = self.modules.read().unwrap();
let module = modules.get(specifier).unwrap();
let slot = match module {
EszipV2Module::Module { source, .. } => source,
EszipV2Module::Redirect { .. } => {
Expand All @@ -653,7 +654,7 @@ impl EszipV2 {
};
match slot {
EszipV2SourceSlot::Pending { wakers, .. } => {
wakers.push(cx.waker().clone());
wakers.lock().unwrap().push(cx.waker().clone());
Poll::Pending
}
EszipV2SourceSlot::Ready(bytes) => Poll::Ready(bytes.clone()),
Expand All @@ -667,8 +668,8 @@ impl EszipV2 {
specifier: &str,
) -> Arc<Vec<u8>> {
poll_fn(|cx| {
let mut modules = self.modules.lock().unwrap();
let module = modules.get_mut(specifier).unwrap();
let modules = self.modules.read().unwrap();
let module = modules.get(specifier).unwrap();
let slot = match module {
EszipV2Module::Module { source_map, .. } => source_map,
EszipV2Module::Redirect { .. } => {
Expand All @@ -677,7 +678,7 @@ impl EszipV2 {
};
match slot {
EszipV2SourceSlot::Pending { wakers, .. } => {
wakers.push(cx.waker().clone());
wakers.lock().unwrap().push(cx.waker().clone());
Poll::Pending
}
EszipV2SourceSlot::Ready(bytes) => Poll::Ready(bytes.clone()),
Expand All @@ -687,7 +688,7 @@ impl EszipV2 {
}

pub fn specifiers(&self) -> Vec<String> {
let modules = self.modules.lock().unwrap();
let modules = self.modules.read().unwrap();
modules.keys().cloned().collect()
}
}
Expand Down