Use FxHash

This commit is contained in:
IQuant 2024-06-04 21:53:34 +03:00
parent 5419556f88
commit 4050fe5c0d
7 changed files with 36 additions and 17 deletions

View file

@ -1820,6 +1820,7 @@ dependencies = [
"poll-promise", "poll-promise",
"rand", "rand",
"reqwest", "reqwest",
"rustc-hash",
"self-replace", "self-replace",
"serde", "serde",
"serde_json", "serde_json",
@ -2491,6 +2492,12 @@ version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.34" version = "0.38.34"

View file

@ -33,6 +33,7 @@ image = { version = "0.25.1", default_features = false, features = ["png"] }
egui_extras = { version = "*", features = ["all_loaders"] } egui_extras = { version = "*", features = ["all_loaders"] }
bytemuck = { version = "1.16.0", features = ["derive"] } bytemuck = { version = "1.16.0", features = ["derive"] }
bincode = "1.3.3" bincode = "1.3.3"
rustc-hash = "1.1.0"
[profile.dev] [profile.dev]
opt-level = 1 opt-level = 1

View file

@ -1,5 +1,6 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{fs::File, io::BufWriter}; use std::{fs::File, io::BufWriter};
use world_model::WorldModel;
pub use world_model::encoding::NoitaWorldUpdate; pub use world_model::encoding::NoitaWorldUpdate;
@ -12,22 +13,25 @@ pub enum WorldUpdateKind {
} }
pub struct WorldManager { pub struct WorldManager {
pub(crate) writer: BufWriter<File>, // pub(crate) writer: BufWriter<File>,
model: WorldModel,
} }
impl WorldManager { impl WorldManager {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
writer: BufWriter::new(File::create("worldlog.bin").unwrap()), // writer: BufWriter::new(File::create("worldlog.bin").unwrap()),
model: WorldModel::new(),
} }
} }
pub fn add_update(&mut self, update: NoitaWorldUpdate) { pub fn add_update(&mut self, update: NoitaWorldUpdate) {
bincode::serialize_into(&mut self.writer, &WorldUpdateKind::Update(update)).unwrap(); // bincode::serialize_into(&mut self.writer, &WorldUpdateKind::Update(update)).unwrap();
self.model.apply_noita_update(&update);
} }
pub fn add_end(&mut self) { pub fn add_end(&mut self) {
bincode::serialize_into(&mut self.writer, &WorldUpdateKind::End).unwrap(); // bincode::serialize_into(&mut self.writer, &WorldUpdateKind::End).unwrap();
} }
} }
@ -43,6 +47,8 @@ mod test {
let mut model = WorldModel::new(); let mut model = WorldModel::new();
let mut model2 = WorldModel::new(); let mut model2 = WorldModel::new();
let mut entry_id = 0; let mut entry_id = 0;
let mut deltas_size = 0;
while let Ok(entry) = bincode::deserialize_from::<_, WorldUpdateKind>(&mut file) while let Ok(entry) = bincode::deserialize_from::<_, WorldUpdateKind>(&mut file)
.inspect_err(|e| println!("{}", e)) .inspect_err(|e| println!("{}", e))
{ {
@ -59,7 +65,7 @@ mod test {
entry.header.w as u32 + 1, entry.header.w as u32 + 1,
entry.header.h as u32 + 1, entry.header.h as u32 + 1,
); );
// TODO
assert_eq!(entry, new_update); assert_eq!(entry, new_update);
} }
WorldUpdateKind::End => { WorldUpdateKind::End => {
@ -70,6 +76,7 @@ mod test {
img.save(format!("/tmp/img_{}.png", entry_id)).unwrap(); img.save(format!("/tmp/img_{}.png", entry_id)).unwrap();
} }
let deltas = model.get_all_deltas(); let deltas = model.get_all_deltas();
deltas_size += lz4_flex::compress_prepend_size(&bitcode::encode(&deltas)).len();
model.reset_change_tracking(); model.reset_change_tracking();
model2.apply_all_deltas(&deltas); model2.apply_all_deltas(&deltas);
@ -84,6 +91,7 @@ mod test {
let img = model2.gen_image(x, y, 2048 * 2, 2048 * 2); let img = model2.gen_image(x, y, 2048 * 2, 2048 * 2);
img.save(format!("/tmp/img_model2.png")).unwrap(); img.save(format!("/tmp/img_model2.png")).unwrap();
println!("Deltas: {} bytes", deltas_size)
// let mut mats = model.mats.iter().copied().collect::<Vec<_>>(); // let mut mats = model.mats.iter().copied().collect::<Vec<_>>();
// mats.sort(); // mats.sort();
// for mat in mats { // for mat in mats {

View file

@ -1,7 +1,9 @@
use bitcode::{Decode, Encode};
use chunk::{Chunk, Pixel, PixelFlags}; use chunk::{Chunk, Pixel, PixelFlags};
use encoding::{NoitaWorldUpdate, PixelRun, PixelRunner}; use encoding::{NoitaWorldUpdate, PixelRun, PixelRunner};
use image::{Rgb, RgbImage}; use image::{Rgb, RgbImage};
use std::collections::{HashMap, HashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use std::collections::HashSet;
mod chunk; mod chunk;
pub mod encoding; pub mod encoding;
@ -11,8 +13,8 @@ const CHUNK_SIZE: usize = 256;
type ChunkCoord = (i32, i32); type ChunkCoord = (i32, i32);
pub struct WorldModel { pub struct WorldModel {
chunks: HashMap<ChunkCoord, Chunk>, chunks: FxHashMap<ChunkCoord, Chunk>,
pub mats: HashSet<u16>, pub mats: FxHashSet<u16>,
palette: MatPalette, palette: MatPalette,
changed_chunks: HashSet<ChunkCoord>, changed_chunks: HashSet<ChunkCoord>,
} }
@ -21,7 +23,7 @@ struct MatPalette {
colors: Vec<Rgb<u8>>, colors: Vec<Rgb<u8>>,
} }
#[derive(Debug)] #[derive(Debug, Encode, Decode)]
pub struct ChunkDelta { pub struct ChunkDelta {
runs: Vec<PixelRun<Option<Pixel>>>, runs: Vec<PixelRun<Option<Pixel>>>,
chunk_coord: (i32, i32), chunk_coord: (i32, i32),

View file

@ -1,6 +1,8 @@
use bitcode::{Decode, Encode};
use super::{encoding::RawPixel, CHUNK_SIZE}; use super::{encoding::RawPixel, CHUNK_SIZE};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Encode, Decode)]
pub enum PixelFlags { pub enum PixelFlags {
#[default] #[default]
Unknown, Unknown,
@ -8,7 +10,7 @@ pub enum PixelFlags {
Fluid, Fluid,
} }
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Encode, Decode)]
pub struct Pixel { pub struct Pixel {
pub flags: PixelFlags, pub flags: PixelFlags,
pub material: u16, pub material: u16,

View file

@ -1,9 +1,8 @@
use bitcode::{Decode, Encode};
use bytemuck::{bytes_of, pod_read_unaligned, AnyBitPattern, NoUninit}; use bytemuck::{bytes_of, pod_read_unaligned, AnyBitPattern, NoUninit};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::mem::size_of; use std::mem::size_of;
use super::chunk::Pixel;
#[derive(Debug, Clone, Copy, AnyBitPattern, NoUninit, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Clone, Copy, AnyBitPattern, NoUninit, Serialize, Deserialize, PartialEq, Eq)]
#[repr(C)] #[repr(C)]
pub(crate) struct Header { pub(crate) struct Header {
@ -28,7 +27,7 @@ pub(crate) struct RawPixel {
/// Stores a run of pixels. /// Stores a run of pixels.
/// Not specific to Noita side - length is an actual length /// Not specific to Noita side - length is an actual length
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Encode, Decode)]
pub struct PixelRun<Pixel> { pub struct PixelRun<Pixel> {
pub length: u32, pub length: u32,
pub data: Pixel, pub data: Pixel,

View file

@ -45,7 +45,7 @@ function world_sync.on_world_update_host()
end_y = end_y + 2 end_y = end_y + 2
local rectangle = rect.Rectangle(start_x, start_y, end_x, end_y) local rectangle = rect.Rectangle(start_x, start_y, end_x, end_y)
-- rect_optimiser:submit(rectangle) rect_optimiser:submit(rectangle)
end end
for i = 0, tonumber(thread_impl.world_update_params_count) - 1 do for i = 0, tonumber(thread_impl.world_update_params_count) - 1 do
local wup = thread_impl.world_update_params.begin[i] local wup = thread_impl.world_update_params.begin[i]
@ -55,7 +55,7 @@ function world_sync.on_world_update_host()
local end_y = wup.update_region.bottom_right.y local end_y = wup.update_region.bottom_right.y
local rectangle = rect.Rectangle(start_x, start_y, end_x, end_y) local rectangle = rect.Rectangle(start_x, start_y, end_x, end_y)
-- rect_optimiser:submit(rectangle) rect_optimiser:submit(rectangle)
end end
local px, py = EntityGetTransform(ctx.my_player.entity) local px, py = EntityGetTransform(ctx.my_player.entity)
@ -74,7 +74,7 @@ function world_sync.on_world_update_host()
end end
end end
if GameGetFrameNum() % 1 == 0 then if GameGetFrameNum() % 10 == 0 then
rect_optimiser:scan() rect_optimiser:scan()
for crect in rect.parts(rect_optimiser:iterate(), 256) do for crect in rect.parts(rect_optimiser:iterate(), 256) do