13个版本 (5个破坏性版本)

0.6.0 2024年7月5日
0.5.2 2024年5月14日
0.4.2 2024年3月15日
0.4.0 2024年1月25日
0.1.0 2023年8月30日

#23 in 游戏

Download history 27/week @ 2024-05-02 392/week @ 2024-05-09 168/week @ 2024-05-16 113/week @ 2024-05-23 116/week @ 2024-05-30 50/week @ 2024-06-06 100/week @ 2024-06-13 125/week @ 2024-06-20 68/week @ 2024-06-27 241/week @ 2024-07-04 134/week @ 2024-07-11 102/week @ 2024-07-18 134/week @ 2024-07-25 102/week @ 2024-08-01 120/week @ 2024-08-08 65/week @ 2024-08-15

每月下载量429
用于 17 个crate (直接使用11个)

MIT 许可证

180KB
5K SLoC

simdnbt

Simdnbt是一个非常快速的NBT序列化和反序列化器。

它最初是作为一个玩笑而制作的,但最终变成了一个太好的玩笑,所以现在它实际上是一件事。

用法

cargo add simdnbt

反序列化

对于反序列化,你可能想使用 simdnbt::borrow::readsimdnbt::owned::read。区别在于“借用”变体需要你保留对原始缓冲区的引用,但速度要快得多。

use std::borrow::Cow;
use std::io::Cursor;

fn example(item_bytes: &[u8]) {
    let nbt = simdnbt::borrow::read(&mut Cursor::new(item_bytes))
        .unwrap()
        .unwrap();
    let skyblock_id: Cow<str> = nbt
        .list("i")
        .and_then(|i| i.compounds())
        .and_then(|i| i.first())
        .and_then(|i| i.compound("tag"))
        .and_then(|tag| tag.compound("ExtraAttributes"))
        .and_then(|ea| ea.string("id"))
        .map(|id| id.to_string_lossy())
        .unwrap_or_default();
}

序列化

use simdnbt::owned::{BaseNbt, Nbt, NbtCompound, NbtTag};

let nbt = Nbt::Some(BaseNbt::new(
    "",
    NbtCompound::from_values(vec![
        ("key".into(), NbtTag::String("value".into())),
    ]),
));
let mut buffer = Vec::new();
nbt.write(&mut buffer);

性能指南

如果可能,请使用 Nbt 的借用变体,并避免不必要的分配(例如,如果可能,将字符串保留为 Cow<str>)。

你可以做的最重要的优化之一是切换到像 mimalloc 这样的分配器(在我的机器上大约快20%)。在运行你的代码时设置 RUSTFLAGS='-C target-cpu=native' 也可能有所帮助。

实现细节

Simdnbt目前使用SIMD指令做两件事

  • 交换int数组的字节序
  • 检查字符串是否是纯ASCII,以便更快地将mutf8转换为utf8

Simdnbt 作弊 为了变得如此之快而采取了一些捷径

  1. 它需要原始数据的引用(以避免克隆)
  2. 在解码时它不验证/解码mutf-8字符串

基准测试

Simdnbt可能是目前存在的最快的NBT解码器。

以下是对Simdnbt与其他几个最快的NBT解码crate进行的基准比较,解码complex_player.dat

吞吐量
simdnbt::borrow 3.9493 GiB/s
simdnbt::owned 825.59 MiB/s
shen_nbt5 606.68 MiB/s
graphite_binary 363.94 MiB/s
azalea_nbt 330.46 MiB/s
valence_nbt 279.58 MiB/s
hematite_nbt 180.22 MiB/s
fastnbt 162.92 MiB/s

对于写入complex_player.dat

吞吐量
simdnbt::owned 2.5033 GiB/s
azalea_nbt 2.4152 GiB/s
simdnbt::borrow 2.1317 GiB/s
graphite_binary 1.8804 GiB/s

上表来自本仓库中的比较基准。请注意,这个基准并不完全公平,因为simdnbt::borrow直到使用前不会完全解码一些东西,比如字符串和整数数组。另外,如果你运行自己的基准测试,你将得到不同的数字,但速度应该相对相同。

依赖项

~0.8–1.4MB
~29K SLoC