mirror of
https://github.com/azalea-rs/simdnbt.git
synced 2025-08-02 15:36:03 +00:00
optimize writing
This commit is contained in:
parent
d2f3fdefc7
commit
40f38c34ef
13 changed files with 12659 additions and 129 deletions
|
@ -24,11 +24,11 @@ hematite-nbt = { version = "0.5.2", default-features = false }
|
|||
|
||||
[profile.release]
|
||||
lto = true
|
||||
debug = true
|
||||
debug = false
|
||||
|
||||
[profile.bench]
|
||||
lto = true
|
||||
debug = true
|
||||
debug = false
|
||||
|
||||
[[bench]]
|
||||
harness = false
|
||||
|
|
|
@ -91,13 +91,13 @@ pub fn bench_read_file(filename: &str, c: &mut Criterion) {
|
|||
// black_box(nbt);
|
||||
// })
|
||||
// });
|
||||
// let nbt = graphite_binary::nbt::decode::read(&mut &input[..]).unwrap();
|
||||
// group.bench_function("graphite_write", |b| {
|
||||
// b.iter(|| {
|
||||
// let out = graphite_binary::nbt::encode::write(&nbt);
|
||||
// black_box(out);
|
||||
// })
|
||||
// });
|
||||
let nbt = graphite_binary::nbt::decode::read(&mut &input[..]).unwrap();
|
||||
group.bench_function("graphite_write", |b| {
|
||||
b.iter(|| {
|
||||
let out = graphite_binary::nbt::encode::write(&nbt);
|
||||
black_box(out);
|
||||
})
|
||||
});
|
||||
|
||||
// group.bench_function("valence_parse", |b| {
|
||||
// b.iter(|| {
|
||||
|
@ -129,7 +129,7 @@ fn bench(c: &mut Criterion) {
|
|||
// bench_read_file("bigtest.nbt", c);
|
||||
// bench_read_file("simple_player.dat", c);
|
||||
bench_read_file("complex_player.dat", c);
|
||||
// bench_read_file("level.dat", c);
|
||||
bench_read_file("level.dat", c);
|
||||
// bench_read_file("stringtest.nbt", c);
|
||||
// bench_read_file("inttest1023.nbt", c);
|
||||
}
|
||||
|
|
12149
callgrind.out.1201671
Normal file
12149
callgrind.out.1201671
Normal file
File diff suppressed because it is too large
Load diff
261
callgrind.txt
Normal file
261
callgrind.txt
Normal file
|
@ -0,0 +1,261 @@
|
|||
--------------------------------------------------------------------------------
|
||||
Profile data file 'callgrind.out.1201671' (creator: callgrind-3.21.0)
|
||||
--------------------------------------------------------------------------------
|
||||
I1 cache:
|
||||
D1 cache:
|
||||
LL cache:
|
||||
Timerange: Basic block 0 - 226913
|
||||
Trigger: Program termination
|
||||
Profiled target: ./target/release/examples/read_and_write (PID 1201671, part 1)
|
||||
Events recorded: Ir
|
||||
Events shown: Ir
|
||||
Event sort order: Ir
|
||||
Thresholds: 99
|
||||
Include dirs:
|
||||
User annotated:
|
||||
Auto-annotation: on
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Ir
|
||||
--------------------------------------------------------------------------------
|
||||
752,320 (100.0%) PROGRAM TOTALS
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Ir file:function
|
||||
--------------------------------------------------------------------------------
|
||||
86,883 (11.55%) /usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:__memset_avx2_unaligned_erms [/usr/lib/libc.so.6]
|
||||
66,157 ( 8.79%) ???:miniz_oxide::inflate::core::decompress [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
59,020 ( 7.85%) /usr/src/debug/glibc/glibc/elf/dl-lookup.c:do_lookup_x [/usr/lib/ld-linux-x86-64.so.2]
|
||||
53,059 ( 7.05%) /usr/src/debug/glibc/glibc/malloc/malloc.c:_int_malloc [/usr/lib/libc.so.6]
|
||||
51,906 ( 6.90%) /usr/src/debug/glibc/glibc/stdio-common/vfscanf-internal.c:__vfscanf_internal [/usr/lib/libc.so.6]
|
||||
34,022 ( 4.52%) /usr/src/debug/glibc/glibc/elf/dl-tunables.c:__GI___tunables_init [/usr/lib/ld-linux-x86-64.so.2]
|
||||
25,637 ( 3.41%) /usr/src/debug/glibc/glibc/malloc/malloc.c:_int_free [/usr/lib/libc.so.6]
|
||||
24,238 ( 3.22%) /usr/src/debug/glibc/glibc/stdlib/../stdlib/strtol_l.c:____strtoul_l_internal [/usr/lib/libc.so.6]
|
||||
23,541 ( 3.13%) ???:miniz_oxide::inflate::core::init_tree [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
22,849 ( 3.04%) ???:simdnbt::owned::CompoundTag::new'2 [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
21,287 ( 2.83%) /usr/src/debug/glibc/glibc/elf/dl-reloc.c:_dl_relocate_object [/usr/lib/ld-linux-x86-64.so.2]
|
||||
19,545 ( 2.60%) /usr/src/debug/glibc/glibc/elf/dl-lookup.c:_dl_lookup_symbol_x [/usr/lib/ld-linux-x86-64.so.2]
|
||||
19,054 ( 2.53%) /usr/src/debug/glibc/glibc/elf/../sysdeps/generic/dl-new-hash.h:_dl_lookup_symbol_x
|
||||
18,154 ( 2.41%) /usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/../multiarch/strcmp-sse2.S:strcmp [/usr/lib/ld-linux-x86-64.so.2]
|
||||
14,879 ( 1.98%) /usr/src/debug/glibc/glibc/malloc/malloc.c:malloc [/usr/lib/libc.so.6]
|
||||
14,065 ( 1.87%) /usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:__memcpy_avx_unaligned_erms [/usr/lib/libc.so.6]
|
||||
13,713 ( 1.82%) /usr/src/debug/glibc/glibc/malloc/malloc.c:malloc_consolidate [/usr/lib/libc.so.6]
|
||||
12,356 ( 1.64%) /usr/src/debug/glibc/glibc/elf/../sysdeps/x86_64/dl-machine.h:_dl_relocate_object
|
||||
11,810 ( 1.57%) /usr/src/debug/glibc/glibc/elf/dl-lookup.c:check_match [/usr/lib/ld-linux-x86-64.so.2]
|
||||
11,469 ( 1.52%) /usr/src/debug/glibc/glibc/elf/do-rel.h:_dl_relocate_object
|
||||
9,796 ( 1.30%) ???:simdnbt::owned::CompoundTag::write'2 [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
8,371 ( 1.11%) ???:miniz_oxide::inflate::core::apply_match [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
8,184 ( 1.09%) /usr/src/debug/glibc/glibc/malloc/malloc.c:free [/usr/lib/libc.so.6]
|
||||
6,634 ( 0.88%) /usr/src/debug/glibc/glibc/malloc/malloc.c:unlink_chunk.isra.0 [/usr/lib/libc.so.6]
|
||||
6,224 ( 0.83%) /usr/src/debug/glibc/glibc/elf/dl-version.c:_dl_check_map_versions [/usr/lib/ld-linux-x86-64.so.2]
|
||||
5,267 ( 0.70%) ???:core::ptr::drop_in_place<simdnbt::owned::Tag>'2 [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
4,620 ( 0.61%) /usr/src/debug/glibc/glibc/elf/dl-tunables.h:__GI___tunables_init
|
||||
3,956 ( 0.53%) ???:simdnbt::owned::CompoundTag::new [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
3,496 ( 0.46%) /usr/src/debug/glibc/glibc/libio/genops.c:_IO_sputbackc [/usr/lib/libc.so.6]
|
||||
3,391 ( 0.45%) /usr/src/debug/glibc/glibc/libio/iogetdelim.c:getdelim [/usr/lib/libc.so.6]
|
||||
3,119 ( 0.41%) /usr/src/debug/glibc/glibc/elf/../sysdeps/x86/dl-cacheinfo.h:intel_check_word.constprop.0 [/usr/lib/ld-linux-x86-64.so.2]
|
||||
2,689 ( 0.36%) /usr/src/debug/glibc/glibc/malloc/malloc.c:_int_free_merge_chunk [/usr/lib/libc.so.6]
|
||||
2,471 ( 0.33%) ???:core::ptr::drop_in_place<simdnbt::owned::list::ListTag> [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
2,413 ( 0.32%) /usr/src/debug/glibc/glibc/elf/../bits/stdlib-bsearch.h:intel_check_word.constprop.0
|
||||
2,354 ( 0.31%) /usr/src/debug/glibc/glibc/malloc/malloc.c:realloc [/usr/lib/libc.so.6]
|
||||
2,282 ( 0.30%) /usr/src/debug/glibc/glibc/elf/dl-load.c:_dl_map_object_from_fd [/usr/lib/ld-linux-x86-64.so.2]
|
||||
2,157 ( 0.29%) /usr/src/debug/glibc/glibc/malloc/malloc.c:_int_realloc [/usr/lib/libc.so.6]
|
||||
1,987 ( 0.26%) ???:<flate2::gz::read::GzDecoder<R> as std::io::Read>::read [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
1,944 ( 0.26%) /usr/src/debug/glibc/glibc/malloc/malloc.c:_int_free_create_chunk [/usr/lib/libc.so.6]
|
||||
1,840 ( 0.24%) /usr/src/debug/glibc/glibc/elf/dl-cache.c:_dl_cache_libcmp [/usr/lib/ld-linux-x86-64.so.2]
|
||||
1,794 ( 0.24%) /usr/src/debug/glibc/glibc/libio/strops.c:_IO_str_init_static_internal [/usr/lib/libc.so.6]
|
||||
1,783 ( 0.24%) /usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/memchr-avx2.S:__memchr_avx2 [/usr/lib/libc.so.6]
|
||||
1,647 ( 0.22%) ???:crc32fast::specialized::pclmulqdq::calculate [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
1,610 ( 0.21%) /usr/src/debug/glibc/glibc/stdio-common/isoc23_sscanf.c:__isoc23_sscanf [/usr/lib/libc.so.6]
|
||||
1,577 ( 0.21%) ???:simdnbt::owned::list::ListTag::new [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
1,540 ( 0.20%) ???:simdnbt::owned::CompoundTag::write [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
1,500 ( 0.20%) /usr/src/debug/glibc/glibc/malloc/malloc.c:alloc_perturb [/usr/lib/libc.so.6]
|
||||
1,368 ( 0.18%) /usr/src/debug/glibc/glibc/elf/dl-deps.c:_dl_map_object_deps [/usr/lib/ld-linux-x86-64.so.2]
|
||||
1,349 ( 0.18%) /usr/src/debug/glibc/glibc/libio/genops.c:_IO_setb [/usr/lib/libc.so.6]
|
||||
1,312 ( 0.17%) /usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/strlen-avx2.S:__strlen_avx2 [/usr/lib/libc.so.6]
|
||||
1,246 ( 0.17%) /usr/src/debug/glibc/glibc/nptl/pthread_getattr_np.c:pthread_getattr_np@@GLIBC_2.32 [/usr/lib/libc.so.6]
|
||||
1,173 ( 0.16%) ???:alloc::raw_vec::finish_grow [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
1,143 ( 0.15%) ???:core::ptr::drop_in_place<simdnbt::owned::Tag> [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
1,140 ( 0.15%) /usr/src/debug/glibc/glibc/elf/rtld.c:dl_main [/usr/lib/ld-linux-x86-64.so.2]
|
||||
1,116 ( 0.15%) /usr/src/debug/glibc/glibc/malloc/arena.c:free
|
||||
1,088 ( 0.14%) /usr/src/debug/glibc/glibc/libio/genops.c:_IO_no_init [/usr/lib/libc.so.6]
|
||||
1,083 ( 0.14%) /usr/src/debug/glibc/glibc/libio/genops.c:_IO_old_init [/usr/lib/libc.so.6]
|
||||
1,050 ( 0.14%) ???:simdnbt::owned::list::ListTag::new'2 [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
1,015 ( 0.13%) ???:core::ptr::drop_in_place<simdnbt::owned::list::ListTag>'2 [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
1,012 ( 0.13%) /usr/src/debug/glibc/glibc/stdio-common/../include/scratch_buffer.h:__vfscanf_internal
|
||||
1,005 ( 0.13%) /usr/src/debug/glibc/glibc/elf/../sysdeps/generic/ldsodefs.h:do_lookup_x
|
||||
934 ( 0.12%) /usr/src/debug/glibc/glibc/elf/get-dynamic-info.h:_dl_map_object_from_fd
|
||||
899 ( 0.12%) /usr/src/debug/glibc/glibc/elf/dl-load.c:_dl_map_object [/usr/lib/ld-linux-x86-64.so.2]
|
||||
862 ( 0.11%) /usr/src/debug/glibc/glibc/elf/dl-misc.c:_dl_name_match_p [/usr/lib/ld-linux-x86-64.so.2]
|
||||
804 ( 0.11%) /usr/src/debug/glibc/glibc/elf/../sysdeps/generic/dl-protected.h:do_lookup_x
|
||||
781 ( 0.10%) /usr/src/debug/glibc/glibc/elf/dl-object.c:_dl_new_object [/usr/lib/ld-linux-x86-64.so.2]
|
||||
771 ( 0.10%) /usr/src/debug/glibc/glibc/malloc/malloc.c:ptmalloc_init.part.0
|
||||
745 ( 0.10%) ???:crc32fast::baseline::update_fast_16 [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
741 ( 0.10%) /usr/src/debug/glibc/glibc/elf/dl-tunables.c:__tunable_get_val [/usr/lib/ld-linux-x86-64.so.2]
|
||||
707 ( 0.09%) /usr/src/debug/glibc/glibc/malloc/arena.c:malloc
|
||||
694 ( 0.09%) /usr/src/debug/glibc/glibc/elf/dl-minimal-malloc.c:__minimal_malloc [/usr/lib/ld-linux-x86-64.so.2]
|
||||
690 ( 0.09%) /usr/src/debug/glibc/glibc/stdio-common/../libio/strfile.h:__isoc23_sscanf
|
||||
683 ( 0.09%) ???:read_and_write::main [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
670 ( 0.09%) /usr/src/debug/glibc/glibc/elf/../sysdeps/generic/ldsodefs.h:_dl_relocate_object
|
||||
650 ( 0.09%) /usr/src/debug/glibc/glibc/nptl/libc-cleanup.c:__libc_cleanup_push_defer [/usr/lib/libc.so.6]
|
||||
645 ( 0.09%) ???:simdnbt::owned::list::ListTag::write [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
608 ( 0.08%) ???:alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
597 ( 0.08%) /usr/src/debug/glibc/glibc/elf/dl-cache.c:search_cache [/usr/lib/ld-linux-x86-64.so.2]
|
||||
561 ( 0.07%) /usr/src/debug/glibc/glibc/elf/../sysdeps/x86/dl-cacheinfo.h:handle_intel.constprop.0 [/usr/lib/ld-linux-x86-64.so.2]
|
||||
480 ( 0.06%) ???:core::ptr::drop_in_place<simdnbt::owned::Nbt> [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
460 ( 0.06%) /usr/src/debug/glibc/glibc/stdlib/../stdlib/strtol.c:__strtoul_internal [/usr/lib/libc.so.6]
|
||||
456 ( 0.06%) /usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/../multiarch/strchr-sse2.S:index [/usr/lib/ld-linux-x86-64.so.2]
|
||||
451 ( 0.06%) /usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/../multiarch/strlen-sse2.S:strlen [/usr/lib/ld-linux-x86-64.so.2]
|
||||
450 ( 0.06%) /usr/src/debug/glibc/glibc/nptl/libc-cleanup.c:__libc_cleanup_pop_restore [/usr/lib/libc.so.6]
|
||||
445 ( 0.06%) /usr/src/debug/glibc/glibc/elf/dl-environ.c:_dl_next_ld_env_entry [/usr/lib/ld-linux-x86-64.so.2]
|
||||
439 ( 0.06%) /usr/src/debug/glibc/glibc/elf/./dl-map-segments.h:_dl_map_object_from_fd
|
||||
410 ( 0.05%) /usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/../multiarch/memset-vec-unaligned-erms.S:memset [/usr/lib/ld-linux-x86-64.so.2]
|
||||
410 ( 0.05%) ???:simdnbt::owned::list::ListTag::write'2 [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
408 ( 0.05%) /usr/src/debug/glibc/glibc/elf/dl-hwcaps_split.c:_dl_hwcaps_split [/usr/lib/ld-linux-x86-64.so.2]
|
||||
373 ( 0.05%) /usr/src/debug/glibc/glibc/elf/dl-sort-maps.c:dfs_traversal.part.0 [/usr/lib/ld-linux-x86-64.so.2]
|
||||
362 ( 0.05%) /usr/src/debug/glibc/glibc/elf/../sysdeps/x86/dl-prop.h:_dl_map_object_from_fd
|
||||
360 ( 0.05%) /rustc/69e97df5ce571a777acd654ec3697ae8d25962ea/library/alloc/src/raw_vec.rs:alloc::raw_vec::RawVec<T,A>::reserve_for_push [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
359 ( 0.05%) /usr/src/debug/glibc/glibc/elf/./get-dynamic-info.h:dl_main
|
||||
347 ( 0.05%) /usr/src/debug/glibc/glibc/misc/../sysdeps/unix/sysv/linux/mmap64.c:mmap [/usr/lib/libc.so.6]
|
||||
346 ( 0.05%) /usr/src/debug/gcc/gcc/libgcc/../gcc/common/config/i386/cpuinfo.h:__cpu_indicator_init@GCC_4.8.0
|
||||
332 ( 0.04%) /usr/src/debug/glibc/glibc/elf/../elf/dl-tls.c:_dl_allocate_tls_storage [/usr/lib/ld-linux-x86-64.so.2]
|
||||
320 ( 0.04%) /usr/src/debug/glibc/glibc/elf/./dl-find_object.h:_dl_find_object_from_map [/usr/lib/ld-linux-x86-64.so.2]
|
||||
312 ( 0.04%) /usr/src/debug/glibc/glibc/elf/dl-sort-maps.c:_dl_sort_maps [/usr/lib/ld-linux-x86-64.so.2]
|
||||
294 ( 0.04%) /usr/src/debug/glibc/glibc/elf/../sysdeps/unix/sysv/linux/dl-sysdep.c:_dl_sysdep_parse_arguments [/usr/lib/ld-linux-x86-64.so.2]
|
||||
273 ( 0.04%) /usr/src/debug/glibc/glibc/elf/dl-init.c:call_init [/usr/lib/ld-linux-x86-64.so.2]
|
||||
264 ( 0.04%) /usr/src/debug/glibc/glibc/elf/dl-load.c:open_verify.constprop.0 [/usr/lib/ld-linux-x86-64.so.2]
|
||||
260 ( 0.03%) /usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:memcpy [/usr/lib/ld-linux-x86-64.so.2]
|
||||
255 ( 0.03%) /usr/src/debug/glibc/glibc/elf/./get-dynamic-info.h:_dl_start
|
||||
248 ( 0.03%) /usr/src/debug/glibc/glibc/elf/dl-fini.c:_dl_fini [/usr/lib/ld-linux-x86-64.so.2]
|
||||
238 ( 0.03%) /usr/src/debug/glibc/glibc/string/../string/strcspn.c:strcspn [/usr/lib/ld-linux-x86-64.so.2]
|
||||
235 ( 0.03%) ???:main [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
224 ( 0.03%) /usr/src/debug/glibc/glibc/malloc/arena.c:realloc
|
||||
221 ( 0.03%) ???:miniz_oxide::inflate::core::transfer [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
219 ( 0.03%) /usr/src/debug/glibc/glibc/elf/../sysdeps/x86/dl-cacheinfo.h:get_common_cache_info.constprop.0 [/usr/lib/ld-linux-x86-64.so.2]
|
||||
219 ( 0.03%) /usr/src/debug/glibc/glibc/elf/../sysdeps/x86/dl-cacheinfo.h:init_cpu_features.constprop.0
|
||||
216 ( 0.03%) ???:alloc::raw_vec::RawVec<T,A>::allocate_in [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
212 ( 0.03%) /usr/src/debug/glibc/glibc/elf/dl-hwcaps_split.c:_dl_hwcaps_split_masked [/usr/lib/ld-linux-x86-64.so.2]
|
||||
205 ( 0.03%) /usr/src/debug/glibc/glibc/elf/dl-catch.c:_dl_catch_exception [/usr/lib/ld-linux-x86-64.so.2]
|
||||
204 ( 0.03%) /usr/src/debug/glibc/glibc/elf/dl-find_object.c:_dlfo_process_initial [/usr/lib/ld-linux-x86-64.so.2]
|
||||
203 ( 0.03%) /usr/src/debug/glibc/glibc/elf/../sysdeps/unix/sysv/linux/dl-parse_auxv.h:_dl_sysdep_parse_arguments
|
||||
198 ( 0.03%) /usr/src/debug/glibc/glibc/malloc/malloc.c:calloc [/usr/lib/libc.so.6]
|
||||
191 ( 0.03%) /usr/src/debug/glibc/glibc/libio/fileops.c:_IO_file_underflow@@GLIBC_2.2.5 [/usr/lib/libc.so.6]
|
||||
190 ( 0.03%) /usr/src/debug/glibc/glibc/elf/dl-hwcaps.c:_dl_important_hwcaps [/usr/lib/ld-linux-x86-64.so.2]
|
||||
184 ( 0.02%) /usr/src/debug/glibc/glibc/libio/libioP.h:getdelim
|
||||
184 ( 0.02%) /usr/src/debug/glibc/glibc/stdio-common/getline.c:getline [/usr/lib/libc.so.6]
|
||||
182 ( 0.02%) /usr/src/debug/glibc/glibc/elf/../sysdeps/x86/dl-prop.h:dl_main
|
||||
182 ( 0.02%) /usr/src/debug/glibc/glibc/elf/rtld.c:_dl_start [/usr/lib/ld-linux-x86-64.so.2]
|
||||
180 ( 0.02%) ???:simdnbt::swap_endianness::swap_endianness_64bit [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
176 ( 0.02%) /usr/src/debug/glibc/glibc/signal/../sysdeps/unix/sysv/linux/libc_sigaction.c:__libc_sigaction [/usr/lib/libc.so.6]
|
||||
175 ( 0.02%) /usr/src/debug/glibc/glibc/elf/dl-lookup-direct.c:_dl_lookup_direct [/usr/lib/ld-linux-x86-64.so.2]
|
||||
173 ( 0.02%) /usr/src/debug/glibc/glibc/elf/../sysdeps/x86/cpu-features.c:init_cpu_features.constprop.0 [/usr/lib/ld-linux-x86-64.so.2]
|
||||
171 ( 0.02%) /usr/src/debug/glibc/glibc/stdlib/cxa_finalize.c:__cxa_finalize [/usr/lib/libc.so.6]
|
||||
163 ( 0.02%) /usr/src/debug/glibc/glibc/elf/dl-object.c:_dl_add_to_namespace_list [/usr/lib/ld-linux-x86-64.so.2]
|
||||
159 ( 0.02%) /rustc/69e97df5ce571a777acd654ec3697ae8d25962ea/library/stdarch/crates/std_detect/src/detect/os/x86.rs:std_detect::detect::cache::detect_and_initialize
|
||||
158 ( 0.02%) /usr/src/debug/glibc/glibc/libio/genops.c:_IO_flush_all [/usr/lib/libc.so.6]
|
||||
157 ( 0.02%) /usr/src/debug/glibc/glibc/elf/../sysdeps/x86/cpu-features.c:update_active.constprop.0 [/usr/lib/ld-linux-x86-64.so.2]
|
||||
153 ( 0.02%) /usr/src/debug/glibc/glibc/elf/dl-lookup-direct.c:check_match [/usr/lib/ld-linux-x86-64.so.2]
|
||||
151 ( 0.02%) /usr/src/debug/glibc/glibc/malloc/malloc.c:sysmalloc [/usr/lib/libc.so.6]
|
||||
150 ( 0.02%) /usr/src/debug/glibc/glibc/elf/../elf/dl-tls.c:_dl_allocate_tls_init [/usr/lib/ld-linux-x86-64.so.2]
|
||||
150 ( 0.02%) /usr/src/debug/glibc/glibc/libio/genops.c:_IO_cleanup [/usr/lib/libc.so.6]
|
||||
147 ( 0.02%) /usr/src/debug/glibc/glibc/libio/../string/bits/string_fortified.h:getdelim
|
||||
145 ( 0.02%) /usr/src/debug/glibc/glibc/elf/dl-tunables.c:do_tunable_update_val [/usr/lib/ld-linux-x86-64.so.2]
|
||||
144 ( 0.02%) /usr/src/debug/glibc/glibc/elf/dl-minimal.c:lookup_malloc_symbol [/usr/lib/ld-linux-x86-64.so.2]
|
||||
143 ( 0.02%) /usr/src/debug/glibc/glibc/elf/dl-call_fini.c:_dl_call_fini [/usr/lib/ld-linux-x86-64.so.2]
|
||||
142 ( 0.02%) /usr/src/debug/glibc/glibc/setjmp/../sysdeps/x86_64/setjmp.S:__sigsetjmp [/usr/lib/libc.so.6]
|
||||
135 ( 0.02%) /rustc/69e97df5ce571a777acd654ec3697ae8d25962ea/library/core/src/cmp.rs:alloc::raw_vec::RawVec<T,A>::reserve_for_push
|
||||
135 ( 0.02%) /usr/src/debug/glibc/glibc/elf/dl-cache.c:_dl_load_cache_lookup [/usr/lib/ld-linux-x86-64.so.2]
|
||||
135 ( 0.02%) /usr/src/debug/glibc/glibc/elf/dl-setup_hash.c:_dl_setup_hash [/usr/lib/ld-linux-x86-64.so.2]
|
||||
132 ( 0.02%) /usr/src/debug/glibc/glibc/posix/../sysdeps/unix/sysv/linux/x86/sysconf.c:sysconf [/usr/lib/libc.so.6]
|
||||
130 ( 0.02%) ???:flate2::gz::GzHeaderParser::parse [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
128 ( 0.02%) /usr/src/debug/glibc/glibc/elf/dl-find_object.c:_dlfo_sort_mappings [/usr/lib/ld-linux-x86-64.so.2]
|
||||
123 ( 0.02%) ???:<flate2::bufreader::BufReader<R> as std::io::Read>::read [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
115 ( 0.02%) /usr/src/debug/glibc/glibc/libio/genops.c:__underflow [/usr/lib/libc.so.6]
|
||||
112 ( 0.01%) /usr/src/debug/glibc/glibc/elf/../elf/dl-tls.c:_dl_determine_tlsoffset [/usr/lib/ld-linux-x86-64.so.2]
|
||||
108 ( 0.01%) ???:simdnbt::swap_endianness::swap_endianness [/home/mat/code/simdnbt/target/release/examples/read_and_write]
|
||||
107 ( 0.01%) /usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:mempcpy [/usr/lib/ld-linux-x86-64.so.2]
|
||||
102 ( 0.01%) /usr/src/debug/glibc/glibc/posix/../sysdeps/posix/sysconf.c:sysconf
|
||||
100 ( 0.01%) /usr/src/debug/glibc/glibc/elf/dl-minimal-malloc.c:__minimal_calloc [/usr/lib/ld-linux-x86-64.so.2]
|
||||
100 ( 0.01%) /usr/src/debug/glibc/glibc/elf/dl-reloc.c:_dl_protect_relro [/usr/lib/ld-linux-x86-64.so.2]
|
||||
100 ( 0.01%) /usr/src/debug/glibc/glibc/libio/genops.c:_IO_switch_to_get_mode [/usr/lib/libc.so.6]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
The following files chosen for auto-annotation could not be found:
|
||||
--------------------------------------------------------------------------------
|
||||
/rustc/69e97df5ce571a777acd654ec3697ae8d25962ea/library/alloc/src/raw_vec.rs
|
||||
/rustc/69e97df5ce571a777acd654ec3697ae8d25962ea/library/core/src/cmp.rs
|
||||
/rustc/69e97df5ce571a777acd654ec3697ae8d25962ea/library/stdarch/crates/std_detect/src/detect/os/x86.rs
|
||||
/usr/src/debug/gcc/gcc/libgcc/../gcc/common/config/i386/cpuinfo.h
|
||||
/usr/src/debug/glibc/glibc/elf/../bits/stdlib-bsearch.h
|
||||
/usr/src/debug/glibc/glibc/elf/../elf/dl-tls.c
|
||||
/usr/src/debug/glibc/glibc/elf/../sysdeps/generic/dl-new-hash.h
|
||||
/usr/src/debug/glibc/glibc/elf/../sysdeps/generic/dl-protected.h
|
||||
/usr/src/debug/glibc/glibc/elf/../sysdeps/generic/ldsodefs.h
|
||||
/usr/src/debug/glibc/glibc/elf/../sysdeps/unix/sysv/linux/dl-parse_auxv.h
|
||||
/usr/src/debug/glibc/glibc/elf/../sysdeps/unix/sysv/linux/dl-sysdep.c
|
||||
/usr/src/debug/glibc/glibc/elf/../sysdeps/x86/cpu-features.c
|
||||
/usr/src/debug/glibc/glibc/elf/../sysdeps/x86/dl-cacheinfo.h
|
||||
/usr/src/debug/glibc/glibc/elf/../sysdeps/x86/dl-prop.h
|
||||
/usr/src/debug/glibc/glibc/elf/../sysdeps/x86_64/dl-machine.h
|
||||
/usr/src/debug/glibc/glibc/elf/./dl-find_object.h
|
||||
/usr/src/debug/glibc/glibc/elf/./dl-map-segments.h
|
||||
/usr/src/debug/glibc/glibc/elf/./get-dynamic-info.h
|
||||
/usr/src/debug/glibc/glibc/elf/dl-cache.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-call_fini.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-catch.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-deps.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-environ.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-find_object.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-fini.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-hwcaps.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-hwcaps_split.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-init.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-load.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-lookup-direct.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-lookup.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-minimal-malloc.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-minimal.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-misc.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-object.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-reloc.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-setup_hash.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-sort-maps.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-tunables.c
|
||||
/usr/src/debug/glibc/glibc/elf/dl-tunables.h
|
||||
/usr/src/debug/glibc/glibc/elf/dl-version.c
|
||||
/usr/src/debug/glibc/glibc/elf/do-rel.h
|
||||
/usr/src/debug/glibc/glibc/elf/get-dynamic-info.h
|
||||
/usr/src/debug/glibc/glibc/elf/rtld.c
|
||||
/usr/src/debug/glibc/glibc/libio/../string/bits/string_fortified.h
|
||||
/usr/src/debug/glibc/glibc/libio/fileops.c
|
||||
/usr/src/debug/glibc/glibc/libio/genops.c
|
||||
/usr/src/debug/glibc/glibc/libio/iogetdelim.c
|
||||
/usr/src/debug/glibc/glibc/libio/libioP.h
|
||||
/usr/src/debug/glibc/glibc/libio/strops.c
|
||||
/usr/src/debug/glibc/glibc/malloc/arena.c
|
||||
/usr/src/debug/glibc/glibc/malloc/malloc.c
|
||||
/usr/src/debug/glibc/glibc/misc/../sysdeps/unix/sysv/linux/mmap64.c
|
||||
/usr/src/debug/glibc/glibc/nptl/libc-cleanup.c
|
||||
/usr/src/debug/glibc/glibc/nptl/pthread_getattr_np.c
|
||||
/usr/src/debug/glibc/glibc/posix/../sysdeps/posix/sysconf.c
|
||||
/usr/src/debug/glibc/glibc/posix/../sysdeps/unix/sysv/linux/x86/sysconf.c
|
||||
/usr/src/debug/glibc/glibc/setjmp/../sysdeps/x86_64/setjmp.S
|
||||
/usr/src/debug/glibc/glibc/signal/../sysdeps/unix/sysv/linux/libc_sigaction.c
|
||||
/usr/src/debug/glibc/glibc/stdio-common/../include/scratch_buffer.h
|
||||
/usr/src/debug/glibc/glibc/stdio-common/../libio/strfile.h
|
||||
/usr/src/debug/glibc/glibc/stdio-common/getline.c
|
||||
/usr/src/debug/glibc/glibc/stdio-common/isoc23_sscanf.c
|
||||
/usr/src/debug/glibc/glibc/stdio-common/vfscanf-internal.c
|
||||
/usr/src/debug/glibc/glibc/stdlib/../stdlib/strtol.c
|
||||
/usr/src/debug/glibc/glibc/stdlib/../stdlib/strtol_l.c
|
||||
/usr/src/debug/glibc/glibc/stdlib/cxa_finalize.c
|
||||
/usr/src/debug/glibc/glibc/string/../string/strcspn.c
|
||||
/usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/../multiarch/memset-vec-unaligned-erms.S
|
||||
/usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/../multiarch/strchr-sse2.S
|
||||
/usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/../multiarch/strcmp-sse2.S
|
||||
/usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/../multiarch/strlen-sse2.S
|
||||
/usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/memchr-avx2.S
|
||||
/usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S
|
||||
/usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
|
||||
/usr/src/debug/glibc/glibc/string/../sysdeps/x86_64/multiarch/strlen-avx2.S
|
||||
|
|
@ -101,15 +101,10 @@ fn simdnbt_items_from_nbt(nbt: Nbt) -> Option<Vec<Option<Item>>> {
|
|||
|
||||
fn main() {
|
||||
let input = black_box(include_bytes!("../tests/realworld.nbt"));
|
||||
|
||||
for _ in 0..10000 {
|
||||
let nbt = Nbt::new(&mut Cursor::new(input));
|
||||
let nbt = black_box(nbt.unwrap().unwrap());
|
||||
black_box(simdnbt_items_from_nbt(nbt));
|
||||
}
|
||||
|
||||
let nbt = Nbt::new(&mut Cursor::new(input)).unwrap().unwrap();
|
||||
for _ in 0..100000 {
|
||||
let mut out = Vec::new();
|
||||
nbt.write(&mut out);
|
||||
}
|
||||
}
|
||||
|
|
20
examples/read_and_write.rs
Normal file
20
examples/read_and_write.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
use std::{hint::black_box, io::Cursor};
|
||||
|
||||
fn main() {
|
||||
let src = black_box(include_bytes!("../tests/complex_player.dat"));
|
||||
let mut decoded_src_decoder = flate2::read::GzDecoder::new(&src[..]);
|
||||
let mut input = Vec::new();
|
||||
if std::io::Read::read_to_end(&mut decoded_src_decoder, &mut input).is_err() {
|
||||
// oh probably wasn't gzipped then
|
||||
input = src.to_vec();
|
||||
}
|
||||
let input = input.as_slice();
|
||||
|
||||
let nbt = simdnbt::owned::Nbt::new(&mut Cursor::new(input))
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
let mut out = Vec::new();
|
||||
nbt.write(&mut out);
|
||||
black_box(out);
|
||||
}
|
|
@ -5,9 +5,9 @@ use byteorder::ReadBytesExt;
|
|||
use crate::{
|
||||
common::{
|
||||
read_i8_array, read_int_array, read_long_array, read_string, read_u8_array,
|
||||
read_with_u32_length, write_i8_array, write_string, write_u32, BYTE_ARRAY_ID, BYTE_ID,
|
||||
COMPOUND_ID, DOUBLE_ID, END_ID, FLOAT_ID, INT_ARRAY_ID, INT_ID, LIST_ID, LONG_ARRAY_ID,
|
||||
LONG_ID, SHORT_ID, STRING_ID,
|
||||
read_with_u32_length, slice_i8_into_u8, unchecked_extend, unchecked_push, write_string,
|
||||
write_u32, write_with_u32_length, BYTE_ARRAY_ID, BYTE_ID, COMPOUND_ID, DOUBLE_ID, END_ID,
|
||||
FLOAT_ID, INT_ARRAY_ID, INT_ID, LIST_ID, LONG_ARRAY_ID, LONG_ID, SHORT_ID, STRING_ID,
|
||||
},
|
||||
raw_list::RawList,
|
||||
Mutf8Str, ReadError,
|
||||
|
@ -27,7 +27,7 @@ pub enum ListTag<'a> {
|
|||
Long(RawList<'a, i64>) = LONG_ID,
|
||||
Float(RawList<'a, f32>) = FLOAT_ID,
|
||||
Double(RawList<'a, f64>) = DOUBLE_ID,
|
||||
ByteArray(&'a [u8]) = BYTE_ARRAY_ID,
|
||||
ByteArray(Vec<&'a [u8]>) = BYTE_ARRAY_ID,
|
||||
String(Vec<&'a Mutf8Str>) = STRING_ID,
|
||||
List(Vec<ListTag<'a>>) = LIST_ID,
|
||||
Compound(Vec<CompoundTag<'a>>) = COMPOUND_ID,
|
||||
|
@ -51,7 +51,15 @@ impl<'a> ListTag<'a> {
|
|||
LONG_ID => ListTag::Long(RawList::new(read_with_u32_length(data, 8)?)),
|
||||
FLOAT_ID => ListTag::Float(RawList::new(read_with_u32_length(data, 4)?)),
|
||||
DOUBLE_ID => ListTag::Double(RawList::new(read_with_u32_length(data, 8)?)),
|
||||
BYTE_ARRAY_ID => ListTag::ByteArray(read_u8_array(data)?),
|
||||
BYTE_ARRAY_ID => ListTag::ByteArray({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut arrays = Vec::with_capacity(length.min(128) as usize);
|
||||
for _ in 0..length {
|
||||
arrays.push(read_u8_array(data)?)
|
||||
}
|
||||
arrays
|
||||
}),
|
||||
STRING_ID => ListTag::String({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
|
@ -102,42 +110,52 @@ impl<'a> ListTag<'a> {
|
|||
}
|
||||
|
||||
pub fn write(&self, data: &mut Vec<u8>) {
|
||||
// fast path for compound since it's very common to have lists of compounds
|
||||
if let ListTag::Compound(compounds) = self {
|
||||
data.reserve(5);
|
||||
// SAFETY: we just reserved 5 bytes
|
||||
unsafe {
|
||||
unchecked_push(data, COMPOUND_ID);
|
||||
unchecked_extend(data, &(compounds.len() as u32).to_be_bytes());
|
||||
}
|
||||
for compound in compounds {
|
||||
compound.write(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
data.push(self.id());
|
||||
match self {
|
||||
ListTag::Empty => {
|
||||
write_u32(data, 0);
|
||||
data.extend(&0u32.to_be_bytes());
|
||||
}
|
||||
ListTag::Byte(bytes) => {
|
||||
write_u32(data, bytes.len() as u32);
|
||||
write_i8_array(data, bytes);
|
||||
write_with_u32_length(data, 1, slice_i8_into_u8(bytes));
|
||||
}
|
||||
ListTag::Short(shorts) => {
|
||||
write_u32(data, shorts.len() as u32);
|
||||
data.extend_from_slice(&shorts.as_big_endian());
|
||||
write_with_u32_length(data, 2, shorts.as_big_endian());
|
||||
}
|
||||
ListTag::Int(ints) => {
|
||||
write_u32(data, ints.len() as u32);
|
||||
data.extend_from_slice(&ints.as_big_endian());
|
||||
write_with_u32_length(data, 4, ints.as_big_endian());
|
||||
}
|
||||
ListTag::Long(longs) => {
|
||||
write_u32(data, longs.len() as u32);
|
||||
data.extend_from_slice(&longs.as_big_endian());
|
||||
write_with_u32_length(data, 8, longs.as_big_endian());
|
||||
}
|
||||
ListTag::Float(floats) => {
|
||||
write_u32(data, floats.len() as u32);
|
||||
data.extend_from_slice(&floats.as_big_endian());
|
||||
write_with_u32_length(data, 4, floats.as_big_endian());
|
||||
}
|
||||
ListTag::Double(doubles) => {
|
||||
write_u32(data, doubles.len() as u32);
|
||||
data.extend_from_slice(&doubles.as_big_endian());
|
||||
write_with_u32_length(data, 8, doubles.as_big_endian());
|
||||
}
|
||||
ListTag::ByteArray(byte_arrays) => {
|
||||
write_u32(data, byte_arrays.len() as u32);
|
||||
data.extend_from_slice(byte_arrays);
|
||||
for array in byte_arrays.iter() {
|
||||
write_with_u32_length(data, 1, array);
|
||||
}
|
||||
}
|
||||
ListTag::String(strings) => {
|
||||
write_u32(data, strings.len() as u32);
|
||||
for &string in strings {
|
||||
for string in strings {
|
||||
write_string(data, string);
|
||||
}
|
||||
}
|
||||
|
@ -147,24 +165,19 @@ impl<'a> ListTag<'a> {
|
|||
list.write(data);
|
||||
}
|
||||
}
|
||||
ListTag::Compound(compounds) => {
|
||||
write_u32(data, compounds.len() as u32);
|
||||
for compound in compounds {
|
||||
compound.write(data);
|
||||
}
|
||||
ListTag::Compound(_) => {
|
||||
unreachable!("fast path for compound should have been taken")
|
||||
}
|
||||
ListTag::IntArray(int_arrays) => {
|
||||
write_u32(data, int_arrays.len() as u32);
|
||||
for array in int_arrays {
|
||||
write_u32(data, array.len() as u32);
|
||||
data.extend_from_slice(&array.as_big_endian());
|
||||
write_with_u32_length(data, 4, array.as_big_endian());
|
||||
}
|
||||
}
|
||||
ListTag::LongArray(long_arrays) => {
|
||||
write_u32(data, long_arrays.len() as u32);
|
||||
for array in long_arrays {
|
||||
write_u32(data, array.len() as u32);
|
||||
data.extend_from_slice(&array.as_big_endian());
|
||||
write_with_u32_length(data, 8, array.as_big_endian());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +229,7 @@ impl<'a> ListTag<'a> {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn byte_arrays(&self) -> Option<&[u8]> {
|
||||
pub fn byte_arrays(&self) -> Option<&Vec<&[u8]>> {
|
||||
match self {
|
||||
ListTag::ByteArray(byte_arrays) => Some(byte_arrays),
|
||||
_ => None,
|
||||
|
|
|
@ -8,9 +8,10 @@ use byteorder::{ReadBytesExt, BE};
|
|||
|
||||
use crate::{
|
||||
common::{
|
||||
read_int_array, read_long_array, read_string, read_u32, read_with_u32_length, write_i32,
|
||||
write_string, BYTE_ARRAY_ID, BYTE_ID, COMPOUND_ID, DOUBLE_ID, END_ID, FLOAT_ID,
|
||||
INT_ARRAY_ID, INT_ID, LIST_ID, LONG_ARRAY_ID, LONG_ID, MAX_DEPTH, SHORT_ID, STRING_ID,
|
||||
read_int_array, read_long_array, read_string, read_u32, read_with_u32_length,
|
||||
unchecked_extend, unchecked_push, unchecked_write_string, write_string, BYTE_ARRAY_ID,
|
||||
BYTE_ID, COMPOUND_ID, DOUBLE_ID, END_ID, FLOAT_ID, INT_ARRAY_ID, INT_ID, LIST_ID,
|
||||
LONG_ARRAY_ID, LONG_ID, MAX_DEPTH, SHORT_ID, STRING_ID,
|
||||
},
|
||||
raw_list::RawList,
|
||||
Mutf8Str, ReadError,
|
||||
|
@ -140,29 +141,37 @@ impl<'a> CompoundTag<'a> {
|
|||
|
||||
pub fn write(&self, data: &mut Vec<u8>) {
|
||||
for (name, tag) in &self.values {
|
||||
data.push(tag.id());
|
||||
write_string(data, name);
|
||||
// reserve 4 bytes extra so we can avoid reallocating for small tags
|
||||
data.reserve(1 + 2 + name.len() + 4);
|
||||
// SAFETY: We just reserved enough space for the tag ID, the name length, the name, and
|
||||
// 4 bytes of tag data.
|
||||
unsafe {
|
||||
unchecked_push(data, tag.id());
|
||||
unchecked_write_string(data, name);
|
||||
}
|
||||
match tag {
|
||||
Tag::Byte(byte) => {
|
||||
data.push(*byte as u8);
|
||||
}
|
||||
Tag::Short(short) => {
|
||||
data.extend_from_slice(&short.to_be_bytes());
|
||||
}
|
||||
Tag::Int(int) => {
|
||||
write_i32(data, *int);
|
||||
}
|
||||
Tag::Byte(byte) => unsafe {
|
||||
unchecked_push(data, *byte as u8);
|
||||
},
|
||||
Tag::Short(short) => unsafe {
|
||||
unchecked_extend(data, &short.to_be_bytes());
|
||||
},
|
||||
Tag::Int(int) => unsafe {
|
||||
unchecked_extend(data, &int.to_be_bytes());
|
||||
},
|
||||
Tag::Long(long) => {
|
||||
data.extend_from_slice(&long.to_be_bytes());
|
||||
}
|
||||
Tag::Float(float) => {
|
||||
data.extend_from_slice(&float.to_be_bytes());
|
||||
}
|
||||
Tag::Float(float) => unsafe {
|
||||
unchecked_extend(data, &float.to_be_bytes());
|
||||
},
|
||||
Tag::Double(double) => {
|
||||
data.extend_from_slice(&double.to_be_bytes());
|
||||
}
|
||||
Tag::ByteArray(byte_array) => {
|
||||
write_i32(data, byte_array.len() as i32);
|
||||
unsafe {
|
||||
unchecked_extend(data, &byte_array.len().to_be_bytes());
|
||||
}
|
||||
data.extend_from_slice(byte_array);
|
||||
}
|
||||
Tag::String(string) => {
|
||||
|
@ -175,12 +184,16 @@ impl<'a> CompoundTag<'a> {
|
|||
compound.write(data);
|
||||
}
|
||||
Tag::IntArray(int_array) => {
|
||||
write_i32(data, int_array.len() as i32);
|
||||
data.extend_from_slice(&int_array.to_little_endian());
|
||||
unsafe {
|
||||
unchecked_extend(data, &int_array.len().to_be_bytes());
|
||||
}
|
||||
data.extend_from_slice(&int_array.as_big_endian());
|
||||
}
|
||||
Tag::LongArray(long_array) => {
|
||||
write_i32(data, long_array.len() as i32);
|
||||
data.extend_from_slice(&long_array.to_little_endian());
|
||||
unsafe {
|
||||
unchecked_extend(data, &long_array.len().to_be_bytes());
|
||||
}
|
||||
data.extend_from_slice(&long_array.as_big_endian());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,35 +108,75 @@ fn slice_u8_into_i8(s: &[u8]) -> &[i8] {
|
|||
unsafe { slice::from_raw_parts(s.as_ptr() as *const i8, s.len()) }
|
||||
}
|
||||
|
||||
fn slice_i8_into_u8(s: &[i8]) -> &[u8] {
|
||||
pub fn slice_i8_into_u8(s: &[i8]) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(s.as_ptr() as *const u8, s.len()) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn write_with_u32_length<'a>(data: &mut Vec<u8>, width: usize, value: &'a [u8]) {
|
||||
let length = value.len() / width;
|
||||
data.reserve(4 + value.len());
|
||||
unsafe {
|
||||
unchecked_extend(data, &(length as u32).to_be_bytes());
|
||||
unchecked_extend(data, value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_u32(data: &mut Vec<u8>, value: u32) {
|
||||
data.extend_from_slice(&value.to_be_bytes());
|
||||
}
|
||||
pub fn write_i32(data: &mut Vec<u8>, value: i32) {
|
||||
data.extend_from_slice(&value.to_be_bytes());
|
||||
}
|
||||
pub fn write_u16(data: &mut Vec<u8>, value: u16) {
|
||||
data.extend_from_slice(&value.to_be_bytes());
|
||||
}
|
||||
pub fn write_i8_array(data: &mut Vec<u8>, value: &[i8]) {
|
||||
data.extend_from_slice(slice_i8_into_u8(value));
|
||||
}
|
||||
pub fn write_string(data: &mut Vec<u8>, value: &Mutf8Str) {
|
||||
write_u16(data, value.len() as u16);
|
||||
data.extend_from_slice(value.as_bytes());
|
||||
data.reserve(2 + value.len());
|
||||
// SAFETY: We reserved enough capacity
|
||||
unsafe {
|
||||
unchecked_write_string(data, value);
|
||||
}
|
||||
}
|
||||
/// Write a string to a Vec<u8> without checking if the Vec has enough capacity.
|
||||
/// This is unsafe because it can cause a buffer overflow if the Vec doesn't have enough capacity.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// You must reserve enough capacity (2 + value.len()) in the Vec before calling this function.
|
||||
#[inline]
|
||||
pub unsafe fn unchecked_write_string(data: &mut Vec<u8>, value: &Mutf8Str) {
|
||||
unchecked_extend(data, &(value.len() as u16).to_be_bytes());
|
||||
unchecked_extend(data, value.as_bytes());
|
||||
}
|
||||
|
||||
/// Extend a Vec<u8> with a slice of u8 without checking if the Vec has enough capacity.
|
||||
///
|
||||
/// This optimization is barely measurable, but it does make it slightly faster!
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// You must reserve enough capacity in the Vec before calling this function.
|
||||
#[inline]
|
||||
pub unsafe fn unchecked_extend(data: &mut Vec<u8>, value: &[u8]) {
|
||||
let ptr = data.as_mut_ptr();
|
||||
let len = data.len();
|
||||
std::ptr::copy_nonoverlapping(value.as_ptr(), ptr.add(len), value.len());
|
||||
data.set_len(len + value.len());
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn unchecked_push(data: &mut Vec<u8>, value: u8) {
|
||||
let ptr = data.as_mut_ptr();
|
||||
let len = data.len();
|
||||
std::ptr::write(ptr.add(len), value);
|
||||
data.set_len(len + 1);
|
||||
}
|
||||
|
||||
/// Convert a slice of any type into a slice of u8. This will probably return the data as little
|
||||
/// endian! Use [`slice_into_u8_big_endian`] to get big endian (the endianness that's used in NBT).
|
||||
#[inline]
|
||||
pub fn slice_into_u8_native_endian<T>(s: &[T]) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(s.as_ptr() as *const u8, s.len() * std::mem::size_of::<T>()) }
|
||||
}
|
||||
|
||||
/// Convert a slice of any type into a Vec<u8>. This will return the data as big endian (the
|
||||
/// endianness that's used in NBT).
|
||||
#[inline]
|
||||
pub fn slice_into_u8_big_endian<T: SwappableNumber>(s: &[T]) -> Vec<u8> {
|
||||
swap_endianness_as_u8::<T>(slice_into_u8_native_endian(s))
|
||||
}
|
||||
|
|
10
src/mutf8.rs
10
src/mutf8.rs
|
@ -76,6 +76,7 @@ fn is_plain_ascii(slice: &[u8]) -> bool {
|
|||
}
|
||||
|
||||
impl Mutf8Str {
|
||||
#[inline]
|
||||
pub fn to_string_lossy(&self) -> Cow<str> {
|
||||
String::from_utf8_lossy(&self.slice)
|
||||
}
|
||||
|
@ -88,6 +89,7 @@ impl Mutf8Str {
|
|||
|
||||
// we can't implement FromStr on Cow<Mutf8Str>
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
#[inline]
|
||||
pub fn from_str(s: &str) -> Cow<Mutf8Str> {
|
||||
match mutf8::encode(s) {
|
||||
Cow::Borrowed(b) => Cow::Borrowed(Mutf8Str::from_slice(b)),
|
||||
|
@ -95,6 +97,7 @@ impl Mutf8Str {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_str(&self) -> Cow<str> {
|
||||
// fast check to skip if none of the bytes have the top bit set or are null
|
||||
if is_plain_ascii(&self.slice) {
|
||||
|
@ -108,10 +111,12 @@ impl Mutf8Str {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.slice.len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
&self.slice
|
||||
}
|
||||
|
@ -126,6 +131,7 @@ impl fmt::Display for Mutf8Str {
|
|||
impl ToOwned for Mutf8Str {
|
||||
type Owned = Mutf8String;
|
||||
|
||||
#[inline]
|
||||
fn to_owned(&self) -> Self::Owned {
|
||||
Mutf8String {
|
||||
vec: self.slice.to_vec(),
|
||||
|
@ -133,6 +139,7 @@ impl ToOwned for Mutf8Str {
|
|||
}
|
||||
}
|
||||
impl Borrow<Mutf8Str> for Mutf8String {
|
||||
#[inline]
|
||||
fn borrow(&self) -> &Mutf8Str {
|
||||
self.as_str()
|
||||
}
|
||||
|
@ -144,6 +151,7 @@ impl Mutf8String {
|
|||
Mutf8Str::from_slice(self.vec.as_slice())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_string(self) -> String {
|
||||
if is_plain_ascii(&self.vec) {
|
||||
// SAFETY: &[u8] and &str are the same layout.
|
||||
|
@ -156,6 +164,7 @@ impl Mutf8String {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.vec.len()
|
||||
}
|
||||
|
@ -163,6 +172,7 @@ impl Mutf8String {
|
|||
impl Deref for Mutf8String {
|
||||
type Target = Mutf8Str;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.as_str()
|
||||
}
|
||||
|
|
|
@ -5,9 +5,10 @@ use byteorder::ReadBytesExt;
|
|||
use crate::{
|
||||
common::{
|
||||
read_i8_array, read_int_array, read_long_array, read_string, read_u8_array,
|
||||
read_with_u32_length, slice_into_u8_big_endian, write_i8_array, write_string, write_u32,
|
||||
BYTE_ARRAY_ID, BYTE_ID, COMPOUND_ID, DOUBLE_ID, END_ID, FLOAT_ID, INT_ARRAY_ID, INT_ID,
|
||||
LIST_ID, LONG_ARRAY_ID, LONG_ID, SHORT_ID, STRING_ID,
|
||||
read_with_u32_length, slice_i8_into_u8, slice_into_u8_big_endian, unchecked_extend,
|
||||
unchecked_push, write_string, write_u32, write_with_u32_length, BYTE_ARRAY_ID, BYTE_ID,
|
||||
COMPOUND_ID, DOUBLE_ID, END_ID, FLOAT_ID, INT_ARRAY_ID, INT_ID, LIST_ID, LONG_ARRAY_ID,
|
||||
LONG_ID, SHORT_ID, STRING_ID,
|
||||
},
|
||||
mutf8::Mutf8String,
|
||||
swap_endianness::swap_endianness,
|
||||
|
@ -28,7 +29,7 @@ pub enum ListTag {
|
|||
Long(Vec<i64>) = LONG_ID,
|
||||
Float(Vec<f32>) = FLOAT_ID,
|
||||
Double(Vec<f64>) = DOUBLE_ID,
|
||||
ByteArray(Vec<u8>) = BYTE_ARRAY_ID,
|
||||
ByteArray(Vec<Vec<u8>>) = BYTE_ARRAY_ID,
|
||||
String(Vec<Mutf8String>) = STRING_ID,
|
||||
List(Vec<ListTag>) = LIST_ID,
|
||||
Compound(Vec<CompoundTag>) = COMPOUND_ID,
|
||||
|
@ -52,7 +53,15 @@ impl ListTag {
|
|||
LONG_ID => ListTag::Long(swap_endianness(read_with_u32_length(data, 8)?)),
|
||||
FLOAT_ID => ListTag::Float(swap_endianness(read_with_u32_length(data, 4)?)),
|
||||
DOUBLE_ID => ListTag::Double(swap_endianness(read_with_u32_length(data, 8)?)),
|
||||
BYTE_ARRAY_ID => ListTag::ByteArray(read_u8_array(data)?.to_owned()),
|
||||
BYTE_ARRAY_ID => ListTag::ByteArray({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut arrays = Vec::with_capacity(length.min(128) as usize);
|
||||
for _ in 0..length {
|
||||
arrays.push(read_u8_array(data)?.to_vec())
|
||||
}
|
||||
arrays
|
||||
}),
|
||||
STRING_ID => ListTag::String({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
|
@ -103,38 +112,48 @@ impl ListTag {
|
|||
}
|
||||
|
||||
pub fn write(&self, data: &mut Vec<u8>) {
|
||||
// fast path for compound since it's very common to have lists of compounds
|
||||
if let ListTag::Compound(compounds) = self {
|
||||
data.reserve(5);
|
||||
// SAFETY: we just reserved 5 bytes
|
||||
unsafe {
|
||||
unchecked_push(data, COMPOUND_ID);
|
||||
unchecked_extend(data, &(compounds.len() as u32).to_be_bytes());
|
||||
}
|
||||
for compound in compounds {
|
||||
compound.write(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
data.push(self.id());
|
||||
match self {
|
||||
ListTag::Empty => {
|
||||
write_u32(data, 0);
|
||||
data.extend(&0u32.to_be_bytes());
|
||||
}
|
||||
ListTag::Byte(bytes) => {
|
||||
write_u32(data, bytes.len() as u32);
|
||||
write_i8_array(data, bytes);
|
||||
write_with_u32_length(data, 1, slice_i8_into_u8(bytes));
|
||||
}
|
||||
ListTag::Short(shorts) => {
|
||||
write_u32(data, shorts.len() as u32);
|
||||
data.extend_from_slice(&slice_into_u8_big_endian(shorts));
|
||||
write_with_u32_length(data, 2, &slice_into_u8_big_endian(shorts));
|
||||
}
|
||||
ListTag::Int(ints) => {
|
||||
write_u32(data, ints.len() as u32);
|
||||
data.extend_from_slice(&slice_into_u8_big_endian(ints));
|
||||
write_with_u32_length(data, 4, &slice_into_u8_big_endian(ints));
|
||||
}
|
||||
ListTag::Long(longs) => {
|
||||
write_u32(data, longs.len() as u32);
|
||||
data.extend_from_slice(&slice_into_u8_big_endian(longs));
|
||||
write_with_u32_length(data, 8, &slice_into_u8_big_endian(longs));
|
||||
}
|
||||
ListTag::Float(floats) => {
|
||||
write_u32(data, floats.len() as u32);
|
||||
data.extend_from_slice(&slice_into_u8_big_endian(floats));
|
||||
write_with_u32_length(data, 4, &slice_into_u8_big_endian(floats));
|
||||
}
|
||||
ListTag::Double(doubles) => {
|
||||
write_u32(data, doubles.len() as u32);
|
||||
data.extend_from_slice(&slice_into_u8_big_endian(doubles));
|
||||
write_with_u32_length(data, 8, &slice_into_u8_big_endian(doubles));
|
||||
}
|
||||
ListTag::ByteArray(byte_arrays) => {
|
||||
write_u32(data, byte_arrays.len() as u32);
|
||||
data.extend_from_slice(byte_arrays);
|
||||
for array in byte_arrays {
|
||||
write_with_u32_length(data, 1, array);
|
||||
}
|
||||
}
|
||||
ListTag::String(strings) => {
|
||||
write_u32(data, strings.len() as u32);
|
||||
|
@ -148,24 +167,19 @@ impl ListTag {
|
|||
list.write(data);
|
||||
}
|
||||
}
|
||||
ListTag::Compound(compounds) => {
|
||||
write_u32(data, compounds.len() as u32);
|
||||
for compound in compounds {
|
||||
compound.write(data);
|
||||
}
|
||||
ListTag::Compound(_) => {
|
||||
unreachable!("fast path for compound should have been taken")
|
||||
}
|
||||
ListTag::IntArray(int_arrays) => {
|
||||
write_u32(data, int_arrays.len() as u32);
|
||||
for array in int_arrays {
|
||||
write_u32(data, array.len() as u32);
|
||||
data.extend_from_slice(&slice_into_u8_big_endian(array));
|
||||
write_with_u32_length(data, 4, &slice_into_u8_big_endian(array));
|
||||
}
|
||||
}
|
||||
ListTag::LongArray(long_arrays) => {
|
||||
write_u32(data, long_arrays.len() as u32);
|
||||
for array in long_arrays {
|
||||
write_u32(data, array.len() as u32);
|
||||
data.extend_from_slice(&slice_into_u8_big_endian(array));
|
||||
write_with_u32_length(data, 8, &slice_into_u8_big_endian(array));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +231,7 @@ impl ListTag {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn byte_arrays(&self) -> Option<&[u8]> {
|
||||
pub fn byte_arrays(&self) -> Option<&[Vec<u8>]> {
|
||||
match self {
|
||||
ListTag::ByteArray(byte_arrays) => Some(byte_arrays),
|
||||
_ => None,
|
||||
|
|
|
@ -9,9 +9,9 @@ use byteorder::{ReadBytesExt, BE};
|
|||
use crate::{
|
||||
common::{
|
||||
read_int_array, read_long_array, read_string, read_u32, read_with_u32_length,
|
||||
slice_into_u8_big_endian, write_i32, write_string, BYTE_ARRAY_ID, BYTE_ID, COMPOUND_ID,
|
||||
DOUBLE_ID, END_ID, FLOAT_ID, INT_ARRAY_ID, INT_ID, LIST_ID, LONG_ARRAY_ID, LONG_ID,
|
||||
MAX_DEPTH, SHORT_ID, STRING_ID,
|
||||
slice_into_u8_big_endian, unchecked_extend, unchecked_push, unchecked_write_string,
|
||||
write_string, BYTE_ARRAY_ID, BYTE_ID, COMPOUND_ID, DOUBLE_ID, END_ID, FLOAT_ID,
|
||||
INT_ARRAY_ID, INT_ID, LIST_ID, LONG_ARRAY_ID, LONG_ID, MAX_DEPTH, SHORT_ID, STRING_ID,
|
||||
},
|
||||
mutf8::Mutf8String,
|
||||
Mutf8Str, ReadError,
|
||||
|
@ -145,29 +145,37 @@ impl CompoundTag {
|
|||
|
||||
pub fn write(&self, data: &mut Vec<u8>) {
|
||||
for (name, tag) in &self.values {
|
||||
data.push(tag.id());
|
||||
write_string(data, name);
|
||||
// reserve 4 bytes extra so we can avoid reallocating for small tags
|
||||
data.reserve(1 + 2 + name.len() + 4);
|
||||
// SAFETY: We just reserved enough space for the tag ID, the name length, the name, and
|
||||
// 4 bytes of tag data.
|
||||
unsafe {
|
||||
unchecked_push(data, tag.id());
|
||||
unchecked_write_string(data, name);
|
||||
}
|
||||
match tag {
|
||||
Tag::Byte(byte) => {
|
||||
data.push(*byte as u8);
|
||||
}
|
||||
Tag::Short(short) => {
|
||||
data.extend_from_slice(&short.to_be_bytes());
|
||||
}
|
||||
Tag::Int(int) => {
|
||||
write_i32(data, *int);
|
||||
}
|
||||
Tag::Byte(byte) => unsafe {
|
||||
unchecked_push(data, *byte as u8);
|
||||
},
|
||||
Tag::Short(short) => unsafe {
|
||||
unchecked_extend(data, &short.to_be_bytes());
|
||||
},
|
||||
Tag::Int(int) => unsafe {
|
||||
unchecked_extend(data, &int.to_be_bytes());
|
||||
},
|
||||
Tag::Long(long) => {
|
||||
data.extend_from_slice(&long.to_be_bytes());
|
||||
}
|
||||
Tag::Float(float) => {
|
||||
data.extend_from_slice(&float.to_be_bytes());
|
||||
}
|
||||
Tag::Float(float) => unsafe {
|
||||
unchecked_extend(data, &float.to_be_bytes());
|
||||
},
|
||||
Tag::Double(double) => {
|
||||
data.extend_from_slice(&double.to_be_bytes());
|
||||
}
|
||||
Tag::ByteArray(byte_array) => {
|
||||
write_i32(data, byte_array.len() as i32);
|
||||
unsafe {
|
||||
unchecked_extend(data, &byte_array.len().to_be_bytes());
|
||||
}
|
||||
data.extend_from_slice(byte_array);
|
||||
}
|
||||
Tag::String(string) => {
|
||||
|
@ -180,11 +188,15 @@ impl CompoundTag {
|
|||
compound.write(data);
|
||||
}
|
||||
Tag::IntArray(int_array) => {
|
||||
write_i32(data, int_array.len() as i32);
|
||||
unsafe {
|
||||
unchecked_extend(data, &int_array.len().to_be_bytes());
|
||||
}
|
||||
data.extend_from_slice(&slice_into_u8_big_endian(int_array));
|
||||
}
|
||||
Tag::LongArray(long_array) => {
|
||||
write_i32(data, long_array.len() as i32);
|
||||
unsafe {
|
||||
unchecked_extend(data, &long_array.len().to_be_bytes());
|
||||
}
|
||||
data.extend_from_slice(&slice_into_u8_big_endian(long_array));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ impl SwappableNumber for i64 {}
|
|||
impl SwappableNumber for f32 {}
|
||||
impl SwappableNumber for f64 {}
|
||||
|
||||
#[inline]
|
||||
fn swap_endianness_16bit(bytes: &mut [u8], num: usize) {
|
||||
for i in 0..num / 32 {
|
||||
let simd: u8x64 = Simd::from_slice(bytes[i * 32 * 2..(i + 1) * 32 * 2].as_ref());
|
||||
|
@ -124,6 +125,7 @@ fn swap_endianness_16bit(bytes: &mut [u8], num: usize) {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn swap_endianness_32bit(bytes: &mut [u8], num: usize) {
|
||||
for i in 0..num / 16 {
|
||||
let simd: u8x64 = Simd::from_slice(bytes[i * 16 * 4..(i + 1) * 16 * 4].as_ref());
|
||||
|
@ -198,6 +200,7 @@ fn swap_endianness_32bit(bytes: &mut [u8], num: usize) {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn swap_endianness_64bit(bytes: &mut [u8], num: usize) {
|
||||
for i in 0..num / 8 {
|
||||
let simd: u8x64 = Simd::from_slice(bytes[i * 64..i * 64 + 64].as_ref());
|
||||
|
|
Loading…
Add table
Reference in a new issue