diff --git a/Cargo.lock b/Cargo.lock index 7f1cefc..4063ce5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -576,6 +576,7 @@ dependencies = [ "smallvec", "sptr", "string-interner", + "sysinfo", ] [[package]] @@ -877,6 +878,15 @@ dependencies = [ "libc", ] +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -917,6 +927,25 @@ dependencies = [ "syn", ] +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags", +] + +[[package]] +name = "objc2-io-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" +dependencies = [ + "libc", + "objc2-core-foundation", +] + [[package]] name = "object" version = "0.37.3" @@ -1322,6 +1351,20 @@ dependencies = [ "syn", ] +[[package]] +name = "sysinfo" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ab6a2f8bfe508deb3c6406578252e491d299cbbf3bc0529ecc3313aee4a52f" +dependencies = [ + "libc", + "memchr", + "ntapi", + "objc2-core-foundation", + "objc2-io-kit", + "windows", +] + [[package]] name = "tempfile" version = "3.27.0" @@ -1715,12 +1758,107 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -1730,6 +1868,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + [[package]] name = "winnow" version = "1.0.1" diff --git a/fix-vm/Cargo.toml b/fix-vm/Cargo.toml index 93cbe21..0e4aa0d 100644 --- a/fix-vm/Cargo.toml +++ b/fix-vm/Cargo.toml @@ -14,6 +14,7 @@ smallvec = { workspace = true } string-interner = { workspace = true } likely_stable = { workspace = true } sptr = "0.3" +sysinfo = { version = "0.38", default-features = false, features = ["system"] } fix-builtins = { path = "../fix-builtins" } fix-codegen = { path = "../fix-codegen" } diff --git a/fix-vm/src/lib.rs b/fix-vm/src/lib.rs index 0ed0b4e..b098b82 100644 --- a/fix-vm/src/lib.rs +++ b/fix-vm/src/lib.rs @@ -11,7 +11,7 @@ use fix_builtins::{BUILTINS, BuiltinId}; use fix_codegen::InstructionPtr; use fix_common::StringId; use fix_error::{Error, Result, Source}; -use gc_arena::arena::CollectionPhase; +use gc_arena::metrics::Pacing; use gc_arena::{Arena, Collect, Gc, Mutation, RefLock, Rootable}; use hashbrown::HashMap; use num_enum::TryFromPrimitive; @@ -485,6 +485,20 @@ enum Action { LoadFile(PendingLoad), } +/// Compute initial heap size mirroring CppNix's strategy: 25% of physical RAM, +/// clamped to [32 MiB, 384 MiB]. Used as `Pacing::min_sleep` so the collector +/// defers the first cycle until the heap reaches this size. +fn initial_heap_size() -> usize { + const MIN_SIZE: usize = 32 * 1024 * 1024; + const MAX_SIZE: usize = 384 * 1024 * 1024; + + let mut sys = sysinfo::System::new(); + sys.refresh_memory(); + let total = sys.total_memory() as usize; + let quarter = total / 4; + quarter.clamp(MIN_SIZE, MAX_SIZE) +} + impl Vm<'_> { pub fn run( ctx: &mut C, @@ -493,8 +507,10 @@ impl Vm<'_> { ) -> Result { let (code, runtime) = ctx.split(); let mut arena: Arena]> = Arena::new(|mc| Vm::new(force_mode, mc, runtime)); - - const COLLECTOR_GRANULARITY: f64 = 1024.0; + arena.metrics().set_pacing(Pacing { + min_sleep: initial_heap_size(), + ..Pacing::STOP_THE_WORLD + }); let mut pc = ip.0; loop { @@ -502,12 +518,8 @@ impl Vm<'_> { match arena.mutate_root(|mc, root| root.dispatch_batch(bytecode, runtime, pc, mc)) { Action::Continue { pc: new_pc } => { pc = new_pc; - if arena.metrics().allocation_debt() > COLLECTOR_GRANULARITY { - if arena.collection_phase() == CollectionPhase::Sweeping { - arena.collect_debt(); - } else if let Some(marked) = arena.mark_debt() { - marked.start_sweeping(); - } + if arena.metrics().allocation_debt() > 0.0 { + arena.finish_cycle(); } } Action::LoadFile(load) => {