1
0
Fork 0
mirror of https://github.com/azalea-rs/simdnbt.git synced 2025-08-02 07:26:04 +00:00

add crab_nbt and ussr_nbt benches and move MainTape::grow into its own function

This commit is contained in:
mat 2025-03-15 04:08:06 +00:00
parent a13caf3cf8
commit a44d709489
8 changed files with 106 additions and 25 deletions

64
Cargo.lock generated
View file

@ -89,6 +89,12 @@ version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "bytemuck"
version = "1.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
[[package]]
name = "byteorder"
version = "1.5.0"
@ -97,9 +103,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.9.0"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
[[package]]
name = "cast"
@ -205,6 +211,18 @@ dependencies = [
"static_assertions",
]
[[package]]
name = "crab_nbt"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6bf9e479d74bed4463ad8f09f0fe471300423152a3a90f8b8e3a613af1de96"
dependencies = [
"bytes",
"cesu8",
"derive_more",
"thiserror 2.0.11",
]
[[package]]
name = "crc32fast"
version = "1.4.2"
@ -281,6 +299,26 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "derive_more"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
dependencies = [
"derive_more-impl",
]
[[package]]
name = "derive_more-impl"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.96",
]
[[package]]
name = "either"
version = "1.13.0"
@ -501,6 +539,12 @@ version = "11.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pin-project-lite"
version = "0.2.16"
@ -707,6 +751,7 @@ version = "0.7.1"
dependencies = [
"azalea-nbt",
"byteorder",
"crab_nbt",
"criterion",
"fastnbt",
"flate2",
@ -717,6 +762,7 @@ dependencies = [
"simd_cesu8",
"simdnbt-derive",
"thiserror 2.0.11",
"ussr-nbt",
"valence_nbt",
]
@ -858,6 +904,20 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "ussr-nbt"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cf987f94965acc38033918fe2b3a1919ac2c798352b8f0cc6b3a432b67de4f2"
dependencies = [
"bytemuck",
"byteorder",
"flate2",
"paste",
"simd_cesu8",
"thiserror 1.0.69",
]
[[package]]
name = "uuid"
version = "1.12.0"

View file

@ -26,6 +26,8 @@ hematite-nbt = { version = "0.5.2", default-features = false }
shen-nbt5 = "0.4.6"
mimalloc = "0.1.43"
crab_nbt = "0.2.9"
ussr-nbt = "0.2.1"
[features]
default = ["derive"]

View file

@ -54,7 +54,7 @@ nbt.write(&mut buffer);
Use the borrow variant of `Nbt` if possible, and avoid allocating unnecessarily (for example, keep strings as `Cow<str>` if you can).
If you're using the owned variant of Simdnbt, switching to a faster allocator like [mimalloc](https://docs.rs/mimalloc/latest/mimalloc/) may help a decent amount (it's ~20% faster on my machine). Setting `RUSTFLAGS='-C target-cpu=native'` when running your code may sometimes also help a little bit.
If you're using the owned variant of Simdnbt, switching to a faster allocator like [mimalloc](https://docs.rs/mimalloc/latest/mimalloc/) may help a decent amount (it's ~20% faster on my machine). Setting `RUSTFLAGS='-C target-cpu=native'` when running your code may also help or hurt performance.
## Implementation details

View file

@ -74,6 +74,18 @@ fn bench_read_file(filename: &str, c: &mut Criterion) {
input_stream.set_position(0);
})
});
group.bench_function("crab_parse", |b| {
b.iter(|| {
black_box(crab_nbt::Nbt::read(&mut input_stream).unwrap());
input_stream.set_position(0);
})
});
group.bench_function("ussr_borrow_parse", |b| {
b.iter(|| {
black_box(ussr_nbt::borrow::Nbt::read(&mut input_stream).unwrap());
input_stream.set_position(0);
})
});
let nbt = azalea_nbt::Nbt::read(&mut Cursor::new(&input)).unwrap();
group.bench_function("azalea_write", |b| {

View file

@ -13,6 +13,7 @@ impl Debug for ExtraTapes<'_> {
}
}
// (note that this is a union, not a struct)
pub union ExtraTapeElement<'a> {
/// An indicator for how long the following list is. This is what we point
/// to from `TapeTagValue`.

View file

@ -46,6 +46,7 @@ pub fn read<'a>(data: &mut Cursor<&'a [u8]>) -> Result<Nbt<'a>, Error> {
if root_type != COMPOUND_ID {
return Err(Error::InvalidRootType(root_type));
}
// our Reader type is faster than Cursor
let mut data = ReaderFromCursor::new(data);
let name = read_string(&mut data)?;

View file

@ -29,28 +29,7 @@ impl<A: Allocator> MainTape<A> {
#[inline(always)]
pub fn push(&mut self, element: TapeElement) {
if self.cur == self.end {
let old_cap = self.capacity();
let extending_by = old_cap;
let new_cap = old_cap + extending_by;
let element_size = mem::size_of::<TapeElement>();
let old_cap_bytes = old_cap * element_size;
let new_cap_bytes = new_cap * element_size;
let new_ptr = unsafe {
self.alloc.grow(
self.ptr,
Layout::from_size_align_unchecked(old_cap_bytes, element_size),
Layout::from_size_align_unchecked(new_cap_bytes, element_size),
)
};
let new_ptr = new_ptr.expect("allocation failed");
self.ptr = new_ptr.cast();
// update cur in case the ptr changed
self.cur = NonNull::new(self.ptr.as_ptr() as *mut TapeElement).unwrap();
self.cur = unsafe { self.cur.add(old_cap) };
// and end has to be updated anyways since we're updating the capacity
self.end = unsafe { self.cur.add(extending_by) };
self.grow()
}
unsafe { self.push_unchecked(element) };
@ -62,6 +41,31 @@ impl<A: Allocator> MainTape<A> {
self.cur = unsafe { self.cur.add(1) };
}
fn grow(&mut self) {
let old_cap = self.capacity();
let extending_by = old_cap;
let new_cap = old_cap + extending_by;
let element_size = mem::size_of::<TapeElement>();
let old_cap_bytes = old_cap * element_size;
let new_cap_bytes = new_cap * element_size;
let new_ptr = unsafe {
self.alloc.grow(
self.ptr,
Layout::from_size_align_unchecked(old_cap_bytes, element_size),
Layout::from_size_align_unchecked(new_cap_bytes, element_size),
)
};
let new_ptr = new_ptr.expect("allocation failed");
self.ptr = new_ptr.cast();
// update cur in case the ptr changed
self.cur = NonNull::new(self.ptr.as_ptr() as *mut TapeElement).unwrap();
self.cur = unsafe { self.cur.add(old_cap) };
// and end has to be updated anyways since we're updating the capacity
self.end = unsafe { self.cur.add(extending_by) };
}
#[inline]
pub fn len(&self) -> usize {
unsafe { self.cur.offset_from(self.ptr.cast()) as usize }

View file

@ -46,6 +46,7 @@ impl<'a> Reader<'a> {
value
}
#[inline]
pub fn read_type<T: Copy>(&mut self) -> Result<T, UnexpectedEofError> {
let addr = self.cur;