feat(tvix/eval): Forbid Hash{Map,Set}, use Fx instead
Per https://nnethercote.github.io/perf-book/hashing.html, we have basically no reason to use the default hasher over a faster, non-DoS-resistant hasher. This gives a nice perf boost basically for free: hello outpath time: [704.76 ms 714.91 ms 725.63 ms] change: [-7.2391% -6.1018% -4.9189%] (p = 0.00 < 0.05) Performance has improved. Change-Id: If5587f444ed3af69f8af4eead6af3ea303b4ae68 Reviewed-on: https://cl.tvl.fyi/c/depot/+/12046 Tested-by: BuildkiteCI Reviewed-by: flokli <flokli@flokli.de> Reviewed-by: Ilan Joselevich <personal@ilanjoselevich.com> Autosubmit: aspen <root@gws.fyi>
This commit is contained in:
parent
1d7ba89c19
commit
b8f92a6d53
17 changed files with 116 additions and 46 deletions
14
tvix/Cargo.lock
generated
14
tvix/Cargo.lock
generated
|
@ -3085,7 +3085,7 @@ dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"quinn-proto",
|
"quinn-proto",
|
||||||
"quinn-udp",
|
"quinn-udp",
|
||||||
"rustc-hash",
|
"rustc-hash 1.1.0",
|
||||||
"rustls 0.23.7",
|
"rustls 0.23.7",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -3101,7 +3101,7 @@ dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"rand",
|
"rand",
|
||||||
"ring",
|
"ring",
|
||||||
"rustc-hash",
|
"rustc-hash 1.1.0",
|
||||||
"rustls 0.23.7",
|
"rustls 0.23.7",
|
||||||
"slab",
|
"slab",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
@ -3416,7 +3416,7 @@ dependencies = [
|
||||||
"countme",
|
"countme",
|
||||||
"hashbrown 0.14.3",
|
"hashbrown 0.14.3",
|
||||||
"memoffset 0.9.0",
|
"memoffset 0.9.0",
|
||||||
"rustc-hash",
|
"rustc-hash 1.1.0",
|
||||||
"text-size",
|
"text-size",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -3473,6 +3473,12 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -4864,6 +4870,7 @@ dependencies = [
|
||||||
"nix-compat",
|
"nix-compat",
|
||||||
"rnix",
|
"rnix",
|
||||||
"rowan",
|
"rowan",
|
||||||
|
"rustc-hash 2.0.0",
|
||||||
"rustyline",
|
"rustyline",
|
||||||
"smol_str",
|
"smol_str",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
@ -4905,6 +4912,7 @@ dependencies = [
|
||||||
"rnix",
|
"rnix",
|
||||||
"rowan",
|
"rowan",
|
||||||
"rstest",
|
"rstest",
|
||||||
|
"rustc-hash 2.0.0",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha1",
|
"sha1",
|
||||||
|
|
|
@ -9701,7 +9701,7 @@ rec {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "rustc-hash";
|
name = "rustc-hash";
|
||||||
packageId = "rustc-hash";
|
packageId = "rustc-hash 1.1.0";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "rustls";
|
name = "rustls";
|
||||||
|
@ -9768,7 +9768,7 @@ rec {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "rustc-hash";
|
name = "rustc-hash";
|
||||||
packageId = "rustc-hash";
|
packageId = "rustc-hash 1.1.0";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "rustls";
|
name = "rustls";
|
||||||
|
@ -10901,7 +10901,7 @@ rec {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "rustc-hash";
|
name = "rustc-hash";
|
||||||
packageId = "rustc-hash";
|
packageId = "rustc-hash 1.1.0";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "text-size";
|
name = "text-size";
|
||||||
|
@ -11051,7 +11051,7 @@ rec {
|
||||||
"rustc-dep-of-std" = [ "core" "compiler_builtins" ];
|
"rustc-dep-of-std" = [ "core" "compiler_builtins" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
"rustc-hash" = rec {
|
"rustc-hash 1.1.0" = rec {
|
||||||
crateName = "rustc-hash";
|
crateName = "rustc-hash";
|
||||||
version = "1.1.0";
|
version = "1.1.0";
|
||||||
edition = "2015";
|
edition = "2015";
|
||||||
|
@ -11064,6 +11064,20 @@ rec {
|
||||||
};
|
};
|
||||||
resolvedDefaultFeatures = [ "default" "std" ];
|
resolvedDefaultFeatures = [ "default" "std" ];
|
||||||
};
|
};
|
||||||
|
"rustc-hash 2.0.0" = rec {
|
||||||
|
crateName = "rustc-hash";
|
||||||
|
version = "2.0.0";
|
||||||
|
edition = "2021";
|
||||||
|
sha256 = "0lni0lf846bzrf3jvci6jaf4142n1mdqxvcpczk5ch9pfgyk8c2q";
|
||||||
|
authors = [
|
||||||
|
"The Rust Project Developers"
|
||||||
|
];
|
||||||
|
features = {
|
||||||
|
"default" = [ "std" ];
|
||||||
|
"rand" = [ "dep:rand" "std" ];
|
||||||
|
};
|
||||||
|
resolvedDefaultFeatures = [ "default" "std" ];
|
||||||
|
};
|
||||||
"rustc_version" = rec {
|
"rustc_version" = rec {
|
||||||
crateName = "rustc_version";
|
crateName = "rustc_version";
|
||||||
version = "0.4.0";
|
version = "0.4.0";
|
||||||
|
@ -15892,6 +15906,10 @@ rec {
|
||||||
name = "rowan";
|
name = "rowan";
|
||||||
packageId = "rowan";
|
packageId = "rowan";
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
name = "rustc-hash";
|
||||||
|
packageId = "rustc-hash 2.0.0";
|
||||||
|
}
|
||||||
{
|
{
|
||||||
name = "rustyline";
|
name = "rustyline";
|
||||||
packageId = "rustyline";
|
packageId = "rustyline";
|
||||||
|
@ -16049,6 +16067,10 @@ rec {
|
||||||
name = "rowan";
|
name = "rowan";
|
||||||
packageId = "rowan";
|
packageId = "rowan";
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
name = "rustc-hash";
|
||||||
|
packageId = "rustc-hash 2.0.0";
|
||||||
|
}
|
||||||
{
|
{
|
||||||
name = "serde";
|
name = "serde";
|
||||||
packageId = "serde";
|
packageId = "serde";
|
||||||
|
|
|
@ -26,6 +26,7 @@ thiserror = "1.0.38"
|
||||||
tokio = "1.28.0"
|
tokio = "1.28.0"
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
tracing-indicatif = "0.3.6"
|
tracing-indicatif = "0.3.6"
|
||||||
|
rustc-hash = "2.0.0"
|
||||||
|
|
||||||
[dependencies.wu-manber]
|
[dependencies.wu-manber]
|
||||||
git = "https://github.com/tvlfyi/wu-manber.git"
|
git = "https://github.com/tvlfyi/wu-manber.git"
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::{collections::HashMap, path::PathBuf, rc::Rc};
|
use std::path::PathBuf;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use tracing::{instrument, Span};
|
use tracing::{instrument, Span};
|
||||||
|
@ -86,7 +88,7 @@ pub fn evaluate(
|
||||||
path: Option<PathBuf>,
|
path: Option<PathBuf>,
|
||||||
args: &Args,
|
args: &Args,
|
||||||
allow_incomplete: AllowIncomplete,
|
allow_incomplete: AllowIncomplete,
|
||||||
env: Option<&HashMap<SmolStr, Value>>,
|
env: Option<&FxHashMap<SmolStr, Value>>,
|
||||||
globals: Option<Rc<GlobalsMap>>,
|
globals: Option<Rc<GlobalsMap>>,
|
||||||
source_map: Option<SourceCode>,
|
source_map: Option<SourceCode>,
|
||||||
) -> Result<EvalResult, IncompleteInput> {
|
) -> Result<EvalResult, IncompleteInput> {
|
||||||
|
@ -218,7 +220,7 @@ pub fn interpret(
|
||||||
args: &Args,
|
args: &Args,
|
||||||
explain: bool,
|
explain: bool,
|
||||||
allow_incomplete: AllowIncomplete,
|
allow_incomplete: AllowIncomplete,
|
||||||
env: Option<&HashMap<SmolStr, Value>>,
|
env: Option<&FxHashMap<SmolStr, Value>>,
|
||||||
globals: Option<Rc<GlobalsMap>>,
|
globals: Option<Rc<GlobalsMap>>,
|
||||||
source_map: Option<SourceCode>,
|
source_map: Option<SourceCode>,
|
||||||
) -> Result<InterpretResult, IncompleteInput> {
|
) -> Result<InterpretResult, IncompleteInput> {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::{collections::HashMap, path::PathBuf};
|
|
||||||
|
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use rustyline::{error::ReadlineError, Editor};
|
use rustyline::{error::ReadlineError, Editor};
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
use tvix_eval::{GlobalsMap, SourceCode, Value};
|
use tvix_eval::{GlobalsMap, SourceCode, Value};
|
||||||
|
@ -88,7 +89,7 @@ pub struct Repl<'a> {
|
||||||
multiline_input: Option<String>,
|
multiline_input: Option<String>,
|
||||||
rl: Editor<()>,
|
rl: Editor<()>,
|
||||||
/// Local variables defined at the top-level in the repl
|
/// Local variables defined at the top-level in the repl
|
||||||
env: HashMap<SmolStr, Value>,
|
env: FxHashMap<SmolStr, Value>,
|
||||||
|
|
||||||
io_handle: Rc<TvixStoreIO>,
|
io_handle: Rc<TvixStoreIO>,
|
||||||
args: &'a Args,
|
args: &'a Args,
|
||||||
|
@ -102,7 +103,7 @@ impl<'a> Repl<'a> {
|
||||||
Self {
|
Self {
|
||||||
multiline_input: None,
|
multiline_input: None,
|
||||||
rl,
|
rl,
|
||||||
env: HashMap::new(),
|
env: FxHashMap::default(),
|
||||||
io_handle,
|
io_handle,
|
||||||
args,
|
args,
|
||||||
source_map: Default::default(),
|
source_map: Default::default(),
|
||||||
|
|
|
@ -34,6 +34,7 @@ sha2 = "0.10.8"
|
||||||
sha1 = "0.10.6"
|
sha1 = "0.10.6"
|
||||||
md-5 = "0.10.6"
|
md-5 = "0.10.6"
|
||||||
data-encoding = "2.6.0"
|
data-encoding = "2.6.0"
|
||||||
|
rustc-hash = "2.0.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.5"
|
criterion = "0.5"
|
||||||
|
|
3
tvix/eval/clippy.toml
Normal file
3
tvix/eval/clippy.toml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# See https://nnethercote.github.io/perf-book/hashing.html. Use FxHashMap and
|
||||||
|
# FxHashSet, not HashMap and HashSet
|
||||||
|
disallowed-types = ["std::collections::HashMap", "std::collections::HashSet"]
|
|
@ -9,8 +9,8 @@ use genawaiter::rc::Gen;
|
||||||
use imbl::OrdMap;
|
use imbl::OrdMap;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::cmp::{self, Ordering};
|
use std::cmp::{self, Ordering};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::collections::{BTreeMap, HashSet};
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::arithmetic_op;
|
use crate::arithmetic_op;
|
||||||
|
@ -88,6 +88,7 @@ mod pure_builtins {
|
||||||
use imbl::Vector;
|
use imbl::Vector;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use os_str_bytes::OsStringBytes;
|
use os_str_bytes::OsStringBytes;
|
||||||
|
use rustc_hash::FxHashSet;
|
||||||
|
|
||||||
use crate::{value::PointerEquality, AddContext, NixContext, NixContextElement};
|
use crate::{value::PointerEquality, AddContext, NixContext, NixContextElement};
|
||||||
|
|
||||||
|
@ -700,7 +701,7 @@ mod pure_builtins {
|
||||||
//
|
//
|
||||||
// In this implementation, we do none of that, no syntax checks, no realization.
|
// In this implementation, we do none of that, no syntax checks, no realization.
|
||||||
// The next `TODO` are the checks that Nix implements.
|
// The next `TODO` are the checks that Nix implements.
|
||||||
let mut ctx_elements: HashSet<NixContextElement> = HashSet::new();
|
let mut ctx_elements: FxHashSet<NixContextElement> = FxHashSet::default();
|
||||||
let span = generators::request_span(&co).await;
|
let span = generators::request_span(&co).await;
|
||||||
let origin = origin
|
let origin = origin
|
||||||
.coerce_to_string(
|
.coerce_to_string(
|
||||||
|
@ -1115,7 +1116,7 @@ mod pure_builtins {
|
||||||
.to_list()?
|
.to_list()?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|v| v.to_str())
|
.map(|v| v.to_str())
|
||||||
.collect::<Result<HashSet<_>, _>>()?;
|
.collect::<Result<FxHashSet<_>, _>>()?;
|
||||||
let res = attrs.iter().filter_map(|(k, v)| {
|
let res = attrs.iter().filter_map(|(k, v)| {
|
||||||
if !keys.contains(k) {
|
if !keys.contains(k) {
|
||||||
Some((k.clone(), v.clone()))
|
Some((k.clone(), v.clone()))
|
||||||
|
|
|
@ -560,7 +560,7 @@ impl Compiler<'_, '_> {
|
||||||
|
|
||||||
/// Emit definitions for all variables in the top-level global env passed to the evaluation (eg
|
/// Emit definitions for all variables in the top-level global env passed to the evaluation (eg
|
||||||
/// local variables in the REPL)
|
/// local variables in the REPL)
|
||||||
pub(super) fn compile_env(&mut self, env: &HashMap<SmolStr, Value>) {
|
pub(super) fn compile_env(&mut self, env: &FxHashMap<SmolStr, Value>) {
|
||||||
for (name, value) in env {
|
for (name, value) in env {
|
||||||
self.scope_mut().declare_constant(name.to_string());
|
self.scope_mut().declare_constant(name.to_string());
|
||||||
self.emit_constant(value.clone(), &EntireFile);
|
self.emit_constant(value.clone(), &EntireFile);
|
||||||
|
|
|
@ -20,8 +20,9 @@ mod scope;
|
||||||
|
|
||||||
use codemap::Span;
|
use codemap::Span;
|
||||||
use rnix::ast::{self, AstToken};
|
use rnix::ast::{self, AstToken};
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::BTreeMap;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::rc::{Rc, Weak};
|
use std::rc::{Rc, Weak};
|
||||||
|
|
||||||
|
@ -117,7 +118,7 @@ impl TrackedFormal {
|
||||||
|
|
||||||
/// The map of globally available functions and other values that
|
/// The map of globally available functions and other values that
|
||||||
/// should implicitly be resolvable in the global scope.
|
/// should implicitly be resolvable in the global scope.
|
||||||
pub type GlobalsMap = HashMap<&'static str, Value>;
|
pub type GlobalsMap = FxHashMap<&'static str, Value>;
|
||||||
|
|
||||||
/// Set of builtins that (if they exist) should be made available in
|
/// Set of builtins that (if they exist) should be made available in
|
||||||
/// the global scope, meaning that they can be accessed not just
|
/// the global scope, meaning that they can be accessed not just
|
||||||
|
@ -187,7 +188,7 @@ impl<'source, 'observer> Compiler<'source, 'observer> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
location: Option<PathBuf>,
|
location: Option<PathBuf>,
|
||||||
globals: Rc<GlobalsMap>,
|
globals: Rc<GlobalsMap>,
|
||||||
env: Option<&HashMap<SmolStr, Value>>,
|
env: Option<&FxHashMap<SmolStr, Value>>,
|
||||||
source: &'source SourceCode,
|
source: &'source SourceCode,
|
||||||
file: &'source codemap::File,
|
file: &'source codemap::File,
|
||||||
observer: &'observer mut dyn CompilerObserver,
|
observer: &'observer mut dyn CompilerObserver,
|
||||||
|
@ -1588,7 +1589,7 @@ pub fn prepare_globals(
|
||||||
Rc::new_cyclic(Box::new(move |weak: &Weak<GlobalsMap>| {
|
Rc::new_cyclic(Box::new(move |weak: &Weak<GlobalsMap>| {
|
||||||
// First step is to construct the builtins themselves as
|
// First step is to construct the builtins themselves as
|
||||||
// `NixAttrs`.
|
// `NixAttrs`.
|
||||||
let mut builtins: GlobalsMap = HashMap::from_iter(builtins);
|
let mut builtins: GlobalsMap = FxHashMap::from_iter(builtins);
|
||||||
|
|
||||||
// At this point, optionally insert `import` if enabled. To
|
// At this point, optionally insert `import` if enabled. To
|
||||||
// "tie the knot" of `import` needing the full set of globals
|
// "tie the knot" of `import` needing the full set of globals
|
||||||
|
@ -1601,7 +1602,7 @@ pub fn prepare_globals(
|
||||||
|
|
||||||
// Next, the actual map of globals which the compiler will use
|
// Next, the actual map of globals which the compiler will use
|
||||||
// to resolve identifiers is constructed.
|
// to resolve identifiers is constructed.
|
||||||
let mut globals: GlobalsMap = HashMap::new();
|
let mut globals: GlobalsMap = FxHashMap::default();
|
||||||
|
|
||||||
// builtins contain themselves (`builtins.builtins`), which we
|
// builtins contain themselves (`builtins.builtins`), which we
|
||||||
// can resolve by manually constructing a suspended thunk that
|
// can resolve by manually constructing a suspended thunk that
|
||||||
|
@ -1654,7 +1655,7 @@ pub fn compile(
|
||||||
expr: &ast::Expr,
|
expr: &ast::Expr,
|
||||||
location: Option<PathBuf>,
|
location: Option<PathBuf>,
|
||||||
globals: Rc<GlobalsMap>,
|
globals: Rc<GlobalsMap>,
|
||||||
env: Option<&HashMap<SmolStr, Value>>,
|
env: Option<&FxHashMap<SmolStr, Value>>,
|
||||||
source: &SourceCode,
|
source: &SourceCode,
|
||||||
file: &codemap::File,
|
file: &codemap::File,
|
||||||
observer: &mut dyn CompilerObserver,
|
observer: &mut dyn CompilerObserver,
|
||||||
|
|
|
@ -10,10 +10,8 @@
|
||||||
//! stack indices. To do this, the compiler simulates where locals
|
//! stack indices. To do this, the compiler simulates where locals
|
||||||
//! will be at runtime using the data structures implemented here.
|
//! will be at runtime using the data structures implemented here.
|
||||||
|
|
||||||
use std::{
|
use rustc_hash::FxHashMap;
|
||||||
collections::{hash_map, HashMap},
|
use std::{collections::hash_map, ops::Index};
|
||||||
ops::Index,
|
|
||||||
};
|
|
||||||
|
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
|
|
||||||
|
@ -168,7 +166,7 @@ pub struct Scope {
|
||||||
pub upvalues: Vec<Upvalue>,
|
pub upvalues: Vec<Upvalue>,
|
||||||
|
|
||||||
/// Secondary by-name index over locals.
|
/// Secondary by-name index over locals.
|
||||||
by_name: HashMap<String, ByName>,
|
by_name: FxHashMap<String, ByName>,
|
||||||
|
|
||||||
/// How many scopes "deep" are these locals?
|
/// How many scopes "deep" are these locals?
|
||||||
scope_depth: usize,
|
scope_depth: usize,
|
||||||
|
|
|
@ -36,7 +36,7 @@ mod test_utils;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
@ -86,7 +86,7 @@ enum BuilderGlobals {
|
||||||
pub struct EvaluationBuilder<'co, 'ro, 'env, IO> {
|
pub struct EvaluationBuilder<'co, 'ro, 'env, IO> {
|
||||||
source_map: Option<SourceCode>,
|
source_map: Option<SourceCode>,
|
||||||
globals: BuilderGlobals,
|
globals: BuilderGlobals,
|
||||||
env: Option<&'env HashMap<SmolStr, Value>>,
|
env: Option<&'env FxHashMap<SmolStr, Value>>,
|
||||||
io_handle: IO,
|
io_handle: IO,
|
||||||
enable_import: bool,
|
enable_import: bool,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
|
@ -264,7 +264,7 @@ impl<'co, 'ro, 'env, IO> EvaluationBuilder<'co, 'ro, 'env, IO> {
|
||||||
Self { nix_path, ..self }
|
Self { nix_path, ..self }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn env(self, env: Option<&'env HashMap<SmolStr, Value>>) -> Self {
|
pub fn env(self, env: Option<&'env FxHashMap<SmolStr, Value>>) -> Self {
|
||||||
Self { env, ..self }
|
Self { env, ..self }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +352,7 @@ pub struct Evaluation<'co, 'ro, 'env, IO> {
|
||||||
globals: Rc<GlobalsMap>,
|
globals: Rc<GlobalsMap>,
|
||||||
|
|
||||||
/// Top-level variables to define in the evaluation
|
/// Top-level variables to define in the evaluation
|
||||||
env: Option<&'env HashMap<SmolStr, Value>>,
|
env: Option<&'env FxHashMap<SmolStr, Value>>,
|
||||||
|
|
||||||
/// Implementation of file-IO to use during evaluation, e.g. for
|
/// Implementation of file-IO to use during evaluation, e.g. for
|
||||||
/// impure builtins.
|
/// impure builtins.
|
||||||
|
@ -570,7 +570,7 @@ fn parse_compile_internal(
|
||||||
location: Option<PathBuf>,
|
location: Option<PathBuf>,
|
||||||
source: SourceCode,
|
source: SourceCode,
|
||||||
globals: Rc<GlobalsMap>,
|
globals: Rc<GlobalsMap>,
|
||||||
env: Option<&HashMap<SmolStr, Value>>,
|
env: Option<&FxHashMap<SmolStr, Value>>,
|
||||||
compiler_observer: &mut dyn CompilerObserver,
|
compiler_observer: &mut dyn CompilerObserver,
|
||||||
) -> Option<Rc<Lambda>> {
|
) -> Option<Rc<Lambda>> {
|
||||||
let parsed = rnix::ast::Root::parse(code);
|
let parsed = rnix::ast::Root::parse(code);
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
//! paying the cost when creating new strings.
|
//! paying the cost when creating new strings.
|
||||||
use bstr::{BStr, BString, ByteSlice, Chars};
|
use bstr::{BStr, BString, ByteSlice, Chars};
|
||||||
use rnix::ast;
|
use rnix::ast;
|
||||||
|
use rustc_hash::FxHashSet;
|
||||||
use std::alloc::{alloc, dealloc, handle_alloc_error, Layout};
|
use std::alloc::{alloc, dealloc, handle_alloc_error, Layout};
|
||||||
use std::borrow::{Borrow, Cow};
|
use std::borrow::{Borrow, Cow};
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
use std::fmt::{self, Debug, Display};
|
use std::fmt::{self, Debug, Display};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
@ -40,23 +40,29 @@ pub enum NixContextElement {
|
||||||
/// operations, e.g. concatenation, interpolation and other string operations.
|
/// operations, e.g. concatenation, interpolation and other string operations.
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, Debug, Serialize, Default)]
|
#[derive(Clone, Debug, Serialize, Default)]
|
||||||
pub struct NixContext(HashSet<NixContextElement>);
|
pub struct NixContext(FxHashSet<NixContextElement>);
|
||||||
|
|
||||||
impl From<NixContextElement> for NixContext {
|
impl From<NixContextElement> for NixContext {
|
||||||
fn from(value: NixContextElement) -> Self {
|
fn from(value: NixContextElement) -> Self {
|
||||||
Self([value].into())
|
let mut set = FxHashSet::default();
|
||||||
|
set.insert(value);
|
||||||
|
Self(set)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<HashSet<NixContextElement>> for NixContext {
|
impl From<FxHashSet<NixContextElement>> for NixContext {
|
||||||
fn from(value: HashSet<NixContextElement>) -> Self {
|
fn from(value: FxHashSet<NixContextElement>) -> Self {
|
||||||
Self(value)
|
Self(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize> From<[NixContextElement; N]> for NixContext {
|
impl<const N: usize> From<[NixContextElement; N]> for NixContext {
|
||||||
fn from(value: [NixContextElement; N]) -> Self {
|
fn from(value: [NixContextElement; N]) -> Self {
|
||||||
Self(HashSet::from(value))
|
let mut set = FxHashSet::default();
|
||||||
|
for elt in value {
|
||||||
|
set.insert(elt);
|
||||||
|
}
|
||||||
|
Self(set)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
//! object, but when forcing a thunk, the runtime *must* mutate the
|
//! object, but when forcing a thunk, the runtime *must* mutate the
|
||||||
//! memoisable slot.
|
//! memoisable slot.
|
||||||
|
|
||||||
|
use rustc_hash::FxHashSet;
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Ref, RefCell, RefMut},
|
cell::{Ref, RefCell, RefMut},
|
||||||
collections::HashSet,
|
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
@ -413,7 +413,7 @@ impl TotalDisplay for Thunk {
|
||||||
/// The inner `HashSet` is not available on the outside, as it would be
|
/// The inner `HashSet` is not available on the outside, as it would be
|
||||||
/// potentially unsafe to interact with the pointers in the set.
|
/// potentially unsafe to interact with the pointers in the set.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ThunkSet(HashSet<*const ThunkRepr>);
|
pub struct ThunkSet(FxHashSet<*const ThunkRepr>);
|
||||||
|
|
||||||
impl ThunkSet {
|
impl ThunkSet {
|
||||||
/// Check whether the given thunk has already been seen. Will mark the thunk
|
/// Check whether the given thunk has already been seen. Will mark the thunk
|
||||||
|
|
|
@ -14,8 +14,9 @@ mod macros;
|
||||||
|
|
||||||
use bstr::{BString, ByteSlice, ByteVec};
|
use bstr::{BString, ByteSlice, ByteVec};
|
||||||
use codemap::Span;
|
use codemap::Span;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::{cmp::Ordering, collections::HashMap, ops::DerefMut, path::PathBuf, rc::Rc};
|
use std::{cmp::Ordering, ops::DerefMut, path::PathBuf, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arithmetic_op,
|
arithmetic_op,
|
||||||
|
@ -211,7 +212,7 @@ impl Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ImportCache(HashMap<PathBuf, Value>);
|
struct ImportCache(FxHashMap<PathBuf, Value>);
|
||||||
|
|
||||||
/// The `ImportCache` holds the `Value` resulting from `import`ing a certain
|
/// The `ImportCache` holds the `Value` resulting from `import`ing a certain
|
||||||
/// file, so that the same file doesn't need to be re-evaluated multiple times.
|
/// file, so that the same file doesn't need to be re-evaluated multiple times.
|
||||||
|
|
9
web/tvixbolt/Cargo.lock
generated
9
web/tvixbolt/Cargo.lock
generated
|
@ -1223,7 +1223,7 @@ dependencies = [
|
||||||
"countme",
|
"countme",
|
||||||
"hashbrown 0.14.5",
|
"hashbrown 0.14.5",
|
||||||
"memoffset",
|
"memoffset",
|
||||||
"rustc-hash",
|
"rustc-hash 1.1.0",
|
||||||
"text-size",
|
"text-size",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1239,6 +1239,12 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.17"
|
version = "1.0.17"
|
||||||
|
@ -1561,6 +1567,7 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
"rnix",
|
"rnix",
|
||||||
"rowan",
|
"rowan",
|
||||||
|
"rustc-hash 2.0.0",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha1",
|
"sha1",
|
||||||
|
|
|
@ -3668,7 +3668,7 @@ rec {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "rustc-hash";
|
name = "rustc-hash";
|
||||||
packageId = "rustc-hash";
|
packageId = "rustc-hash 1.1.0";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "text-size";
|
name = "text-size";
|
||||||
|
@ -3695,7 +3695,7 @@ rec {
|
||||||
"rustc-dep-of-std" = [ "core" "compiler_builtins" ];
|
"rustc-dep-of-std" = [ "core" "compiler_builtins" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
"rustc-hash" = rec {
|
"rustc-hash 1.1.0" = rec {
|
||||||
crateName = "rustc-hash";
|
crateName = "rustc-hash";
|
||||||
version = "1.1.0";
|
version = "1.1.0";
|
||||||
edition = "2015";
|
edition = "2015";
|
||||||
|
@ -3708,6 +3708,20 @@ rec {
|
||||||
};
|
};
|
||||||
resolvedDefaultFeatures = [ "default" "std" ];
|
resolvedDefaultFeatures = [ "default" "std" ];
|
||||||
};
|
};
|
||||||
|
"rustc-hash 2.0.0" = rec {
|
||||||
|
crateName = "rustc-hash";
|
||||||
|
version = "2.0.0";
|
||||||
|
edition = "2021";
|
||||||
|
sha256 = "0lni0lf846bzrf3jvci6jaf4142n1mdqxvcpczk5ch9pfgyk8c2q";
|
||||||
|
authors = [
|
||||||
|
"The Rust Project Developers"
|
||||||
|
];
|
||||||
|
features = {
|
||||||
|
"default" = [ "std" ];
|
||||||
|
"rand" = [ "dep:rand" "std" ];
|
||||||
|
};
|
||||||
|
resolvedDefaultFeatures = [ "default" "std" ];
|
||||||
|
};
|
||||||
"rustversion" = rec {
|
"rustversion" = rec {
|
||||||
crateName = "rustversion";
|
crateName = "rustversion";
|
||||||
version = "1.0.17";
|
version = "1.0.17";
|
||||||
|
@ -4642,6 +4656,10 @@ rec {
|
||||||
name = "rowan";
|
name = "rowan";
|
||||||
packageId = "rowan";
|
packageId = "rowan";
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
name = "rustc-hash";
|
||||||
|
packageId = "rustc-hash 2.0.0";
|
||||||
|
}
|
||||||
{
|
{
|
||||||
name = "serde";
|
name = "serde";
|
||||||
packageId = "serde";
|
packageId = "serde";
|
||||||
|
|
Loading…
Reference in a new issue