mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
azalea-language now does a binary search instead of a hashmap lookup
This commit is contained in:
parent
2be4f0f2b6
commit
6a5ab34a2d
7 changed files with 30 additions and 13 deletions
|
@ -264,7 +264,7 @@ pub fn make_basic_empty_chunk(
|
||||||
z: pos.z,
|
z: pos.z,
|
||||||
chunk_data: ClientboundLevelChunkPacketData {
|
chunk_data: ClientboundLevelChunkPacketData {
|
||||||
heightmaps: Nbt::None,
|
heightmaps: Nbt::None,
|
||||||
data: chunk_bytes.into(),
|
data: Arc::new(chunk_bytes.into()),
|
||||||
block_entities: vec![],
|
block_entities: vec![],
|
||||||
},
|
},
|
||||||
light_data: ClientboundLightUpdatePacketData::default(),
|
light_data: ClientboundLightUpdatePacketData::default(),
|
||||||
|
|
|
@ -4,9 +4,22 @@ use std::{collections::HashMap, sync::LazyLock};
|
||||||
|
|
||||||
use compact_str::CompactString;
|
use compact_str::CompactString;
|
||||||
|
|
||||||
pub static STORAGE: LazyLock<HashMap<CompactString, CompactString>> =
|
pub static STORAGE: LazyLock<Vec<(CompactString, CompactString)>> = LazyLock::new(|| {
|
||||||
LazyLock::new(|| serde_json::from_str(include_str!("en_us.json")).unwrap());
|
let json =
|
||||||
|
serde_json::from_str::<HashMap<CompactString, CompactString>>(include_str!("en_us.json"))
|
||||||
|
.unwrap();
|
||||||
|
let mut json = json.into_iter().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// sort by key to make binary search work
|
||||||
|
json.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
|
|
||||||
|
json
|
||||||
|
});
|
||||||
|
|
||||||
pub fn get(key: &str) -> Option<&str> {
|
pub fn get(key: &str) -> Option<&str> {
|
||||||
STORAGE.get(key).map(|s| s.as_str())
|
let key = CompactString::from(key);
|
||||||
|
let storage = &*STORAGE;
|
||||||
|
// more memory efficient than a hashmap lookup
|
||||||
|
let index = storage.binary_search_by(|(k, _)| k.cmp(&key));
|
||||||
|
index.ok().map(|i| storage[i].1.as_str())
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub struct ClientboundLevelChunkPacketData {
|
||||||
///
|
///
|
||||||
/// This is an Arc because it's often very big and we want it to be cheap to
|
/// This is an Arc because it's often very big and we want it to be cheap to
|
||||||
/// clone.
|
/// clone.
|
||||||
pub data: Arc<Vec<u8>>,
|
pub data: Arc<Box<[u8]>>,
|
||||||
pub block_entities: Vec<BlockEntity>,
|
pub block_entities: Vec<BlockEntity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,11 @@ impl Error for BitStorageError {}
|
||||||
impl BitStorage {
|
impl BitStorage {
|
||||||
/// Create a new BitStorage with the given number of bits per entry.
|
/// Create a new BitStorage with the given number of bits per entry.
|
||||||
/// `size` is the number of entries in the BitStorage.
|
/// `size` is the number of entries in the BitStorage.
|
||||||
pub fn new(bits: usize, size: usize, data: Option<Vec<u64>>) -> Result<Self, BitStorageError> {
|
pub fn new(
|
||||||
|
bits: usize,
|
||||||
|
size: usize,
|
||||||
|
data: Option<Box<[u64]>>,
|
||||||
|
) -> Result<Self, BitStorageError> {
|
||||||
if let Some(data) = &data {
|
if let Some(data) = &data {
|
||||||
// 0 bit storage
|
// 0 bit storage
|
||||||
if data.is_empty() {
|
if data.is_empty() {
|
||||||
|
@ -132,11 +136,11 @@ impl BitStorage {
|
||||||
}
|
}
|
||||||
data
|
data
|
||||||
} else {
|
} else {
|
||||||
vec![0; calculated_length]
|
vec![0; calculated_length].into()
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(BitStorage {
|
Ok(BitStorage {
|
||||||
data: using_data.into(),
|
data: using_data,
|
||||||
bits,
|
bits,
|
||||||
mask,
|
mask,
|
||||||
size,
|
size,
|
||||||
|
@ -252,7 +256,7 @@ mod tests {
|
||||||
1, 2, 2, 3, 4, 4, 5, 6, 6, 4, 8, 0, 7, 4, 3, 13, 15, 16, 9, 14, 10, 12, 0, 2,
|
1, 2, 2, 3, 4, 4, 5, 6, 6, 4, 8, 0, 7, 4, 3, 13, 15, 16, 9, 14, 10, 12, 0, 2,
|
||||||
];
|
];
|
||||||
let compact_data: [u64; 2] = [0x0020863148418841, 0x01018A7260F68C87];
|
let compact_data: [u64; 2] = [0x0020863148418841, 0x01018A7260F68C87];
|
||||||
let storage = BitStorage::new(5, data.len(), Some(compact_data.to_vec())).unwrap();
|
let storage = BitStorage::new(5, data.len(), Some(Box::new(compact_data))).unwrap();
|
||||||
|
|
||||||
for (i, expected) in data.iter().enumerate() {
|
for (i, expected) in data.iter().enumerate() {
|
||||||
assert_eq!(storage.get(i), *expected);
|
assert_eq!(storage.get(i), *expected);
|
||||||
|
|
|
@ -353,7 +353,7 @@ impl Chunk {
|
||||||
warn!("Heightmap {name} is not a long array");
|
warn!("Heightmap {name} is not a long array");
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let data: Vec<u64> = data.iter().map(|x| *x as u64).collect();
|
let data: Box<[u64]> = data.iter().map(|x| *x as u64).collect();
|
||||||
let heightmap = Heightmap::new(kind, dimension_height, min_y, data);
|
let heightmap = Heightmap::new(kind, dimension_height, min_y, data);
|
||||||
heightmaps.insert(kind, heightmap);
|
heightmaps.insert(kind, heightmap);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl HeightmapKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Heightmap {
|
impl Heightmap {
|
||||||
pub fn new(kind: HeightmapKind, dimension_height: u32, min_y: i32, data: Vec<u64>) -> Self {
|
pub fn new(kind: HeightmapKind, dimension_height: u32, min_y: i32, data: Box<[u64]>) -> Self {
|
||||||
let bits = math::ceil_log2(dimension_height + 1);
|
let bits = math::ceil_log2(dimension_height + 1);
|
||||||
let data = BitStorage::new(bits as usize, 16 * 16, Some(data)).unwrap();
|
let data = BitStorage::new(bits as usize, 16 * 16, Some(data)).unwrap();
|
||||||
Self { kind, data, min_y }
|
Self { kind, data, min_y }
|
||||||
|
|
|
@ -31,7 +31,7 @@ impl PalettedContainer {
|
||||||
pub fn new(container_type: PalettedContainerKind) -> Self {
|
pub fn new(container_type: PalettedContainerKind) -> Self {
|
||||||
let palette = Palette::SingleValue(0);
|
let palette = Palette::SingleValue(0);
|
||||||
let size = container_type.size();
|
let size = container_type.size();
|
||||||
let storage = BitStorage::new(0, size, Some(vec![])).unwrap();
|
let storage = BitStorage::new(0, size, Some(Box::new([]))).unwrap();
|
||||||
|
|
||||||
PalettedContainer {
|
PalettedContainer {
|
||||||
bits_per_entry: 0,
|
bits_per_entry: 0,
|
||||||
|
@ -76,7 +76,7 @@ impl PalettedContainer {
|
||||||
bits_per_entry.into(),
|
bits_per_entry.into(),
|
||||||
size,
|
size,
|
||||||
if data.is_empty() {
|
if data.is_empty() {
|
||||||
Some(vec![])
|
Some(Box::new([]))
|
||||||
} else {
|
} else {
|
||||||
// we're going to update the data after creating the bitstorage
|
// we're going to update the data after creating the bitstorage
|
||||||
None
|
None
|
||||||
|
|
Loading…
Add table
Reference in a new issue