From f8130c3c92946d2293634ba4e252d6bc93026c3c Mon Sep 17 00:00:00 2001 From: mat Date: Sun, 23 Feb 2025 03:10:21 +0000 Subject: [PATCH] minor memory usage optimizations --- Cargo.lock | 31 +++++++++ Cargo.toml | 1 + azalea-buf/src/read.rs | 7 ++ azalea-buf/src/write.rs | 7 ++ azalea-client/src/disconnect.rs | 3 +- azalea-client/src/test_simulation.rs | 2 +- azalea-language/Cargo.toml | 1 + azalea-language/src/lib.rs | 4 +- azalea-physics/src/fluids.rs | 14 +++- .../packets/game/c_level_chunk_with_light.rs | 12 +++- azalea-world/src/chunk_storage.rs | 1 + azalea/examples/testbot/commands/debug.rs | 68 ++++++++++++++++++- 12 files changed, 141 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b3cbfd63..e37ae92d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -449,6 +449,7 @@ dependencies = [ name = "azalea-language" version = "0.11.0+mc1.21.4" dependencies = [ + "compact_str", "serde", "serde_json", ] @@ -823,6 +824,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "castaway" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" +dependencies = [ + "rustversion", +] + [[package]] name = "cc" version = "1.2.15" @@ -951,6 +961,21 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "compact_str" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "serde", + "static_assertions", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -2907,6 +2932,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "subtle" version = "2.6.1" diff --git a/Cargo.toml b/Cargo.toml index dd3c6bcf..f549d16f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,6 +80,7 @@ hickory-resolver = { version = "0.24.3", default-features = false } uuid = "1.12.1" num-format = "0.4.4" indexmap = "2.7.1" +compact_str = "0.8.1" # --- Profile Settings --- diff --git a/azalea-buf/src/read.rs b/azalea-buf/src/read.rs index e6f7aa51..324eab87 100755 --- a/azalea-buf/src/read.rs +++ b/azalea-buf/src/read.rs @@ -3,6 +3,7 @@ use std::{ collections::HashMap, hash::Hash, io::{Cursor, Read}, + sync::Arc, }; use byteorder::{BE, ReadBytesExt}; @@ -423,3 +424,9 @@ impl AzaleaRead for (A, B) { Ok((A::azalea_read(buf)?, B::azalea_read(buf)?)) } } + +impl AzaleaRead for Arc { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result { + Ok(Arc::new(T::azalea_read(buf)?)) + } +} diff --git a/azalea-buf/src/write.rs b/azalea-buf/src/write.rs index c4b9f413..73aefe40 100755 --- a/azalea-buf/src/write.rs +++ b/azalea-buf/src/write.rs @@ -1,6 +1,7 @@ use std::{ collections::HashMap, io::{self, Write}, + sync::Arc, }; use byteorder::{BigEndian, WriteBytesExt}; @@ -298,3 +299,9 @@ impl AzaleaWrite for (A, B) { self.1.azalea_write(buf) } } + +impl AzaleaWrite for Arc { + fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { + T::azalea_write(&**self, buf) + } +} diff --git a/azalea-client/src/disconnect.rs b/azalea-client/src/disconnect.rs index a1eac971..bd10ac75 100644 --- a/azalea-client/src/disconnect.rs +++ b/azalea-client/src/disconnect.rs @@ -1,7 +1,7 @@ //! Disconnect a client from the server. use azalea_chat::FormattedText; -use azalea_entity::{EntityBundle, LocalEntity, metadata::PlayerMetadataBundle}; +use azalea_entity::{EntityBundle, InLoadedChunk, LocalEntity, metadata::PlayerMetadataBundle}; use bevy_app::{App, Plugin, PostUpdate}; use bevy_ecs::{ component::Component, @@ -57,6 +57,7 @@ pub fn remove_components_from_disconnected_players( .remove::() .remove::() .remove::() + .remove::() // this makes it close the tcp connection .remove::() // swarm detects when this tx gets dropped to fire SwarmEvent::Disconnect diff --git a/azalea-client/src/test_simulation.rs b/azalea-client/src/test_simulation.rs index 38cfbc15..2479e953 100644 --- a/azalea-client/src/test_simulation.rs +++ b/azalea-client/src/test_simulation.rs @@ -257,7 +257,7 @@ pub fn make_basic_empty_chunk( z: pos.z, chunk_data: ClientboundLevelChunkPacketData { heightmaps: Nbt::None, - data: chunk_bytes, + data: chunk_bytes.into(), block_entities: vec![], }, light_data: ClientboundLightUpdatePacketData::default(), diff --git a/azalea-language/Cargo.toml b/azalea-language/Cargo.toml index c19a2689..983ac7f9 100644 --- a/azalea-language/Cargo.toml +++ b/azalea-language/Cargo.toml @@ -7,5 +7,6 @@ license.workspace = true repository.workspace = true [dependencies] +compact_str = { workspace = true, features = ["serde"] } serde.workspace = true serde_json.workspace = true diff --git a/azalea-language/src/lib.rs b/azalea-language/src/lib.rs index 33014144..bb5d144e 100755 --- a/azalea-language/src/lib.rs +++ b/azalea-language/src/lib.rs @@ -2,7 +2,9 @@ use std::{collections::HashMap, sync::LazyLock}; -pub static STORAGE: LazyLock> = +use compact_str::CompactString; + +pub static STORAGE: LazyLock> = LazyLock::new(|| serde_json::from_str(include_str!("en_us.json")).unwrap()); pub fn get(key: &str) -> Option<&str> { diff --git a/azalea-physics/src/fluids.rs b/azalea-physics/src/fluids.rs index 7a0c86a9..bbc044f6 100644 --- a/azalea-physics/src/fluids.rs +++ b/azalea-physics/src/fluids.rs @@ -5,6 +5,7 @@ use azalea_block::{ use azalea_core::{ direction::Direction, position::{BlockPos, Vec3}, + resource_location::ResourceLocation, }; use azalea_entity::{InLoadedChunk, LocalEntity, Physics, Position}; use azalea_world::{Instance, InstanceContainer, InstanceName}; @@ -31,11 +32,18 @@ pub fn update_in_water_state_and_do_fluid_pushing( update_in_water_state_and_do_water_current_pushing(&mut physics, &world, position); + // right now doing registries.dimension_type() clones the entire registry which + // is very inefficient, so for now we're doing this instead + let is_ultrawarm = world .registries - .dimension_type() - .and_then(|d| d.map.get(instance_name).map(|d| d.ultrawarm)) - == Some(Some(true)); + .map + .get(&ResourceLocation::new("minecraft:dimension_type")) + .and_then(|d| { + d.get(&**instance_name) + .map(|d| d.byte("ultrawarm") != Some(0)) + }) + .unwrap_or_default(); let lava_push_factor = if is_ultrawarm { 0.007 } else { diff --git a/azalea-protocol/src/packets/game/c_level_chunk_with_light.rs b/azalea-protocol/src/packets/game/c_level_chunk_with_light.rs index 9166e0eb..43237c3b 100755 --- a/azalea-protocol/src/packets/game/c_level_chunk_with_light.rs +++ b/azalea-protocol/src/packets/game/c_level_chunk_with_light.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use azalea_buf::AzBuf; use azalea_protocol_macros::ClientboundGamePacket; use simdnbt::owned::Nbt; @@ -16,8 +18,14 @@ pub struct ClientboundLevelChunkWithLight { #[derive(Clone, Debug, AzBuf)] pub struct ClientboundLevelChunkPacketData { pub heightmaps: Nbt, - // we can't parse the data in azalea-protocol because it depends on context from other packets - pub data: Vec, + /// The raw chunk sections. + /// + /// We can't parse the data in azalea-protocol because it depends on context + /// from other packets + /// + /// This is an Arc because it's often very big and we want it to be cheap to + /// clone. + pub data: Arc>, pub block_entities: Vec, } diff --git a/azalea-world/src/chunk_storage.rs b/azalea-world/src/chunk_storage.rs index 9852dd1a..455d87e7 100755 --- a/azalea-world/src/chunk_storage.rs +++ b/azalea-world/src/chunk_storage.rs @@ -448,6 +448,7 @@ impl AzaleaRead for Section { let block_count = u16::azalea_read(buf)?; // this is commented out because the vanilla server is wrong + // ^ this comment was written ages ago. needs more investigation. // assert!( // block_count <= 16 * 16 * 16, // "A section has more blocks than what should be possible. This is a bug!" diff --git a/azalea/examples/testbot/commands/debug.rs b/azalea/examples/testbot/commands/debug.rs index fe552668..df98511d 100644 --- a/azalea/examples/testbot/commands/debug.rs +++ b/azalea/examples/testbot/commands/debug.rs @@ -5,11 +5,15 @@ use std::{env, fs::File, io::Write, thread, time::Duration}; use azalea::{ BlockPos, brigadier::prelude::*, + chunks::ReceiveChunkEvent, entity::{LookDirection, Position}, interact::HitResultComponent, + packet_handling::game, pathfinder::{ExecutingPath, Pathfinder}, world::MinecraftEntityId, }; +use azalea_world::InstanceContainer; +use bevy_ecs::event::Events; use parking_lot::Mutex; use super::{CommandSource, Ctx}; @@ -200,8 +204,53 @@ pub fn register(commands: &mut CommandDispatcher>) { writeln!(report).unwrap(); for (info, _) in ecs.iter_resources() { - writeln!(report, "Resource: {}", info.name()).unwrap(); - writeln!(report, "- Size: {} bytes", info.layout().size()).unwrap(); + let name = info.name(); + writeln!(report, "Resource: {name}").unwrap(); + // writeln!(report, "- Size: {} bytes", + // info.layout().size()).unwrap(); + + match name { + "azalea_world::container::InstanceContainer" => { + let instance_container = ecs.resource::(); + for (instance_name, instance) in &instance_container.instances { + writeln!(report, "- Name: {}", instance_name).unwrap(); + writeln!(report, "- Reference count: {}", instance.strong_count()) + .unwrap(); + if let Some(instance) = instance.upgrade() { + let instance = instance.read(); + let strong_chunks = instance + .chunks + .map + .iter() + .filter(|(_, v)| v.strong_count() > 0) + .count(); + writeln!( + report, + "- Chunks: {} strongly referenced, {} in map", + strong_chunks, + instance.chunks.map.len() + ) + .unwrap(); + writeln!( + report, + "- Entities: {}", + instance.entities_by_chunk.len() + ) + .unwrap(); + } + } + } + "bevy_ecs::event::collections::Events" => { + let events = ecs.resource::>(); + writeln!(report, "- Event count: {}", events.len()).unwrap(); + } + "bevy_ecs::event::collections::Events" => { + let events = ecs.resource::>(); + writeln!(report, "- Event count: {}", events.len()).unwrap(); + } + + _ => {} + } } println!("\x1b[1mWrote report to {}\x1b[m", report_path.display()); @@ -209,4 +258,19 @@ pub fn register(commands: &mut CommandDispatcher>) { 1 })); + + commands.register(literal("exit").executes(|ctx: &Ctx| { + let source = ctx.source.lock(); + source.reply("bye!"); + + source.bot.disconnect(); + + thread::spawn(move || { + thread::sleep(Duration::from_secs(1)); + + std::process::exit(0); + }); + + 1 + })); }