diff --git a/tvix/Cargo.nix b/tvix/Cargo.nix index 4826317e9..926145c31 100644 --- a/tvix/Cargo.nix +++ b/tvix/Cargo.nix @@ -16122,7 +16122,7 @@ rec { "proptest" = [ "dep:proptest" ]; "test-strategy" = [ "dep:test-strategy" ]; }; - resolvedDefaultFeatures = [ "arbitrary" "default" "impure" "nix_tests" "proptest" "test-strategy" ]; + resolvedDefaultFeatures = [ "arbitrary" "default" "impure" "nix_tests" "no_leak" "proptest" "test-strategy" ]; }; "tvix-eval-builtin-macros" = rec { crateName = "tvix-eval-builtin-macros"; diff --git a/tvix/eval/Cargo.toml b/tvix/eval/Cargo.toml index 83600eb6e..ed2ed0440 100644 --- a/tvix/eval/Cargo.toml +++ b/tvix/eval/Cargo.toml @@ -58,6 +58,11 @@ impure = [] # Enables Arbitrary impls for internal types (required to run tests) arbitrary = ["proptest", "test-strategy", "imbl/proptest"] +# Don't leak strings (enable this if you care about peak memory usage of eval) +# +# This is intended as a stop-gap until we have a garbage collector +no_leak = [] + [[bench]] name = "eval" harness = false diff --git a/tvix/eval/src/value/string.rs b/tvix/eval/src/value/string.rs index 163e140a1..3e991890e 100644 --- a/tvix/eval/src/value/string.rs +++ b/tvix/eval/src/value/string.rs @@ -409,6 +409,10 @@ unsafe impl Sync for NixString {} impl Drop for NixString { fn drop(&mut self) { + if !cfg!(feature = "no_leak") { + return; + } + // SAFETY: There's no way to construct a NixString that doesn't leave the allocation correct // according to the rules of dealloc unsafe { @@ -419,9 +423,17 @@ impl Drop for NixString { impl Clone for NixString { fn clone(&self) -> Self { - // SAFETY: There's no way to construct a NixString that doesn't leave the allocation correct - // according to the rules of clone - unsafe { Self(NixStringInner::clone(self.0)) } + if cfg!(feature = "no_leak") || self.context().is_some() { + // SAFETY: There's no way to construct a NixString that doesn't leave the allocation correct + // according to the rules of clone + unsafe { Self(NixStringInner::clone(self.0)) } + } else { + // SAFETY: + // + // - NixStrings are never mutated + // - NixStrings are never freed + Self(self.0) + } } }