Skip to content

Commit

Permalink
feat(parallel): Add merge_in_parallel (#9939)
Browse files Browse the repository at this point in the history
**Description:**

This feature will be shared by a large portion of codebases in the future, so I extracted these patches from another PR.
  • Loading branch information
kdy1 authored Jan 24, 2025
1 parent 9d6fe37 commit c5b8390
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/thirty-badgers-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
swc_parallel: minor
---

feat(parallel): Add `merge_in_parallel`
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion crates/swc_parallel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ version = "1.1.0"
[features]
default = ["parallel"]
# Make it really parallel
parallel = ["chili"]
parallel = ["dep:chili"]
# Alias for parallel, just for CI. Do not use it if you are not working on SWC.
concurrent = ["parallel"]
indexmap = ["dep:indexmap"]

[dependencies]
chili = { workspace = true, optional = true }
indexmap = { workspace = true, optional = true }
once_cell = { workspace = true }

[dev-dependencies]
Expand Down
1 change: 1 addition & 0 deletions crates/swc_parallel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::{cell::RefCell, mem::transmute};

pub mod items;
pub mod merge;

#[derive(Default)]
pub struct MaybeScope<'a>(ScopeLike<'a>);
Expand Down
75 changes: 75 additions & 0 deletions crates/swc_parallel/src/merge.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use std::{
collections::{hash_map, HashMap},
hash::{BuildHasher, Hash},
};

use crate::join;

pub fn merge_in_parallel<T: Merge>(mut items: Vec<T>) -> T {
assert!(!items.is_empty());

if items.len() == 1 {
return items.into_iter().next().unwrap();
}

let b = items.split_off(items.len() / 2);

let (mut a, b) = join(
move || merge_in_parallel(items),
move || merge_in_parallel(b),
);

a.merge(b);

a
}

/// Used to merge in parallel.
pub trait Merge: Send {
fn merge(&mut self, other: Self);
}

impl<K, V, S> Merge for HashMap<K, V, S>
where
Self: Send,
K: Hash + Eq,
V: Merge,
S: BuildHasher,
{
fn merge(&mut self, other: Self) {
self.reserve(other.len());

for (k, val) in other {
match self.entry(k) {
hash_map::Entry::Occupied(mut o) => o.get_mut().merge(val),
hash_map::Entry::Vacant(v) => {
v.insert(val);
}
}
}
}
}

#[cfg(feature = "indexmap")]
impl<K, V, S> Merge for indexmap::IndexMap<K, V, S>
where
Self: Send,
K: Eq + Hash,
V: Merge,
S: BuildHasher,
{
fn merge(&mut self, other: Self) {
self.reserve(other.len());

for (k, v) in other {
match self.entry(k) {
indexmap::map::Entry::Occupied(mut e) => {
e.get_mut().merge(v);
}
indexmap::map::Entry::Vacant(e) => {
e.insert(v);
}
}
}
}
}

0 comments on commit c5b8390

Please sign in to comment.