diff --git a/simdnbt/src/borrow/compound.rs b/simdnbt/src/borrow/compound.rs index 7e29234..11bbc69 100644 --- a/simdnbt/src/borrow/compound.rs +++ b/simdnbt/src/borrow/compound.rs @@ -1,4 +1,4 @@ -use std::io::Cursor; +use std::{io::Cursor, mem::MaybeUninit}; use byteorder::ReadBytesExt; @@ -33,6 +33,12 @@ impl<'a> NbtCompound<'a> { } let mut tags = alloc.get().named.start(depth); + + let mut tags_buffer = unsafe { + MaybeUninit::<[MaybeUninit<(&Mutf8Str, NbtTag<'a>)>; 4]>::uninit().assume_init() + }; + let mut tags_buffer_len: usize = 0; + loop { let tag_type = match data.read_u8() { Ok(tag_type) => tag_type, @@ -61,8 +67,23 @@ impl<'a> NbtCompound<'a> { return Err(e); } }; - tags.push((tag_name, tag)); + + tags_buffer[tags_buffer_len] = MaybeUninit::new((tag_name, tag)); + tags_buffer_len += 1; + + if tags_buffer_len == tags_buffer.len() { + // writing the tags in groups like this is slightly faster + for i in 0..tags_buffer_len { + tags.push(unsafe { tags_buffer.get_unchecked(i).assume_init_read() }); + } + tags_buffer_len = 0; + } } + + for i in 0..tags_buffer_len { + tags.push(unsafe { tags_buffer.get_unchecked(i).assume_init_read() }); + } + let values = alloc.get().named.finish(tags, depth); Ok(Self { values }) diff --git a/simdnbt/src/borrow/tag_alloc.rs b/simdnbt/src/borrow/tag_alloc.rs index ffde9e5..6356481 100644 --- a/simdnbt/src/borrow/tag_alloc.rs +++ b/simdnbt/src/borrow/tag_alloc.rs @@ -231,6 +231,21 @@ impl ContiguousTagsAllocator { self.alloc.len = self.size; } + #[inline] + pub fn extend_from_slice(&mut self, slice: &[T]) { + while self.alloc.len + slice.len() > self.alloc.cap { + self.grow(); + } + + // copy the slice + unsafe { + let end = self.alloc.ptr.as_ptr().add(self.alloc.len); + std::ptr::copy_nonoverlapping(slice.as_ptr(), end, slice.len()); + } + self.alloc.len += slice.len(); + self.size += slice.len(); + } + #[inline] pub fn push(&mut self, value: T) { // check if we need to reallocate