aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2022-08-19 14:14:08 -0500
committerGitHub <noreply@github.com>2022-08-19 14:14:08 -0500
commitac4d675d44a93a6625f508263c650206a7ff1f98 (patch)
tree38822285da0b365bfd7f2e347d19e1e2db78bd46
parentb9cb596ea75b446d19e6ad066c750348be60f4c7 (diff)
downloadazalea-drasl-ac4d675d44a93a6625f508263c650206a7ff1f98.tar.xz
NBT decoder optimizations (#17)
* replace HashMap with AHashMap * faster read_string by just doing read_exact * re-enable all the benchmarks
-rwxr-xr-xCargo.lock12
-rwxr-xr-xazalea-nbt/Cargo.toml1
-rwxr-xr-xazalea-nbt/src/decode.rs18
-rwxr-xr-xazalea-nbt/src/encode.rs4
-rwxr-xr-xazalea-nbt/src/lib.rs11
-rwxr-xr-xazalea-nbt/src/tag.rs30
-rwxr-xr-xazalea-nbt/tests/tests.rs8
7 files changed, 47 insertions, 37 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 5f1bdb2e..fc80ad39 100755
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -20,6 +20,17 @@ dependencies = [
]
[[package]]
+name = "ahash"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
+dependencies = [
+ "getrandom",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
name = "anyhow"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -183,6 +194,7 @@ dependencies = [
name = "azalea-nbt"
version = "0.1.0"
dependencies = [
+ "ahash",
"azalea-buf",
"byteorder",
"criterion",
diff --git a/azalea-nbt/Cargo.toml b/azalea-nbt/Cargo.toml
index 992d242a..3b334e37 100755
--- a/azalea-nbt/Cargo.toml
+++ b/azalea-nbt/Cargo.toml
@@ -6,6 +6,7 @@ version = "0.1.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+ahash = "0.7.6"
azalea-buf = {path = "../azalea-buf"}
byteorder = "1.4.3"
flate2 = "1.0.23"
diff --git a/azalea-nbt/src/decode.rs b/azalea-nbt/src/decode.rs
index 12c13448..314e763e 100755
--- a/azalea-nbt/src/decode.rs
+++ b/azalea-nbt/src/decode.rs
@@ -1,21 +1,17 @@
use crate::Error;
use crate::Tag;
-use azalea_buf::BufReadError;
-use azalea_buf::McBufReadable;
+use ahash::AHashMap;
+use azalea_buf::{BufReadError, McBufReadable};
use byteorder::{ReadBytesExt, BE};
use flate2::read::{GzDecoder, ZlibDecoder};
-use std::collections::HashMap;
-use std::io::BufRead;
-use std::io::Read;
+use std::io::{BufRead, Read};
#[inline]
fn read_string(stream: &mut impl Read) -> Result<String, Error> {
let length = stream.read_u16::<BE>()?;
- let mut buf = Vec::with_capacity(length as usize);
- for _ in 0..length {
- buf.push(stream.read_u8()?);
- }
+ let mut buf = vec![0; length as usize];
+ stream.read_exact(&mut buf)?;
Ok(String::from_utf8(buf)?)
}
@@ -74,7 +70,7 @@ impl Tag {
// Effectively a list of a named tags. Order is not guaranteed.
10 => {
// we default to capacity 4 because it'll probably not be empty
- let mut map = HashMap::with_capacity(4);
+ let mut map = AHashMap::with_capacity(4);
loop {
let tag_id = stream.read_u8().unwrap_or(0);
if tag_id == 0 {
@@ -122,7 +118,7 @@ impl Tag {
}
let name = read_string(stream)?;
let tag = Tag::read_known(stream, tag_id)?;
- let mut map = HashMap::with_capacity(1);
+ let mut map = AHashMap::with_capacity(1);
map.insert(name, tag);
Ok(Tag::Compound(map))
diff --git a/azalea-nbt/src/encode.rs b/azalea-nbt/src/encode.rs
index 3763ffd1..1bb8f366 100755
--- a/azalea-nbt/src/encode.rs
+++ b/azalea-nbt/src/encode.rs
@@ -1,9 +1,9 @@
use crate::Error;
use crate::Tag;
+use ahash::AHashMap;
use azalea_buf::McBufWritable;
use byteorder::{WriteBytesExt, BE};
use flate2::write::{GzEncoder, ZlibEncoder};
-use std::collections::HashMap;
use std::io::Write;
// who needs friends when you've got code that runs in nanoseconds?
@@ -19,7 +19,7 @@ fn write_string(writer: &mut dyn Write, string: &str) -> Result<(), Error> {
#[inline]
fn write_compound(
writer: &mut dyn Write,
- value: &HashMap<String, Tag>,
+ value: &AHashMap<String, Tag>,
end_tag: bool,
) -> Result<(), Error> {
for (key, tag) in value {
diff --git a/azalea-nbt/src/lib.rs b/azalea-nbt/src/lib.rs
index 75232eb0..c644cfdc 100755
--- a/azalea-nbt/src/lib.rs
+++ b/azalea-nbt/src/lib.rs
@@ -9,15 +9,16 @@ pub use tag::Tag;
#[cfg(test)]
mod tests {
use super::*;
+ use ahash::AHashMap;
use azalea_buf::{McBufReadable, McBufWritable};
- use std::{collections::HashMap, io::Cursor};
+ use std::io::Cursor;
#[test]
fn mcbuf_nbt() {
let mut buf = Vec::new();
- let tag = Tag::Compound(HashMap::from_iter(vec![(
+ let tag = Tag::Compound(AHashMap::from_iter(vec![(
"hello world".to_string(),
- Tag::Compound(HashMap::from_iter(vec![(
+ Tag::Compound(AHashMap::from_iter(vec![(
"name".to_string(),
Tag::String("Bananrama".to_string()),
)])),
@@ -29,9 +30,9 @@ mod tests {
let result = Tag::read_from(&mut buf).unwrap();
assert_eq!(
result,
- Tag::Compound(HashMap::from_iter(vec![(
+ Tag::Compound(AHashMap::from_iter(vec![(
"hello world".to_string(),
- Tag::Compound(HashMap::from_iter(vec![(
+ Tag::Compound(AHashMap::from_iter(vec![(
"name".to_string(),
Tag::String("Bananrama".to_string()),
)])),
diff --git a/azalea-nbt/src/tag.rs b/azalea-nbt/src/tag.rs
index e2df08f7..1b96a8cb 100755
--- a/azalea-nbt/src/tag.rs
+++ b/azalea-nbt/src/tag.rs
@@ -1,20 +1,20 @@
-use std::collections::HashMap;
+use ahash::AHashMap;
#[derive(Clone, Debug, PartialEq)]
pub enum Tag {
- End, // 0
- Byte(i8), // 1
- Short(i16), // 2
- Int(i32), // 3
- Long(i64), // 4
- Float(f32), // 5
- Double(f64), // 6
- ByteArray(Vec<i8>), // 7
- String(String), // 8
- List(Vec<Tag>), // 9
- Compound(HashMap<String, Tag>), // 10
- IntArray(Vec<i32>), // 11
- LongArray(Vec<i64>), // 12
+ End, // 0
+ Byte(i8), // 1
+ Short(i16), // 2
+ Int(i32), // 3
+ Long(i64), // 4
+ Float(f32), // 5
+ Double(f64), // 6
+ ByteArray(Vec<i8>), // 7
+ String(String), // 8
+ List(Vec<Tag>), // 9
+ Compound(AHashMap<String, Tag>), // 10
+ IntArray(Vec<i32>), // 11
+ LongArray(Vec<i64>), // 12
}
impl Default for Tag {
@@ -107,7 +107,7 @@ impl Tag {
}
#[inline]
- pub fn as_compound(&self) -> Option<&HashMap<String, Tag>> {
+ pub fn as_compound(&self) -> Option<&AHashMap<String, Tag>> {
if let Tag::Compound(v) = self {
Some(v)
} else {
diff --git a/azalea-nbt/tests/tests.rs b/azalea-nbt/tests/tests.rs
index 7f20e54d..41a14d1b 100755
--- a/azalea-nbt/tests/tests.rs
+++ b/azalea-nbt/tests/tests.rs
@@ -1,6 +1,6 @@
+use ahash::AHashMap;
use azalea_nbt::Tag;
use std::{
- collections::HashMap,
fs::File,
io::{Cursor, Read},
};
@@ -12,9 +12,9 @@ fn test_decode_hello_world() {
let tag = Tag::read(&mut file).unwrap();
assert_eq!(
tag,
- Tag::Compound(HashMap::from_iter(vec![(
+ Tag::Compound(AHashMap::from_iter(vec![(
"hello world".to_string(),
- Tag::Compound(HashMap::from_iter(vec![(
+ Tag::Compound(AHashMap::from_iter(vec![(
"name".to_string(),
Tag::String("Bananrama".to_string()),
)]))
@@ -58,7 +58,7 @@ fn test_bigtest() {
#[test]
fn test_stringtest() {
- let correct_tag = Tag::Compound(HashMap::from_iter(vec![(
+ let correct_tag = Tag::Compound(AHashMap::from_iter(vec![(
"😃".to_string(),
Tag::List(vec![
Tag::String("asdfkghasfjgihsdfogjsndfg".to_string()),