1
0
Fork 0
mirror of https://github.com/azalea-rs/simdnbt.git synced 2025-08-02 15:36:03 +00:00

simplify some code

This commit is contained in:
mat 2023-08-27 22:55:04 -05:00
parent 0dd09fd76e
commit 5daf7c60e7
5 changed files with 133 additions and 194 deletions

View file

@ -14,9 +14,10 @@ thiserror = "1.0.47"
[dev-dependencies]
criterion = { version = "^0.5.1", features = ["html_reports"] }
graphite_binary = "0.1.0"
valence_nbt = "0.6.1"
valence_nbt = { version = "0.6.1", features = ["binary"] }
fastnbt = "2.4.4"
azalea-nbt = { git = "https://github.com/mat-1/azalea" }
hematite-nbt = { version = "0.5.2", default-features = false }
[profile.release]
lto = true

View file

@ -7,7 +7,7 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughpu
use flate2::read::GzDecoder;
pub fn bench_read_file(filename: &str, c: &mut Criterion) {
let mut file = File::open(filename).unwrap();
let mut file = File::open(format!("tests/{filename}")).unwrap();
let mut contents = Vec::new();
file.read_to_end(&mut contents).unwrap();
let mut src = &contents[..];
@ -21,54 +21,70 @@ pub fn bench_read_file(filename: &str, c: &mut Criterion) {
}
let input = input.as_slice();
let mut group = c.benchmark_group(filename);
let mut group = c.benchmark_group(format!("compare/{filename}"));
group.throughput(Throughput::Bytes(input.len() as u64));
group.bench_function("azalea_parse", |b| {
b.iter(|| {
let input = black_box(input);
let nbt = black_box(azalea_nbt::Nbt::read(&mut Cursor::new(input)).unwrap());
black_box(
nbt.as_compound()
.unwrap()
.get("")
.unwrap()
.as_compound()
.unwrap()
.get("PersistentId")
.unwrap()
.as_int()
.unwrap(),
);
let nbt = azalea_nbt::Nbt::read(&mut Cursor::new(input)).unwrap();
black_box(nbt);
// black_box(
// nbt.as_compound()
// .unwrap()
// .get("")
// .unwrap()
// .as_compound()
// .unwrap()
// .get("PersistentId")
// .unwrap()
// .as_int()
// .unwrap(),
// );
})
});
group.bench_function("graphite_parse", |b| {
b.iter(|| {
let input = black_box(input);
let nbt = black_box(graphite_binary::nbt::decode::read(&mut &input[..]).unwrap());
// black_box(nbt);
black_box(nbt.find_root("PersistentId").unwrap().as_int());
let nbt = graphite_binary::nbt::decode::read(&mut &input[..]).unwrap();
black_box(nbt);
// black_box(nbt.find_root("PersistentId").unwrap().as_int());
})
});
group.bench_function("simdnbt_parse", |b| {
b.iter(|| {
let input = black_box(input);
let nbt = black_box(simdnbt::Nbt::new(&mut Cursor::new(input)));
let nbt = nbt.unwrap().unwrap();
// black_box(nbt);
black_box(nbt.int("PersistentId").unwrap());
let nbt = simdnbt::Nbt::new(&mut Cursor::new(input)).unwrap().unwrap();
black_box(nbt);
// black_box(nbt.int("PersistentId").unwrap());
})
});
// group.bench_function("valence_parse", |b| {
// b.iter(|| {
// let input = black_box(input);
// let nbt = valence_nbt::from_binary_slice(&mut &input[..]).unwrap();
// black_box(nbt);
// })
// });
group.bench_function("valence_parse", |b| {
b.iter(|| {
let input = black_box(input);
let nbt = valence_nbt::Compound::from_binary(&mut &input[..]).unwrap();
black_box(nbt);
})
});
group.bench_function("fastnbt_parse", |b| {
b.iter(|| {
let input = black_box(input);
let nbt: fastnbt::Value = fastnbt::from_bytes(input).unwrap();
black_box(nbt);
})
});
group.bench_function("hematite_parse", |b| {
b.iter(|| {
let input = black_box(input);
let nbt = nbt::Blob::from_reader(&mut Cursor::new(input)).unwrap();
black_box(nbt);
})
});
// // writing
@ -103,14 +119,14 @@ pub fn bench_read_file(filename: &str, c: &mut Criterion) {
}
fn bench(c: &mut Criterion) {
// bench_read_file("tests/hello_world.nbt", c);
// bench_read_file("tests/bigtest.nbt", c);
bench_read_file("tests/simple_player.dat", c);
// bench_read_file("tests/complex_player.dat", c);
// bench_read_file("tests/level.dat", c);
// bench_read_file("tests/stringtest.nbt", c);
// bench_read_file("tests/inttest.nbt", c);
// bench_read_file("hello_world.nbt", c);
// 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("stringtest.nbt", c);
// bench_read_file("inttest.nbt", c);
}
criterion_group!(benches, bench);
criterion_main!(benches);
criterion_group!(compare, bench);
criterion_main!(compare);

View file

@ -1,4 +1,3 @@
use azalea_nbt::Nbt;
use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
use flate2::read::GzDecoder;
use std::{
@ -7,7 +6,7 @@ use std::{
};
fn bench_file(filename: &str, c: &mut Criterion) {
let mut file = File::open(filename).unwrap();
let mut file = File::open(format!("tests/{filename}")).unwrap();
let mut contents = Vec::new();
file.read_to_end(&mut contents).unwrap();
let mut src = &contents[..];
@ -22,26 +21,17 @@ fn bench_file(filename: &str, c: &mut Criterion) {
let mut decoded_src_stream = Cursor::new(&decoded_src[..]);
let nbt = Nbt::read(&mut decoded_src_stream).unwrap();
decoded_src_stream.set_position(0);
let mut group = c.benchmark_group(filename);
let mut group = c.benchmark_group(format!("nbt/{filename}"));
group.throughput(Throughput::Bytes(decoded_src.len() as u64));
group.bench_function("Decode", |b| {
b.iter(|| {
black_box(Nbt::read(&mut decoded_src_stream).unwrap());
black_box(simdnbt::Nbt::new(&mut decoded_src_stream).unwrap());
decoded_src_stream.set_position(0);
})
});
group.bench_function("Encode", |b| {
b.iter(|| {
nbt.write(&mut black_box(Vec::new()));
})
});
// group.bench_function("Get", |b| {
// b.iter(|| {
// let level = nbt
@ -60,16 +50,16 @@ fn bench_file(filename: &str, c: &mut Criterion) {
}
fn bench(c: &mut Criterion) {
// bench_file("tests/bigtest.nbt", c);
// bench_file("tests/simple_player.dat", c);
// bench_file("tests/complex_player.dat", c);
// bench_file("tests/level.dat", c);
// bench_file("tests/stringtest.nbt", c);
// bench_file("tests/inttest16.nbt", c);
// bench_file("bigtest.nbt", c);
// bench_file("simple_player.dat", c);
bench_file("complex_player.dat", c);
// bench_file("level.dat", c);
// bench_file("stringtest.nbt", c);
// bench_file("inttest16.nbt", c);
// bench_file("tests/inttest1023.nbt", c);
// bench_file("tests/inttest3.nbt", c);
// bench_file("inttest1023.nbt", c);
// bench_file("inttest3.nbt", c);
}
criterion_group!(benches, bench);
criterion_main!(benches);
criterion_group!(nbt, bench);
criterion_main!(nbt);

View file

@ -1,3 +1,12 @@
/// an unnecessarily fast nbt decoder.
///
/// ```
/// use simdnbt::Nbt;
///
/// let nbt = Nbt::new(&mut std::io::Cursor::new(include_bytes!("../tests/hello_world.nbt"))).unwrap().unwrap();
/// assert_eq!(nbt.name().to_str(), "hello world");
/// assert_eq!(nbt.string("name").unwrap().to_str().as_ref(), "Bananrama");
/// ```
mod error;
mod mutf8;
@ -25,10 +34,7 @@ impl<'a> Deref for Nbt<'a> {
}
}
pub fn read_with_u16_length<'a>(
data: &mut Cursor<&'a [u8]>,
width: usize,
) -> Result<&'a [u8], Error> {
fn read_with_u16_length<'a>(data: &mut Cursor<&'a [u8]>, width: usize) -> Result<&'a [u8], Error> {
let length = data.read_u16::<BE>()?;
let length_in_bytes = length as usize * width;
// make sure we don't read more than the length
@ -40,10 +46,7 @@ pub fn read_with_u16_length<'a>(
Ok(&data.get_ref()[start_position..start_position + length_in_bytes])
}
pub fn read_with_u32_length<'a>(
data: &mut Cursor<&'a [u8]>,
width: usize,
) -> Result<&'a [u8], Error> {
fn read_with_u32_length<'a>(data: &mut Cursor<&'a [u8]>, width: usize) -> Result<&'a [u8], Error> {
let length = data.read_u32::<BE>()?;
let length_in_bytes = length as usize * width;
// make sure we don't read more than the length
@ -55,7 +58,7 @@ pub fn read_with_u32_length<'a>(
Ok(&data.get_ref()[start_position..start_position + length_in_bytes])
}
pub fn read_string<'a>(data: &mut Cursor<&'a [u8]>) -> Result<&'a Mutf8Str, Error> {
fn read_string<'a>(data: &mut Cursor<&'a [u8]>) -> Result<&'a Mutf8Str, Error> {
let data = read_with_u16_length(data, 1)?;
Ok(Mutf8Str::from_slice(data))
}
@ -76,27 +79,27 @@ impl<'a> Nbt<'a> {
}
}
pub const END_ID: u8 = 0;
pub const BYTE_ID: u8 = 1;
pub const SHORT_ID: u8 = 2;
pub const INT_ID: u8 = 3;
pub const LONG_ID: u8 = 4;
pub const FLOAT_ID: u8 = 5;
pub const DOUBLE_ID: u8 = 6;
pub const BYTE_ARRAY_ID: u8 = 7;
pub const STRING_ID: u8 = 8;
pub const LIST_ID: u8 = 9;
pub const COMPOUND_ID: u8 = 10;
pub const INT_ARRAY_ID: u8 = 11;
pub const LONG_ARRAY_ID: u8 = 12;
const END_ID: u8 = 0;
const BYTE_ID: u8 = 1;
const SHORT_ID: u8 = 2;
const INT_ID: u8 = 3;
const LONG_ID: u8 = 4;
const FLOAT_ID: u8 = 5;
const DOUBLE_ID: u8 = 6;
const BYTE_ARRAY_ID: u8 = 7;
const STRING_ID: u8 = 8;
const LIST_ID: u8 = 9;
const COMPOUND_ID: u8 = 10;
const INT_ARRAY_ID: u8 = 11;
const LONG_ARRAY_ID: u8 = 12;
const MAX_DEPTH: usize = 512;
#[derive(Debug, Default)]
pub struct CompoundTag<'a> {
values: Vec<(&'a Mutf8Str, Tag<'a>)>,
}
const MAX_DEPTH: usize = 512;
impl<'a> CompoundTag<'a> {
fn new(data: &mut Cursor<&'a [u8]>, depth: usize) -> Result<Self, Error> {
if depth > MAX_DEPTH {
@ -133,6 +136,7 @@ impl<'a> CompoundTag<'a> {
Ok(Self { values })
}
#[inline]
pub fn get(&self, name: &str) -> Option<&Tag<'a>> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
@ -157,148 +161,76 @@ impl<'a> CompoundTag<'a> {
}
pub fn byte(&self, name: &str) -> Option<i8> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
if key == &name {
if let Tag::Byte(value) = value {
return Some(*value);
}
}
match self.get(name) {
Some(Tag::Byte(byte)) => Some(*byte),
_ => None,
}
None
}
pub fn short(&self, name: &str) -> Option<i16> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
if key == &name {
if let Tag::Short(value) = value {
return Some(*value);
}
}
match self.get(name) {
Some(Tag::Short(short)) => Some(*short),
_ => None,
}
None
}
pub fn int(&self, name: &str) -> Option<i32> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
if key == &name {
if let Tag::Int(value) = value {
return Some(*value);
}
}
match self.get(name) {
Some(Tag::Int(int)) => Some(*int),
_ => None,
}
None
}
pub fn long(&self, name: &str) -> Option<i64> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
if key == &name {
if let Tag::Long(value) = value {
return Some(*value);
}
}
match self.get(name) {
Some(Tag::Long(long)) => Some(*long),
_ => None,
}
None
}
pub fn float(&self, name: &str) -> Option<f32> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
if key == &name {
if let Tag::Float(value) = value {
return Some(*value);
}
}
match self.get(name) {
Some(Tag::Float(float)) => Some(*float),
_ => None,
}
None
}
pub fn double(&self, name: &str) -> Option<&f64> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
if key == &name {
if let Tag::Double(value) = value {
return Some(value);
}
}
match self.get(name) {
Some(Tag::Double(double)) => Some(double),
_ => None,
}
None
}
pub fn byte_array(&self, name: &str) -> Option<&[u8]> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
if key == &name {
if let Tag::ByteArray(value) = value {
return Some(value);
}
}
match self.get(name) {
Some(Tag::ByteArray(byte_array)) => Some(byte_array),
_ => None,
}
None
}
pub fn string(&self, name: &str) -> Option<&Mutf8Str> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
if key == &name {
if let Tag::String(value) = value {
return Some(value);
}
}
match self.get(name) {
Some(Tag::String(string)) => Some(string),
_ => None,
}
None
}
pub fn list(&self, name: &str) -> Option<&ListTag<'a>> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
if key == &name {
if let Tag::List(value) = value {
return Some(value);
}
}
match self.get(name) {
Some(Tag::List(list)) => Some(list),
_ => None,
}
None
}
pub fn compound(&self, name: &str) -> Option<&CompoundTag<'a>> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
if key == &name {
if let Tag::Compound(value) = value {
return Some(value);
}
}
match self.get(name) {
Some(Tag::Compound(compound)) => Some(compound),
_ => None,
}
None
}
pub fn int_array(&self, name: &str) -> Option<&[i32]> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
if key == &name {
if let Tag::IntArray(value) = value {
return Some(value);
}
}
match self.get(name) {
Some(Tag::IntArray(int_array)) => Some(int_array),
_ => None,
}
None
}
pub fn long_array(&self, name: &str) -> Option<&[i64]> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
if key == &name {
if let Tag::LongArray(value) = value {
return Some(value);
}
}
match self.get(name) {
Some(Tag::LongArray(long_array)) => Some(long_array),
_ => None,
}
None
}
pub fn iter(&self) -> impl Iterator<Item = (&Mutf8Str, &Tag<'a>)> {

Binary file not shown.