perf: switch to ahash, indexmap-allocator-api

This commit is contained in:
Guillem L. Jara
2026-05-25 01:50:22 +02:00
parent 8e979cfad1
commit 98fa3c33c2
8 changed files with 102 additions and 23 deletions
Generated
+75 -4
View File
@@ -17,6 +17,19 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "ahash"
version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
dependencies = [
"cfg-if",
"getrandom 0.3.4",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "aho-corasick"
version = "1.1.4"
@@ -420,6 +433,18 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
[[package]]
name = "getrandom"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
dependencies = [
"cfg-if",
"libc",
"r-efi 5.3.0",
"wasip2",
]
[[package]]
name = "getrandom"
version = "0.4.2"
@@ -428,7 +453,7 @@ checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
dependencies = [
"cfg-if",
"libc",
"r-efi",
"r-efi 6.0.0",
"rand_core",
"wasip2",
"wasip3",
@@ -452,6 +477,8 @@ version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"allocator-api2 0.2.21",
"equivalent",
"foldhash 0.1.5",
]
@@ -496,16 +523,27 @@ dependencies = [
"serde_core",
]
[[package]]
name = "indexmap-allocator-api"
version = "2.7.1"
source = "git+https://github.com/Hans-Halverson/indexmap-allocator-api.git?rev=36852f985c01fb9f58f2d9e510655ca1dbb1f4d0#36852f985c01fb9f58f2d9e510655ca1dbb1f4d0"
dependencies = [
"allocator-api2 0.2.21",
"equivalent",
"hashbrown 0.15.5",
]
[[package]]
name = "interpreter"
version = "0.1.0"
dependencies = [
"ahash",
"allocator-api2 0.4.0",
"bumpalo",
"color-eyre",
"either",
"hashbrown 0.17.1",
"indexmap",
"indexmap-allocator-api",
"memchr",
"parser",
"thiserror",
@@ -769,6 +807,7 @@ checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d"
name = "parser"
version = "0.1.0"
dependencies = [
"ahash",
"allocator-api2 0.4.0",
"ariadne",
"bumpalo",
@@ -846,6 +885,12 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "r-efi"
version = "6.0.0"
@@ -859,7 +904,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
dependencies = [
"chacha20",
"getrandom",
"getrandom 0.4.2",
"rand_core",
]
@@ -1036,7 +1081,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [
"fastrand",
"getrandom",
"getrandom 0.4.2",
"once_cell",
"rustix",
"windows-sys 0.61.2",
@@ -1324,6 +1369,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasip2"
version = "1.0.3+wasi-0.2.9"
@@ -1584,6 +1635,26 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]]
name = "zerocopy"
version = "0.8.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "zerofrom"
version = "0.1.7"
+1 -1
View File
@@ -30,9 +30,9 @@ smallvec = { version = "1.15.1", features = ["union", "const_generics", "const_n
bumpalo = { version = "3.20.2", features = ["boxed", "collections", "std", "allocator-api2"] }
hashbrown = "0.17.0"
allocator-api2 = "0.4.0"
ahash = "0.8.12"
[dependencies]
# lexer.workspace = true # FIXME(parser complete): bypass through parser
interpreter.workspace = true
parser.workspace = true
color-eyre.workspace = true
+5 -1
View File
@@ -14,7 +14,11 @@ parser.workspace = true
bumpalo.workspace = true
allocator-api2.workspace = true
hashbrown.workspace = true
indexmap = "2.14.0"
ahash.workspace = true
# I'm not particularly happy about this, but it's crucial for performance, and
# I have audited the two commits. It's pinned to that hash to avoid possible
# supply-chain attacks. Hopefully upstream maintainers will change their mind.
indexmap-allocator-api = { git = 'https://github.com/Hans-Halverson/indexmap-allocator-api.git', rev = "36852f985c01fb9f58f2d9e510655ca1dbb1f4d0" }
[lints]
workspace = true
+2 -2
View File
@@ -20,7 +20,7 @@ use crate::{
pub struct Code<'arena> {
pub arena: &'arena Bump,
pub bc: Bytecode<'arena>,
pub consts: Consts,
pub consts: Consts<'arena>,
pub symbols: SymbolTable<'arena>,
free_regs: Vec<'arena, Reg>,
pub reg_pointer: u16,
@@ -240,7 +240,7 @@ pub fn test_interpreter(stmnt: &Body<'_>) -> String {
let mut c = Code {
arena: &bump,
bc: Bytecode::new_in(&bump),
consts: Consts::new(),
consts: Consts::new_in(&bump),
symbols: SymbolTable::new_in(&bump),
reg_pointer: 0,
free_regs: Vec::new_in(&bump),
+13 -12
View File
@@ -1,8 +1,9 @@
use std::fmt::{self, Display};
use ahash::RandomState;
use bumpalo::{Bump, collections::Vec};
use hashbrown::{DefaultHashBuilder, HashMap};
use indexmap::{IndexMap, IndexSet};
use hashbrown::HashMap;
use indexmap_allocator_api::{IndexMap, IndexSet};
use parser::Identifier;
use crate::ir::{
@@ -28,7 +29,7 @@ pub struct Interpreter<'a> {
program_counter: usize,
registers: Registers<'a>,
symbols: SymbolTable<'a>,
consts: Consts,
consts: Consts<'a>,
compat: ExecMode,
}
@@ -37,14 +38,14 @@ pub struct Registers<'a>(Vec<'a, Value>);
#[derive(Debug)]
pub struct SymbolTable<'a> {
user: IndexMap<Identifier<'a>, Value>,
user: IndexMap<Identifier<'a>, Value, RandomState, &'a Bump>,
// separate table for cheap invalidation. It's an arena _visibly shrugs_.
records: HashMap<usize, Value, DefaultHashBuilder, &'a Bump>,
records: HashMap<usize, Value, RandomState, &'a Bump>,
// etc
}
#[derive(Debug)]
pub struct Consts(pub IndexSet<Value>);
pub struct Consts<'a>(pub IndexSet<Value, RandomState, &'a Bump>);
impl<'a> Interpreter<'a> {
pub fn new(compat: ExecMode, code: Code<'a>) -> Self {
@@ -63,8 +64,8 @@ impl<'a> Interpreter<'a> {
impl<'a> SymbolTable<'a> {
pub fn new_in(arena: &'a Bump) -> Self {
Self {
user: IndexMap::new(),
records: HashMap::new_in(arena),
user: IndexMap::new_in(arena),
records: HashMap::with_hasher_in(RandomState::new(), arena),
}
}
fn lookup_user_var(&self, var: NonLocal) -> &Value {
@@ -88,9 +89,9 @@ impl<'a> SymbolTable<'a> {
}
}
impl Consts {
pub fn new() -> Self {
Self(IndexSet::with_capacity(4))
impl<'a> Consts<'a> {
pub fn new_in(arena: &'a Bump) -> Self {
Self(IndexSet::with_capacity_in(4, arena))
}
}
@@ -195,7 +196,7 @@ impl Display for SymbolTable<'_> {
}
}
impl Display for Consts {
impl Display for Consts<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Consts:")?;
fmt_list(f, self.0.iter(), |f, i, e| write!(f, "mem[{i}] = {e:?}"))
+1
View File
@@ -14,6 +14,7 @@ smallvec.workspace = true
bumpalo.workspace = true
hashbrown.workspace = true
allocator-api2.workspace = true
ahash.workspace = true
ariadne = "0.6.0"
[lints]
+3 -2
View File
@@ -5,9 +5,10 @@
use std::fmt::Debug;
use ahash::RandomState;
use bumpalo::{Bump, boxed::Box, collections::Vec};
use either::Either;
use hashbrown::{DefaultHashBuilder, HashMap};
use hashbrown::HashMap;
use lexer::{Slice, Span, Token};
use crate::{ParsingError, Result, lex::TokenExt};
@@ -21,7 +22,7 @@ pub struct Ast<'a> {
pub end_file: Vec<'a, Body<'a>>,
pub rules: Vec<'a, Rule<'a>>,
pub concurrent: Vec<'a, Rule<'a>>,
pub functions: HashMap<Identifier<'a>, Function<'a>, DefaultHashBuilder, &'a Bump>,
pub functions: HashMap<Identifier<'a>, Function<'a>, RandomState, &'a Bump>,
}
#[derive(Debug)]
+2 -1
View File
@@ -16,6 +16,7 @@ mod tests;
use std::{fmt::Debug, mem::replace};
use ahash::RandomState;
use bumpalo::{Bump, boxed::Box, collections::Vec, vec};
use either::Either::{Left, Right};
use hashbrown::HashMap;
@@ -685,7 +686,7 @@ impl<'a> Ast<'a> {
end_file: Vec::new_in(arena),
rules: Vec::new_in(arena),
concurrent: Vec::new_in(arena),
functions: HashMap::new_in(arena),
functions: HashMap::with_hasher_in(RandomState::new(), arena),
}
}
}