diff options
| author | mat <github@matdoes.dev> | 2023-03-24 13:55:11 +0000 |
|---|---|---|
| committer | mat <github@matdoes.dev> | 2023-03-24 13:55:11 +0000 |
| commit | 4b387c320c126d2db69ec6f2dc1a610a58928a2e (patch) | |
| tree | 56a22a7872cd1309721c05a770bebac05d0adedb | |
| parent | bdc42557479e6201f88151468ef1331820f62681 (diff) | |
| parent | 0641dac7f0aa6c055fca8ab633ad85859d0ddd97 (diff) | |
| download | azalea-drasl-4b387c320c126d2db69ec6f2dc1a610a58928a2e.tar.xz | |
fix merge conflict
| -rw-r--r-- | Cargo.lock | 17 | ||||
| -rw-r--r-- | azalea-nbt/Cargo.toml | 1 | ||||
| -rwxr-xr-x | azalea-nbt/benches/compare.rs | 2 | ||||
| -rwxr-xr-x | azalea-nbt/benches/nbt.rs | 33 | ||||
| -rwxr-xr-x | azalea-nbt/src/encode.rs | 73 | ||||
| -rwxr-xr-x | azalea-nbt/src/tag.rs | 90 | ||||
| -rw-r--r-- | azalea-nbt/tests/inttest1023.nbt | bin | 0 -> 4104 bytes | |||
| -rwxr-xr-x | azalea-nbt/tests/inttest16.nbt (renamed from azalea-nbt/tests/inttest.nbt) | bin | 95 -> 95 bytes | |||
| -rw-r--r-- | azalea-nbt/tests/inttest3.nbt | bin | 0 -> 24 bytes | |||
| -rwxr-xr-x | azalea-nbt/tests/tests.rs | 32 |
10 files changed, 222 insertions, 26 deletions
@@ -345,6 +345,7 @@ dependencies = [ "flate2", "graphite_binary", "log", + "packed_simd_2", "serde", "valence_nbt", ] @@ -1515,6 +1516,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" [[package]] +name = "libm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" + +[[package]] name = "linked-hash-map" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1741,6 +1748,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] +name = "packed_simd_2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282" +dependencies = [ + "cfg-if", + "libm", +] + +[[package]] name = "parking" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/azalea-nbt/Cargo.toml b/azalea-nbt/Cargo.toml index 2c35c3da..bead5ba3 100644 --- a/azalea-nbt/Cargo.toml +++ b/azalea-nbt/Cargo.toml @@ -15,6 +15,7 @@ compact_str = { version = "0.7.0", features = ["serde"] } enum-as-inner = "0.5.1" flate2 = "^1.0.25" log = "0.4.17" +packed_simd_2 = "0.3.8" serde = { version = "1.0.152", features = ["derive"], optional = true } [dev-dependencies] diff --git a/azalea-nbt/benches/compare.rs b/azalea-nbt/benches/compare.rs index f0fa17c0..23e133da 100755 --- a/azalea-nbt/benches/compare.rs +++ b/azalea-nbt/benches/compare.rs @@ -79,7 +79,7 @@ pub fn bench_read_file(filename: &str, c: &mut Criterion) { } fn bench(c: &mut Criterion) { - bench_read_file("tests/bigtest.nbt", c); + // bench_read_file("tests/bigtest.nbt", c); // bench_read_file("tests/simple_player.dat", c); // bench_read_file("tests/complex_player.dat", c); // bench_read_file("tests/level.dat", c); diff --git a/azalea-nbt/benches/nbt.rs b/azalea-nbt/benches/nbt.rs index 0d413103..a219a46d 100755 --- a/azalea-nbt/benches/nbt.rs +++ b/azalea-nbt/benches/nbt.rs @@ -15,7 +15,10 @@ fn bench_file(filename: &str, c: &mut Criterion) { // decode the original src so most of the time isn't spent on unzipping let mut decoded_src_decoder = GzDecoder::new(&mut src); let mut decoded_src = Vec::new(); - decoded_src_decoder.read_to_end(&mut decoded_src).unwrap(); + if decoded_src_decoder.read_to_end(&mut decoded_src).is_err() { + // oh probably wasn't gzipped then + decoded_src = contents; + } let mut decoded_src_stream = Cursor::new(&decoded_src[..]); @@ -26,12 +29,12 @@ fn bench_file(filename: &str, c: &mut Criterion) { group.throughput(Throughput::Bytes(decoded_src.len() as u64)); - group.bench_function("Decode", |b| { - b.iter(|| { - black_box(Nbt::read(&mut decoded_src_stream).unwrap()); - decoded_src_stream.set_position(0); - }) - }); + // group.bench_function("Decode", |b| { + // b.iter(|| { + // black_box(Nbt::read(&mut decoded_src_stream).unwrap()); + // decoded_src_stream.set_position(0); + // }) + // }); // group.bench_function("Encode", |b| { // b.iter(|| { @@ -41,7 +44,16 @@ fn bench_file(filename: &str, c: &mut Criterion) { group.bench_function("Get", |b| { b.iter(|| { - black_box(nbt.as_compound().unwrap().get("")); + let level = nbt + .as_compound() + .unwrap() + .get("Level") + .unwrap() + .as_compound() + .unwrap(); + for (k, _) in level.iter() { + black_box(level.get(black_box(k))); + } }) }); group.finish(); @@ -53,7 +65,10 @@ fn bench(c: &mut Criterion) { // bench_file("tests/complex_player.dat", c); // bench_file("tests/level.dat", c); // bench_file("tests/stringtest.nbt", c); - // bench_file("tests/inttest.nbt", c); + // bench_file("tests/inttest16.nbt", c); + + // bench_file("tests/inttest1023.nbt", c); + // bench_file("tests/inttest3.nbt", c); } criterion_group!(benches, bench); diff --git a/azalea-nbt/src/encode.rs b/azalea-nbt/src/encode.rs index bf56c223..f5195327 100755 --- a/azalea-nbt/src/encode.rs +++ b/azalea-nbt/src/encode.rs @@ -2,6 +2,7 @@ use crate::tag::*; use azalea_buf::McBufWritable; use byteorder::{WriteBytesExt, BE}; use flate2::write::{GzEncoder, ZlibEncoder}; +use packed_simd_2::{i32x16, i32x2, i32x4, i32x8, i64x2, i64x4, i64x8}; use std::io::Write; #[inline(always)] @@ -81,14 +82,78 @@ fn write_list(writer: &mut impl Write, value: &NbtList) { } NbtList::Int(l) => { writer.write_i32::<BE>(l.len() as i32).unwrap(); - for &v in l { - writer.write_i32::<BE>(v).unwrap(); + // flip the bits to big endian with simd + let l = l.as_slice(); + let mut position = 0; + // x16 + while l.len() - position >= 16 { + let l = unsafe { i32x16::from_slice_unaligned_unchecked(&l[position..]) }; + l.to_be(); + let l = unsafe { std::mem::transmute::<i32x16, [u8; 64]>(l) }; + writer.write_all(&l).unwrap(); + position += 16; + } + // x8 + if l.len() - position >= 8 { + let l = unsafe { i32x8::from_slice_unaligned_unchecked(&l[position..]) }; + l.to_be(); + let l = unsafe { std::mem::transmute::<i32x8, [u8; 32]>(l) }; + writer.write_all(&l).unwrap(); + position += 8; + } + // x4 + if l.len() - position >= 4 { + let l = unsafe { i32x4::from_slice_unaligned_unchecked(&l[position..]) }; + l.to_be(); + let l = unsafe { std::mem::transmute::<i32x4, [u8; 16]>(l) }; + writer.write_all(&l).unwrap(); + position += 4; + } + // x2 + if l.len() - position >= 2 { + let l = unsafe { i32x2::from_slice_unaligned_unchecked(&l[position..]) }; + l.to_be(); + let l = unsafe { std::mem::transmute::<i32x2, [u8; 8]>(l) }; + writer.write_all(&l).unwrap(); + position += 2; + } + // x1 ... just a normal write_i32 + if l.len() - position >= 1 { + writer.write_i32::<BE>(l[position]).unwrap(); } } NbtList::Long(l) => { writer.write_i32::<BE>(l.len() as i32).unwrap(); - for &v in l { - writer.write_i64::<BE>(v).unwrap(); + // flip the bits to big endian with simd + let l = l.as_slice(); + let mut position = 0; + // x16 + while l.len() - position >= 8 { + let l = unsafe { i64x8::from_slice_unaligned_unchecked(&l[position..]) }; + l.to_be(); + let l = unsafe { std::mem::transmute::<i64x8, [u8; 64]>(l) }; + writer.write_all(&l).unwrap(); + position += 8; + } + // x4 + if l.len() - position >= 4 { + let l = unsafe { i64x4::from_slice_unaligned_unchecked(&l[position..]) }; + l.to_be(); + let l = unsafe { std::mem::transmute::<i64x4, [u8; 32]>(l) }; + writer.write_all(&l).unwrap(); + position += 4; + } + // x2 + if l.len() - position >= 2 { + let l = unsafe { i64x2::from_slice_unaligned_unchecked(&l[position..]) }; + l.to_be(); + let l = unsafe { std::mem::transmute::<i64x2, [u8; 16]>(l) }; + writer.write_all(&l).unwrap(); + position += 2; + } + // x1 ... just a normal write_i32 + if l.len() - position >= 1 { + writer.write_i64::<BE>(l[position]).unwrap(); } } NbtList::Float(l) => { diff --git a/azalea-nbt/src/tag.rs b/azalea-nbt/src/tag.rs index 32d73a7c..efb6bdd2 100755 --- a/azalea-nbt/src/tag.rs +++ b/azalea-nbt/src/tag.rs @@ -48,6 +48,17 @@ pub enum Nbt { IntArray(NbtIntArray) = INT_ARRAY_ID, LongArray(NbtLongArray) = LONG_ARRAY_ID, } +impl Nbt { + /// Get the numerical ID of the tag type. + #[inline] + pub fn id(&self) -> u8 { + // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a `repr(C)` + // `union` between `repr(C)` structs, each of which has the `u8` + // discriminant as its first field, so we can read the discriminant + // without offsetting the pointer. + unsafe { *<*const _>::from(self).cast::<u8>() } + } +} /// An NBT value. #[derive(Clone, Debug, PartialEq)] @@ -69,7 +80,7 @@ pub enum NbtList { LongArray(Vec<NbtLongArray>) = LONG_ARRAY_ID, } -impl Nbt { +impl NbtList { /// Get the numerical ID of the tag type. #[inline] pub fn id(&self) -> u8 { @@ -80,15 +91,64 @@ impl Nbt { unsafe { *<*const _>::from(self).cast::<u8>() } } } -impl NbtList { - /// Get the numerical ID of the tag type. - #[inline] - pub fn id(&self) -> u8 { - // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a `repr(C)` - // `union` between `repr(C)` structs, each of which has the `u8` - // discriminant as its first field, so we can read the discriminant - // without offsetting the pointer. - unsafe { *<*const _>::from(self).cast::<u8>() } +impl From<Vec<NbtByte>> for NbtList { + fn from(v: Vec<NbtByte>) -> Self { + Self::Byte(v) + } +} +impl From<Vec<NbtShort>> for NbtList { + fn from(v: Vec<NbtShort>) -> Self { + Self::Short(v) + } +} +impl From<Vec<NbtInt>> for NbtList { + fn from(v: Vec<NbtInt>) -> Self { + Self::Int(v) + } +} +impl From<Vec<NbtLong>> for NbtList { + fn from(v: Vec<NbtLong>) -> Self { + Self::Long(v) + } +} +impl From<Vec<NbtFloat>> for NbtList { + fn from(v: Vec<NbtFloat>) -> Self { + Self::Float(v) + } +} +impl From<Vec<NbtDouble>> for NbtList { + fn from(v: Vec<NbtDouble>) -> Self { + Self::Double(v) + } +} +impl From<Vec<NbtByteArray>> for NbtList { + fn from(v: Vec<NbtByteArray>) -> Self { + Self::ByteArray(v) + } +} +impl From<Vec<NbtString>> for NbtList { + fn from(v: Vec<NbtString>) -> Self { + Self::String(v) + } +} +impl From<Vec<NbtList>> for NbtList { + fn from(v: Vec<NbtList>) -> Self { + Self::List(v) + } +} +impl From<Vec<NbtCompound>> for NbtList { + fn from(v: Vec<NbtCompound>) -> Self { + Self::Compound(v) + } +} +impl From<Vec<NbtIntArray>> for NbtList { + fn from(v: Vec<NbtIntArray>) -> Self { + Self::IntArray(v) + } +} +impl From<Vec<NbtLongArray>> for NbtList { + fn from(v: Vec<NbtLongArray>) -> Self { + Self::LongArray(v) } } @@ -161,7 +221,9 @@ impl NbtCompound { #[inline] fn is_worth_sorting(&self) -> bool { - self.inner.len() >= 128 + // i don't actually know when binary search starts being better, but it's at + // least more than 12 + self.inner.len() >= 32 } } #[cfg(feature = "serde")] @@ -191,3 +253,9 @@ impl FromIterator<(NbtString, Nbt)> for NbtCompound { Self { inner } } } + +impl From<Vec<(NbtString, Nbt)>> for NbtCompound { + fn from(inner: Vec<(NbtString, Nbt)>) -> Self { + Self { inner } + } +} diff --git a/azalea-nbt/tests/inttest1023.nbt b/azalea-nbt/tests/inttest1023.nbt Binary files differnew file mode 100644 index 00000000..481dde19 --- /dev/null +++ b/azalea-nbt/tests/inttest1023.nbt diff --git a/azalea-nbt/tests/inttest.nbt b/azalea-nbt/tests/inttest16.nbt Binary files differindex ad9255f2..ad9255f2 100755 --- a/azalea-nbt/tests/inttest.nbt +++ b/azalea-nbt/tests/inttest16.nbt diff --git a/azalea-nbt/tests/inttest3.nbt b/azalea-nbt/tests/inttest3.nbt Binary files differnew file mode 100644 index 00000000..2890f577 --- /dev/null +++ b/azalea-nbt/tests/inttest3.nbt diff --git a/azalea-nbt/tests/tests.rs b/azalea-nbt/tests/tests.rs index a7f6912f..5c82c3c7 100755 --- a/azalea-nbt/tests/tests.rs +++ b/azalea-nbt/tests/tests.rs @@ -1,4 +1,4 @@ -use azalea_nbt::{NbtCompound, NbtList, Nbt}; +use azalea_nbt::{Nbt, NbtCompound, NbtList}; use std::io::Cursor; #[test] @@ -108,3 +108,33 @@ fn test_simple_player() { assert_eq!(decoded_tag, original_tag); } + +// #[test] +// fn test_inttest() { +// let original = include_bytes!("inttest.nbt").to_vec(); + +// let mut original_stream = Cursor::new(original); +// let original_tag = Nbt::read_gzip(&mut original_stream).unwrap(); + +// let mut result = Vec::new(); +// original_tag.write(&mut result); + +// let decoded_tag = Nbt::read(&mut Cursor::new(&result)).unwrap(); + +// assert_eq!(decoded_tag, original_tag); +// } + +#[test] +fn test_inttest1023() { + let original = include_bytes!("inttest1023.nbt").to_vec(); + + let mut original_stream = Cursor::new(original.as_slice()); + let original_tag = Nbt::read(&mut original_stream).unwrap(); + + let mut result = Vec::new(); + original_tag.write(&mut result); + + let decoded_tag = Nbt::read(&mut Cursor::new(&result)).unwrap(); + + assert_eq!(decoded_tag, original_tag); +} |
