Skip to content

Commit 50119ac

Browse files
committed
simplify bit storage
1 parent 0334413 commit 50119ac

File tree

5 files changed

+117
-93
lines changed

5 files changed

+117
-93
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

azalea-world/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ license.workspace = true
77
repository.workspace = true
88

99
[dev-dependencies]
10-
azalea.path = "../azalea"
1110
criterion.workspace = true
11+
rand.workspace = true
1212

1313
[dependencies]
1414
azalea-block.workspace = true

azalea-world/benches/chunks.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::hint::black_box;
33
use azalea_core::position::ChunkBlockPos;
44
use azalea_registry::builtin::BlockKind;
55
use azalea_world::{BitStorage, Chunk};
6-
use criterion::{Criterion, criterion_group, criterion_main};
6+
use criterion::{BatchSize, Bencher, Criterion, criterion_group, criterion_main};
77

88
fn bench_chunks(c: &mut Criterion) {
99
c.bench_function("Chunk::set", |b| {
@@ -25,13 +25,36 @@ fn bench_chunks(c: &mut Criterion) {
2525
});
2626
}
2727

28+
fn bench_bitstorage_with(b: &mut Bencher, bits: usize, size: usize) {
29+
let mut storage = BitStorage::new(bits, size, None).unwrap();
30+
b.iter_batched(
31+
|| {
32+
// let index = rand
33+
let mut vec = Vec::with_capacity(size);
34+
for _ in 0..size {
35+
vec.push(rand::random_range(0..size));
36+
}
37+
vec
38+
},
39+
|indices| {
40+
for index in indices {
41+
storage.set(index, 1);
42+
}
43+
},
44+
BatchSize::SmallInput,
45+
);
46+
black_box(storage);
47+
}
48+
2849
fn bench_bitstorage(c: &mut Criterion) {
29-
c.bench_function("BitStorage::set", |b| {
30-
let mut storage = BitStorage::new(1, 4096, None).unwrap();
31-
b.iter(|| {
32-
storage.set(136, 1);
33-
});
34-
black_box(storage);
50+
c.bench_function("BitStorage::set (1 bit per entry)", |b| {
51+
bench_bitstorage_with(b, 1, 4096)
52+
});
53+
c.bench_function("BitStorage::set (2 bits per entry)", |b| {
54+
bench_bitstorage_with(b, 2, 4096)
55+
});
56+
c.bench_function("BitStorage::set (3 bits per entry)", |b| {
57+
bench_bitstorage_with(b, 3, 4096)
3558
});
3659
}
3760

azalea-world/src/bit_storage.rs

Lines changed: 83 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,73 @@
11
use std::{error::Error, fmt};
22

3+
// fast constant division
34
#[rustfmt::skip]
4-
const MAGIC: [(i32, i32, i32); 64] = [
5-
// divide_mul, divide_add, divide_shift
6-
(-1, -1, 0),
7-
(-0b10000000000000000000000000000000, 0, 0),
8-
(0b1010101010101010101010101010101, 0b1010101010101010101010101010101, 0),
9-
(-0b10000000000000000000000000000000, 0, 1),
10-
(0b110011001100110011001100110011, 0b110011001100110011001100110011, 0),
11-
(0b101010101010101010101010101010, 0b101010101010101010101010101010, 0),
12-
(0b100100100100100100100100100100, 0b100100100100100100100100100100, 0),
13-
(-0b10000000000000000000000000000000, 0, 2),
14-
(0b11100011100011100011100011100, 0b11100011100011100011100011100, 0),
15-
(0b11001100110011001100110011001, 0b11001100110011001100110011001, 0),
16-
(0b10111010001011101000101110100, 0b10111010001011101000101110100, 0),
17-
(0b10101010101010101010101010101, 0b10101010101010101010101010101, 0),
18-
(0b10011101100010011101100010011, 0b10011101100010011101100010011, 0),
19-
(0b10010010010010010010010010010, 0b10010010010010010010010010010, 0),
20-
(0b10001000100010001000100010001, 0b10001000100010001000100010001, 0),
21-
(-0b10000000000000000000000000000000, 0, 3),
22-
(0b1111000011110000111100001111, 0b1111000011110000111100001111, 0),
23-
(0b1110001110001110001110001110, 0b1110001110001110001110001110, 0),
24-
(0b1101011110010100001101011110, 0b1101011110010100001101011110, 0),
25-
(0b1111111111111111111111111111000, 0b1111111111111111111111111111000, 0),
26-
(0b1100001100001100001100001100, 0b1100001100001100001100001100, 0),
27-
(0b1011101000101110100010111010, 0b1011101000101110100010111010, 0),
28-
(0b1011001000010110010000101100, 0b1011001000010110010000101100, 0),
29-
(0b1010101010101010101010101010, 0b1010101010101010101010101010, 0),
30-
(0b1010001111010111000010100011, 0b1010001111010111000010100011, 0),
31-
(0b1001110110001001110110001001, 0b1001110110001001110110001001, 0),
32-
(0b1001011110110100001001011110, 0b1001011110110100001001011110, 0),
33-
(0b1001001001001001001001001001, 0b1001001001001001001001001001, 0),
34-
(0b1000110100111101110010110000, 0b1000110100111101110010110000, 0),
35-
(0b1000100010001000100010001000, 0b1000100010001000100010001000, 0),
36-
(0b1000010000100001000010000100, 0b1000010000100001000010000100, 0),
37-
(-0b10000000000000000000000000000000, 0, 4),
38-
(0b111110000011111000001111100, 0b111110000011111000001111100, 0),
39-
(0b111100001111000011110000111, 0b111100001111000011110000111, 0),
40-
(0b111010100000111010100000111, 0b111010100000111010100000111, 0),
41-
(0b111000111000111000111000111, 0b111000111000111000111000111, 0),
42-
(0b110111010110011111001000101, 0b110111010110011111001000101, 0),
43-
(0b110101111001010000110101111, 0b110101111001010000110101111, 0),
44-
(0b110100100000110100100000110, 0b110100100000110100100000110, 0),
45-
(0b110011001100110011001100110, 0b110011001100110011001100110, 0),
46-
(0b110001111100111000001100011, 0b110001111100111000001100011, 0),
47-
(0b110000110000110000110000110, 0b110000110000110000110000110, 0),
48-
(0b101111101000001011111010000, 0b101111101000001011111010000, 0),
49-
(0b101110100010111010001011101, 0b101110100010111010001011101, 0),
50-
(0b101101100000101101100000101, 0b101101100000101101100000101, 0),
51-
(0b101100100001011001000010110, 0b101100100001011001000010110, 0),
52-
(0b101011100100110001000001010, 0b101011100100110001000001010, 0),
53-
(0b101010101010101010101010101, 0b101010101010101010101010101, 0),
54-
(0b101001110010111100000101001, 0b101001110010111100000101001, 0),
55-
(0b101000111101011100001010001, 0b101000111101011100001010001, 0),
56-
(0b101000001010000010100000101, 0b101000001010000010100000101, 0),
57-
(0b100111011000100111011000100, 0b100111011000100111011000100, 0),
58-
(0b100110101001000011100111110, 0b100110101001000011100111110, 0),
59-
(0b100101111011010000100101111, 0b100101111011010000100101111, 0),
60-
(0b100101001111001000001001010, 0b100101001111001000001001010, 0),
61-
(0b100100100100100100100100100, 0b100100100100100100100100100, 0),
62-
(0b100011111011100000100011111, 0b100011111011100000100011111, 0),
63-
(0b100011010011110111001011000, 0b100011010011110111001011000, 0),
64-
(0b100010101101100011110010111, 0b100010101101100011110010111, 0),
65-
(0b100010001000100010001000100, 0b100010001000100010001000100, 0),
66-
(0b100001100100101110001010011, 0b100001100100101110001010011, 0),
67-
(0b100001000010000100001000010, 0b100001000010000100001000010, 0),
68-
(0b100000100000100000100000100, 0b100000100000100000100000100, 0),
69-
(-0b10000000000000000000000000000000, 0, 5),
5+
const MAGIC: [(i32, i32, u32); 64] = [
6+
// mul, add, shift
7+
(1, 0, 0), // divide by 1
8+
(1, 0, 1), // divide by 2, etc
9+
(0x55555555, 0x55555555, 32),
10+
(1, 0, 2),
11+
(0x33333333, 0x33333333, 32),
12+
(0x2AAAAAAA, 0x2AAAAAAA, 32),
13+
(0x24924924, 0x24924924, 32),
14+
(1, 0, 3),
15+
(0x1C71C71C, 0x1C71C71C, 32),
16+
(0x19999999, 0x19999999, 32),
17+
(0x1745D174, 0x1745D174, 32),
18+
(0x15555555, 0x15555555, 32),
19+
(0x13B13B13, 0x13B13B13, 32),
20+
(0x12492492, 0x12492492, 32),
21+
(0x11111111, 0x11111111, 32),
22+
(1, 0, 4),
23+
(0xF0F0F0F, 0xF0F0F0F, 32),
24+
(0xE38E38E, 0xE38E38E, 32),
25+
(0xD79435E, 0xD79435E, 32),
26+
(0x7FFFFFF8, 0x7FFFFFF8, 32),
27+
(0xC30C30C, 0xC30C30C, 32),
28+
(0xBA2E8BA, 0xBA2E8BA, 32),
29+
(0xB21642C, 0xB21642C, 32),
30+
(0xAAAAAAA, 0xAAAAAAA, 32),
31+
(0xA3D70A3, 0xA3D70A3, 32),
32+
(0x9D89D89, 0x9D89D89, 32),
33+
(0x97B425E, 0x97B425E, 32),
34+
(0x9249249, 0x9249249, 32),
35+
(0x8D3DCB0, 0x8D3DCB0, 32),
36+
(0x8888888, 0x8888888, 32),
37+
(0x8421084, 0x8421084, 32),
38+
(1, 0, 5),
39+
(0x7C1F07C, 0x7C1F07C, 32),
40+
(0x7878787, 0x7878787, 32),
41+
(0x7507507, 0x7507507, 32),
42+
(0x71C71C7, 0x71C71C7, 32),
43+
(0x6EB3E45, 0x6EB3E45, 32),
44+
(0x6BCA1AF, 0x6BCA1AF, 32),
45+
(0x6906906, 0x6906906, 32),
46+
(0x6666666, 0x6666666, 32),
47+
(0x63E7063, 0x63E7063, 32),
48+
(0x6186186, 0x6186186, 32),
49+
(0x5F417D0, 0x5F417D0, 32),
50+
(0x5D1745D, 0x5D1745D, 32),
51+
(0x5B05B05, 0x5B05B05, 32),
52+
(0x590B216, 0x590B216, 32),
53+
(0x572620A, 0x572620A, 32),
54+
(0x5555555, 0x5555555, 32),
55+
(0x5397829, 0x5397829, 32),
56+
(0x51EB851, 0x51EB851, 32),
57+
(0x5050505, 0x5050505, 32),
58+
(0x4EC4EC4, 0x4EC4EC4, 32),
59+
(0x4D4873E, 0x4D4873E, 32),
60+
(0x4BDA12F, 0x4BDA12F, 32),
61+
(0x4A7904A, 0x4A7904A, 32),
62+
(0x4924924, 0x4924924, 32),
63+
(0x47DC11F, 0x47DC11F, 32),
64+
(0x469EE58, 0x469EE58, 32),
65+
(0x456C797, 0x456C797, 32),
66+
(0x4444444, 0x4444444, 32),
67+
(0x4325C53, 0x4325C53, 32),
68+
(0x4210842, 0x4210842, 32),
69+
(0x4104104, 0x4104104, 32),
70+
(1, 0, 6),
7071
];
7172

7273
/// A compact list of integers with the given number of bits per entry.
@@ -77,9 +78,9 @@ pub struct BitStorage {
7778
mask: u64,
7879
size: usize,
7980
values_per_long: usize,
80-
divide_mul: u64,
81-
divide_add: u64,
82-
divide_shift: i32,
81+
divide_mul: i32,
82+
divide_add: i32,
83+
divide_shift: u32,
8384
}
8485

8586
#[derive(Debug)]
@@ -99,8 +100,8 @@ impl fmt::Display for BitStorageError {
99100
impl Error for BitStorageError {}
100101

101102
impl BitStorage {
102-
/// Create a new BitStorage with the given number of bits per entry.
103-
/// `size` is the number of entries in the BitStorage.
103+
/// Create a new BitStorage with the given number of bits per entry. `size`
104+
/// is the number of entries in the BitStorage.
104105
pub fn new(
105106
bits: usize,
106107
size: usize,
@@ -145,18 +146,19 @@ impl BitStorage {
145146
mask,
146147
size,
147148
values_per_long,
148-
divide_mul: divide_mul as u32 as u64,
149-
divide_add: divide_add as u32 as u64,
149+
divide_mul,
150+
divide_add,
150151
divide_shift,
151152
})
152153
}
153154

154-
pub fn cell_index(&self, index: u64) -> usize {
155-
// as unsigned wrap
156-
let first = self.divide_mul;
157-
let second = self.divide_add;
155+
#[inline]
156+
fn cell_index(&self, index: u64) -> usize {
157+
let mul = self.divide_mul as u32 as u64;
158+
let add = self.divide_add as u32 as u64;
159+
let shift = self.divide_shift;
158160

159-
(((index * first) + second) >> 32 >> self.divide_shift) as usize
161+
(((index * mul) + add) >> shift) as usize
160162
}
161163

162164
/// Get the data at the given index.
@@ -254,7 +256,9 @@ mod tests {
254256
use super::*;
255257

256258
#[test]
257-
fn test_wikivg_example() {
259+
fn test_protocol_wiki_example() {
260+
// https://minecraft.wiki/w/Java_Edition_protocol/Chunk_format#Visual_example
261+
258262
let data = [
259263
1, 2, 2, 3, 4, 4, 5, 6, 6, 4, 8, 0, 7, 4, 3, 13, 15, 16, 9, 14, 10, 12, 0, 2,
260264
];

azalea-world/src/find_blocks.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,8 @@ impl World {
1111
///
1212
/// ```
1313
/// # use azalea_registry::builtin::BlockKind;
14-
/// # fn example(client: &azalea::Client) {
15-
/// client
16-
/// .world()
17-
/// .read()
18-
/// .find_block(client.position(), &BlockKind::Chest.into());
14+
/// # fn example(world: &World) {
15+
/// let pos = world.find_block(client.position(), &BlockKind::Chest.into());
1916
/// # }
2017
/// ```
2118
pub fn find_block(

0 commit comments

Comments
 (0)