about summary refs log tree commit diff
path: root/tvix/eval/src/value
diff options
context:
space:
mode:
authorAspen Smith <root@gws.fyi>2024-07-28T16·11-0400
committerclbot <clbot@tvl.fyi>2024-08-07T12·38+0000
commitb8f92a6d535af09c24ac887855eb230ca25af1ed (patch)
tree82cea6a4d3979e0c48e9f97285b8564a24e9ceb0 /tvix/eval/src/value
parent1d7ba89c19b231898a997f1af3c13ed8c7247793 (diff)
feat(tvix/eval): Forbid Hash{Map,Set}, use Fx instead r/8453
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>
Diffstat (limited to 'tvix/eval/src/value')
-rw-r--r--tvix/eval/src/value/string.rs18
-rw-r--r--tvix/eval/src/value/thunk.rs4
2 files changed, 14 insertions, 8 deletions
diff --git a/tvix/eval/src/value/string.rs b/tvix/eval/src/value/string.rs
index 3e991890ea5a..5c1f31db7eea 100644
--- a/tvix/eval/src/value/string.rs
+++ b/tvix/eval/src/value/string.rs
@@ -5,9 +5,9 @@
 //! paying the cost when creating new strings.
 use bstr::{BStr, BString, ByteSlice, Chars};
 use rnix::ast;
+use rustc_hash::FxHashSet;
 use std::alloc::{alloc, dealloc, handle_alloc_error, Layout};
 use std::borrow::{Borrow, Cow};
-use std::collections::HashSet;
 use std::ffi::c_void;
 use std::fmt::{self, Debug, Display};
 use std::hash::Hash;
@@ -40,23 +40,29 @@ pub enum NixContextElement {
 /// operations, e.g. concatenation, interpolation and other string operations.
 #[repr(transparent)]
 #[derive(Clone, Debug, Serialize, Default)]
-pub struct NixContext(HashSet<NixContextElement>);
+pub struct NixContext(FxHashSet<NixContextElement>);
 
 impl From<NixContextElement> for NixContext {
     fn from(value: NixContextElement) -> Self {
-        Self([value].into())
+        let mut set = FxHashSet::default();
+        set.insert(value);
+        Self(set)
     }
 }
 
-impl From<HashSet<NixContextElement>> for NixContext {
-    fn from(value: HashSet<NixContextElement>) -> Self {
+impl From<FxHashSet<NixContextElement>> for NixContext {
+    fn from(value: FxHashSet<NixContextElement>) -> Self {
         Self(value)
     }
 }
 
 impl<const N: usize> From<[NixContextElement; N]> for NixContext {
     fn from(value: [NixContextElement; N]) -> Self {
-        Self(HashSet::from(value))
+        let mut set = FxHashSet::default();
+        for elt in value {
+            set.insert(elt);
+        }
+        Self(set)
     }
 }
 
diff --git a/tvix/eval/src/value/thunk.rs b/tvix/eval/src/value/thunk.rs
index 6d1fe1b8a7cc..2019e8ab3239 100644
--- a/tvix/eval/src/value/thunk.rs
+++ b/tvix/eval/src/value/thunk.rs
@@ -18,9 +18,9 @@
 //! object, but when forcing a thunk, the runtime *must* mutate the
 //! memoisable slot.
 
+use rustc_hash::FxHashSet;
 use std::{
     cell::{Ref, RefCell, RefMut},
-    collections::HashSet,
     fmt::Debug,
     rc::Rc,
 };
@@ -413,7 +413,7 @@ impl TotalDisplay for Thunk {
 /// The inner `HashSet` is not available on the outside, as it would be
 /// potentially unsafe to interact with the pointers in the set.
 #[derive(Default)]
-pub struct ThunkSet(HashSet<*const ThunkRepr>);
+pub struct ThunkSet(FxHashSet<*const ThunkRepr>);
 
 impl ThunkSet {
     /// Check whether the given thunk has already been seen. Will mark the thunk