diff --git a/Cargo.lock b/Cargo.lock index 1b9b7d25..11e4b995 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,6 +35,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + [[package]] name = "anstream" version = "0.6.20" @@ -204,6 +210,12 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" version = "1.2.39" @@ -245,6 +257,33 @@ dependencies = [ "windows-link 0.2.0", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "clap" version = "4.5.48" @@ -325,6 +364,42 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "is-terminal", + "itertools 0.10.5", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + [[package]] name = "crossbeam-channel" version = "0.5.15" @@ -334,6 +409,25 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-queue" version = "0.3.12" @@ -349,6 +443,12 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-common" version = "0.1.6" @@ -676,6 +776,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + [[package]] name = "hashbrown" version = "0.15.5" @@ -1035,12 +1146,32 @@ dependencies = [ "serde", ] +[[package]] +name = "is-terminal" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.61.1", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -1137,10 +1268,12 @@ dependencies = [ name = "mchprs" version = "0.4.1" dependencies = [ + "criterion", "mchprs_blocks", "mchprs_core", "mchprs_redpiler", "mchprs_redstone", + "mchprs_save_data", "mchprs_world", "paste", "tracing", @@ -1171,7 +1304,7 @@ dependencies = [ "ctrlc", "hematite-nbt", "hmac", - "itertools", + "itertools 0.14.0", "mchprs_blocks", "mchprs_network", "mchprs_proc_macros", @@ -1224,7 +1357,7 @@ name = "mchprs_redpiler" version = "0.1.0" dependencies = [ "enum_dispatch", - "itertools", + "itertools 0.14.0", "mchprs_blocks", "mchprs_redstone", "mchprs_world", @@ -1518,6 +1651,12 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + [[package]] name = "openssl" version = "0.10.73" @@ -1625,6 +1764,34 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + [[package]] name = "potential_utf" version = "0.1.3" @@ -1739,6 +1906,26 @@ dependencies = [ "getrandom 0.3.3", ] +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.5.17" @@ -1923,6 +2110,15 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "saturating" version = "0.1.0" @@ -2282,6 +2478,16 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tokio" version = "1.47.1" @@ -2603,6 +2809,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index 01649bf9..93f38f40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,9 @@ mchprs_world = { path = "./crates/world" } mchprs_blocks = { path = "./crates/blocks" } mchprs_redpiler = { path = "./crates/redpiler" } mchprs_redstone = { path = "./crates/redstone" } +mchprs_save_data = { path = "./crates/save_data" } paste = { workspace = true } +criterion = { workspace = true } [workspace.dependencies] toml = "0.8" @@ -86,3 +88,8 @@ tracing-appender = "0.2" paste = "1.0" chrono = "0.4" clap = { version = "4.5", features = ["derive"] } +criterion = { version = "0.5", features = ["html_reports"] } + +[[bench]] +name = "redpiler_bench" +harness = false diff --git a/benches/plots/adder b/benches/plots/adder new file mode 100644 index 00000000..2ce93ab6 Binary files /dev/null and b/benches/plots/adder differ diff --git a/benches/plots/call_stack b/benches/plots/call_stack new file mode 100644 index 00000000..43eb9ac1 Binary files /dev/null and b/benches/plots/call_stack differ diff --git a/benches/plots/long_wire b/benches/plots/long_wire new file mode 100644 index 00000000..922deb84 Binary files /dev/null and b/benches/plots/long_wire differ diff --git a/benches/plots/repeater_grid b/benches/plots/repeater_grid new file mode 100644 index 00000000..384e807f Binary files /dev/null and b/benches/plots/repeater_grid differ diff --git a/benches/redpiler_bench.rs b/benches/redpiler_bench.rs new file mode 100644 index 00000000..6c6e59d4 --- /dev/null +++ b/benches/redpiler_bench.rs @@ -0,0 +1,93 @@ +use mchprs_blocks::{blocks::Block, BlockPos}; +use mchprs_core::plot::{PlotWorld, PLOT_WIDTH}; +use mchprs_redpiler::{Compiler, CompilerOptions}; +use mchprs_save_data::plot_data::PlotData; +use mchprs_world::World; + +use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; + +fn load_plot(path: impl AsRef) -> PlotWorld { + let plot_data = PlotData::load_from_file(path).unwrap(); + let chunks = plot_data + .chunk_data + .into_iter() + .enumerate() + .map(|(i, c)| c.load(i as i32 / PLOT_WIDTH, i as i32 % PLOT_WIDTH)); + PlotWorld { + x: 0, + z: 0, + chunks: chunks.collect(), + to_be_ticked: plot_data.pending_ticks, + packet_senders: Vec::new(), + } +} + +const PLOTS: [(&str, BlockPos); 4] = [ + ("adder", BlockPos::new(30, 3, 46)), + ("call_stack", BlockPos::new(29, 0, 10)), + ("long_wire", BlockPos::new(31, 1, 16)), + ("repeater_grid", BlockPos::new(16, 1, 16)), +]; + +fn bench_compile(c: &mut Criterion) { + let compile_options = CompilerOptions::default(); + let mut group = c.benchmark_group("compile_unoptimized"); + for (plot_name, _) in PLOTS { + let world = load_plot(format!("benches/plots/{plot_name}")); + let bounds = world.get_corners(); + group.bench_function(plot_name, |bencher| { + bencher.iter_batched_ref( + Compiler::default, + |compiler: &mut Compiler| { + compiler.compile( + &world, + bounds, + compile_options, + Default::default(), + Default::default(), + ); + }, + BatchSize::LargeInput, + ); + }); + } +} + +fn bench_tick(c: &mut Criterion) { + let compile_options = CompilerOptions::default(); + let mut group = c.benchmark_group("tick_unoptimized"); + for (plot_name, start_trigger_pos) in PLOTS { + let world = load_plot(format!("benches/plots/{plot_name}")); + let bounds = world.get_corners(); + assert!(matches!( + world.get_block(start_trigger_pos), + Block::StoneButton { .. } | Block::Lever { .. } + )); + let setup = || { + let mut compiler = Compiler::default(); + compiler.compile( + &world, + bounds, + compile_options, + Default::default(), + Default::default(), + ); + compiler.on_use_block(start_trigger_pos); + compiler + }; + group.bench_function(plot_name, |bencher| { + bencher.iter_batched_ref( + setup, + |compiler: &mut Compiler| { + while compiler.has_pending_ticks() { + compiler.tick(); + } + }, + BatchSize::LargeInput, + ); + }); + } +} + +criterion_group!(benches, bench_compile, bench_tick); +criterion_main!(benches); diff --git a/crates/redpiler/src/lib.rs b/crates/redpiler/src/lib.rs index 36d3c162..42429efb 100644 --- a/crates/redpiler/src/lib.rs +++ b/crates/redpiler/src/lib.rs @@ -31,7 +31,7 @@ fn block_powered_mut(block: &mut Block) -> Option<&mut bool> { }) } -#[derive(Default, PartialEq, Eq, Debug, Clone)] +#[derive(Default, PartialEq, Eq, Debug, Clone, Copy)] pub struct CompilerOptions { /// Enable optimization passes which may significantly increase compile times. pub optimize: bool,