diff --git a/azalea-nbt/benches/my_benchmark.rs b/azalea-nbt/benches/my_benchmark.rs index 30de196c..3d7eaeee 100644 --- a/azalea-nbt/benches/my_benchmark.rs +++ b/azalea-nbt/benches/my_benchmark.rs @@ -1,5 +1,6 @@ use azalea_nbt::Tag; use criterion::{criterion_group, criterion_main, Criterion, Throughput}; +use flate2::read::GzDecoder; use std::{ fs::File, io::{self, Read, Seek, SeekFrom}, @@ -10,18 +11,25 @@ fn bench_serialize(filename: &str, c: &mut Criterion) { let mut contents = Vec::new(); file.read_to_end(&mut contents).unwrap(); let mut src = std::io::Cursor::new(&contents[..]); + + // 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(); + let mut decoded_src_stream = std::io::Cursor::new(decoded_src); + file.seek(SeekFrom::Start(0)).unwrap(); let nbt = Tag::read_gzip(&mut file).unwrap(); let mut group = c.benchmark_group(filename); group.throughput(Throughput::Bytes(contents.len() as u64)); - group.bench_function("Deserialize As Blob", |b| { + group.bench_function("Decode", |b| { b.iter(|| { - src.seek(SeekFrom::Start(0)).unwrap(); - Tag::read_gzip(&mut src).unwrap(); + decoded_src_stream.seek(SeekFrom::Start(0)).unwrap(); + Tag::read(&mut decoded_src_stream).unwrap(); }) }); - group.bench_function("Serialize As Blob", |b| { + group.bench_function("Encode", |b| { b.iter(|| { nbt.write(&mut io::sink()).unwrap(); }) @@ -31,9 +39,9 @@ fn bench_serialize(filename: &str, c: &mut Criterion) { fn bench(c: &mut Criterion) { bench_serialize("tests/bigtest.nbt", c); - // bench_serialize::("tests/simple_player.dat", c); - // bench_serialize::("tests/complex_player.dat", c); - // bench_serialize::("tests/level.dat", c); + // bench_serialize("tests/simple_player.dat", c); + // bench_serialize("tests/complex_player.dat", c); + bench_serialize("tests/level.dat", c); } criterion_group!(benches, bench); diff --git a/azalea-nbt/src/decode.rs b/azalea-nbt/src/decode.rs index a0a4ba8c..f7cda3f9 100644 --- a/azalea-nbt/src/decode.rs +++ b/azalea-nbt/src/decode.rs @@ -28,7 +28,7 @@ impl Tag { // integer (thus 4 bytes) 7 => { let length = stream.read_i32::().map_err(|_| Error::InvalidTag)?; - let mut bytes = Vec::new(); + let mut bytes = Vec::with_capacity(length as usize); for _ in 0..length { bytes.push(stream.read_i8().map_err(|_| Error::InvalidTag)?); } @@ -39,7 +39,7 @@ impl Tag { // string in bytes 8 => { let length = stream.read_u16::().map_err(|_| Error::InvalidTag)?; - let mut bytes = Vec::new(); + let mut bytes = Vec::with_capacity(length as usize); for _ in 0..length { bytes.push(stream.read_u8().map_err(|_| Error::InvalidTag)?); } @@ -56,7 +56,7 @@ impl Tag { 9 => { let type_id = stream.read_u8().map_err(|_| Error::InvalidTag)?; let length = stream.read_i32::().map_err(|_| Error::InvalidTag)?; - let mut list = Vec::new(); + let mut list = Vec::with_capacity(length as usize); for _ in 0..length { list.push(Tag::read_known(stream, type_id)?); } @@ -64,7 +64,8 @@ impl Tag { } // Effectively a list of a named tags. Order is not guaranteed. 10 => { - let mut map = HashMap::new(); + // we default to capacity 4 because it'll probably not be empty + let mut map = HashMap::with_capacity(4); loop { let tag_id = stream.read_u8().unwrap_or(0); if tag_id == 0 { @@ -84,7 +85,7 @@ impl Tag { // integers. 11 => { let length = stream.read_i32::().map_err(|_| Error::InvalidTag)?; - let mut ints = Vec::new(); + let mut ints = Vec::with_capacity(length as usize); for _ in 0..length { ints.push(stream.read_i32::().map_err(|_| Error::InvalidTag)?); } @@ -94,7 +95,7 @@ impl Tag { // integer (thus 4 bytes) and indicates the number of 8 byte longs. 12 => { let length = stream.read_i32::().map_err(|_| Error::InvalidTag)?; - let mut longs = Vec::new(); + let mut longs = Vec::with_capacity(length as usize); for _ in 0..length { longs.push(stream.read_i64::().map_err(|_| Error::InvalidTag)?); } diff --git a/azalea-nbt/tests/level.dat b/azalea-nbt/tests/level.dat new file mode 100644 index 00000000..e5d11b8c Binary files /dev/null and b/azalea-nbt/tests/level.dat differ diff --git a/azalea-nbt/tests/tests.rs b/azalea-nbt/tests/tests.rs index 2c69745b..b6bc1023 100644 --- a/azalea-nbt/tests/tests.rs +++ b/azalea-nbt/tests/tests.rs @@ -1,8 +1,4 @@ use azalea_nbt::Tag; -use flate2::{ - read::{GzDecoder, ZlibDecoder}, - write::{GzEncoder, ZlibEncoder}, -}; use std::{ collections::HashMap, io::{Cursor, Read},