Skip to content

Commit 1039b23

Browse files
Update internment to bump-allocate strings
One large allocation is better than lots of tiny ones, generally speaking, even if the tiny ones never go away.
1 parent 68e948d commit 1039b23

File tree

3 files changed

+29
-12
lines changed

3 files changed

+29
-12
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

collector/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ crossbeam-channel = "0.3.8"
2525
bincode = "1"
2626
snap = "0.2.5"
2727
hashbrown = "0.7.0"
28+
bumpalo = "3.2"
2829

2930
[dependencies.rustup]
3031
git = "https://github.com/rust-lang/rustup.git"

collector/src/intern.rs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use bumpalo::Bump;
12
use hashbrown::HashSet;
23
use std::sync::Mutex;
34

@@ -16,8 +17,25 @@ macro_rules! intern {
1617
where
1718
D: serde::de::Deserializer<'de>,
1819
{
19-
let s: &'de str = <&'de str>::deserialize(deserializer)?;
20-
Ok($crate::intern::intern::<$for_ty>(s))
20+
use serde::de::Visitor;
21+
use std::fmt;
22+
struct InternVisitor;
23+
impl<'de> Visitor<'de> for InternVisitor {
24+
type Value = $for_ty;
25+
26+
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
27+
f.write_str(concat!("a string (", stringify!($for_ty), ")"))
28+
}
29+
30+
fn visit_str<E>(self, s: &str) -> Result<$for_ty, E> {
31+
Ok($crate::intern::intern::<$for_ty>(s))
32+
}
33+
34+
fn visit_borrowed_str<E>(self, s: &'de str) -> Result<$for_ty, E> {
35+
Ok($crate::intern::intern::<$for_ty>(s))
36+
}
37+
}
38+
deserializer.deserialize_str(InternVisitor)
2139
}
2240
}
2341

@@ -48,18 +66,15 @@ macro_rules! intern {
4866
}
4967

5068
lazy_static::lazy_static! {
51-
static ref INTERNED: Mutex<HashSet<&'static str>>
52-
= Mutex::new(HashSet::new());
69+
static ref INTERNED: Mutex<(HashSet<&'static str>, Bump)>
70+
= Mutex::new((HashSet::new(), Bump::new()));
5371
}
5472

5573
pub fn intern<T: InternString>(value: &str) -> T {
56-
let mut set = INTERNED.lock().unwrap();
74+
let mut guard = INTERNED.lock().unwrap();
5775

58-
if let Some(interned) = set.get(value) {
59-
T::to_interned(interned)
60-
} else {
61-
let v: &'static str = Box::leak(value.to_owned().into_boxed_str());
62-
set.insert(v);
63-
T::to_interned(v)
64-
}
76+
let (ref mut set, ref arena) = &mut *guard;
77+
T::to_interned(set.get_or_insert_with(value, |_| -> &'static str {
78+
unsafe { std::mem::transmute::<&str, &'static str>(arena.alloc_str(value)) }
79+
}))
6580
}

0 commit comments

Comments
 (0)