Skip to content

Commit 6ad1001

Browse files
feat: add broadcast crate (hyperion-mc#83)
1 parent fabd1fc commit 6ad1001

32 files changed

+808
-251
lines changed

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# https://doc.rust-lang.org/rustc/profile-guided-optimization.html
22
# https://nikolaivazquez.com/blog/divan/#measure-allocations
3+
# https://doc.rust-lang.org/cargo/reference/profiles.html
34

45
[workspace]
56
resolver = "2"
@@ -8,7 +9,8 @@ members = [
89
"server",
910
"chunk",
1011
"generator-build",
11-
"generator"
12+
"generator",
13+
"broadcast",
1214
]
1315

1416
[profile.dev]
@@ -21,17 +23,15 @@ opt-level = 3
2123
#debug = true
2224
lto = "fat"
2325
codegen-units = 1
24-
#strip = false
25-
#panic = "abort"
26+
panic = "abort"
2627

2728
[profile.bench]
28-
debug = true
29-
lto = false
30-
#lto = "fat"
31-
#codegen-units = 1
32-
#panic = "abort"
29+
#debug = true
30+
lto = "fat"
31+
codegen-units = 1
3332

3433
[workspace.dependencies]
3534
chunk = { path = "chunk" }
3635
generator-build = { path = "generator-build" }
3736
generator = { path = "generator" }
37+
broadcast = { path = "broadcast" }

Dockerfile

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,13 @@ COPY Cargo.toml Cargo.lock ./
3434
COPY chunk/Cargo.toml ./chunk/Cargo.toml
3535
COPY chunk/src ./chunk/src
3636

37+
COPY broadcast/Cargo.toml ./broadcast/Cargo.toml
38+
COPY broadcast/benches ./broadcast/benches
39+
COPY broadcast/src ./broadcast/src
40+
3741
COPY generator/Cargo.toml ./generator/Cargo.toml
3842
COPY generator/build.rs ./generator/build.rs
39-
COPY generator/generated.zip ./generator/generated.zip
43+
COPY generator/generated.tar.zst ./generator/generated.tar.zst
4044
COPY generator/src ./generator/src
4145

4246
COPY generator-build/Cargo.toml ./generator-build/Cargo.toml
@@ -109,12 +113,3 @@ RUN --mount=type=cache,target=/cargo-home \
109113
IAI_CALLGRIND_RUNNER=/cargo-home/bin/iai-callgrind-runner cargo bench --locked > /app/bench.txt
110114

111115
RUN cat /app/bench.txt
112-
113-
114-
115-
116-
#FROM alpine:3.19 as cli
117-
#
118-
## timings
119-
#COPY --from=debug /build/cargo-timing.html /app/cargo-timing.html
120-

broadcast/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/target

broadcast/Cargo.toml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[package]
2+
name = "broadcast"
3+
version = "0.1.0"
4+
edition = "2021"
5+
authors = ["Andrew Gazelka <[email protected]>"]
6+
readme = "README.md"
7+
publish = false
8+
9+
[dependencies]
10+
anyhow = "1.0.81"
11+
12+
[dev-dependencies]
13+
divan = "0.1.14"
14+
rand = "0.8.5"
15+
16+
[[bench]]
17+
name = "group"
18+
harness = false
19+
20+
[[bench]]
21+
name = "world"
22+
harness = false
23+
24+
[lints.clippy]
25+
complexity = "deny"
26+
27+
nursery = { level = "deny", priority = -1 }
28+
redundant_pub_crate = "allow"
29+
30+
pedantic = "deny"
31+
perf = "deny"
32+
style = "deny"
33+
suspicious = "deny"

broadcast/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# broadcast

broadcast/benches/group.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use std::hint::black_box;
2+
3+
use broadcast::utils::group::group;
4+
use divan::{AllocProfiler, Bencher};
5+
use rand::prelude::SliceRandom;
6+
7+
#[global_allocator]
8+
static ALLOC: AllocProfiler = AllocProfiler::system();
9+
10+
fn main() {
11+
divan::main();
12+
}
13+
14+
// say render distance is 32 chunks
15+
// this means we have 32 * 32 = 1024 chunks we will have to go through
16+
const LENS: &[u32] = &[64, 128, 256, 512, 1024, 2048];
17+
18+
// Register a `fibonacci` function and benchmark it over multiple cases.
19+
#[divan::bench(
20+
args = LENS,
21+
)]
22+
fn contiguous(bencher: Bencher, len: u32) {
23+
let v = (0..len).collect::<Vec<_>>();
24+
25+
bencher.counter(len).bench(|| {
26+
group(&v).for_each(|elem| {
27+
black_box(elem);
28+
});
29+
});
30+
}
31+
32+
#[divan::bench(
33+
args = LENS,
34+
)]
35+
fn random_eighth(bencher: Bencher, len: u32) {
36+
let mut v: Vec<_> = (0..len).collect();
37+
38+
// shuffle using rand
39+
v.shuffle(&mut rand::thread_rng());
40+
41+
let eigth = len / 8;
42+
43+
let idxes = &mut v[..eigth as usize];
44+
45+
// sort
46+
idxes.sort_unstable();
47+
48+
let idxes = &v[..eigth as usize];
49+
50+
bencher.counter(len).bench(|| {
51+
group(idxes).for_each(|elem| {
52+
black_box(elem);
53+
});
54+
});
55+
}

broadcast/benches/world.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#![feature(thread_local)]
2+
3+
use std::{cell::RefCell, collections::BTreeMap, hint::black_box};
4+
5+
use broadcast::Broadcaster;
6+
use divan::Bencher;
7+
8+
// #[global_allocator]
9+
// static ALLOC: AllocProfiler = AllocProfiler::system();
10+
11+
fn main() {
12+
divan::main();
13+
}
14+
15+
// say render distance is 32 chunks
16+
// this means we have 32 * 32 = 1024 chunks we will have to go through
17+
// const LENS: &[u16] = &[1, 2, 4, 8, 16, 32, 64];
18+
const LENS: &[u16] = &[128, 256, 512, 1024];
19+
20+
#[inline(never)]
21+
fn generate_world(width: u16) -> Broadcaster {
22+
let mut world = Broadcaster::create(width).unwrap();
23+
24+
world.populate(|_, data| {
25+
let data_len = rand::random::<u8>();
26+
let to_push = (0..data_len)
27+
.map(|_| rand::random::<u8>())
28+
.collect::<Vec<_>>();
29+
30+
data.extend(to_push);
31+
});
32+
33+
world
34+
}
35+
36+
// for normal (x, y) -> x + y * width
37+
// world fastest │ slowest │ median │ mean │
38+
// samples │ iters ╰─ player_render_distance_32 │ │ │
39+
// │ │ ├─ 128 709.6 µs │ 1.138 ms │ 785.8 µs │ 827.8
40+
// µs │ 100 │ 100 │ 14.09 Mitem/s │ 8.78 Mitem/s │ 12.72
41+
// Mitem/s │ 12.07 Mitem/s │ │ ├─ 256 835.8 µs │ 1.078 ms │
42+
// 937.8 µs │ 935.2 µs │ 100 │ 100 │ 11.96 Mitem/s │ 9.268
43+
// Mitem/s │ 10.66 Mitem/s │ 10.69 Mitem/s │ │ ├─ 512 1.004 ms │
44+
// 1.319 ms │ 1.124 ms │ 1.114 ms │ 100 │ 100 │ 9.952
45+
// Mitem/s │ 7.576 Mitem/s │ 8.893 Mitem/s │ 8.969 Mitem/s │ │ ╰─ 1024
46+
// 1.037 ms │ 1.336 ms │ 1.132 ms │ 1.138 ms │ 100 │ 100
47+
// 9.639 Mitem/s │ 7.48 Mitem/s │ 8.833 Mitem/s │ 8.784 Mitem/s │ │
48+
49+
//
50+
51+
#[thread_local]
52+
static WORLDS: RefCell<BTreeMap<u16, Broadcaster>> = RefCell::new(BTreeMap::new());
53+
54+
// Register a `fibonacci` function and benchmark it over multiple cases.
55+
#[divan::bench(
56+
args = LENS,
57+
)]
58+
fn player_render_distance_32(bencher: Bencher, len: u16) {
59+
const PLAYER_COUNT: usize = 10_000;
60+
const PLAYER_VIEW_DISTANCE: u16 = 32;
61+
62+
let mut worlds = WORLDS.borrow_mut();
63+
let world = worlds.entry(len).or_insert_with(|| generate_world(len));
64+
65+
// let mut world = generate_world(len);
66+
67+
bencher.counter(PLAYER_COUNT).bench_local(move || {
68+
for _ in 0..PLAYER_COUNT {
69+
let start_x = rand::random::<u16>() % (len - PLAYER_VIEW_DISTANCE * 2);
70+
let end_x = start_x + PLAYER_VIEW_DISTANCE * 2;
71+
72+
let start_y = rand::random::<u16>() % (len - PLAYER_VIEW_DISTANCE * 2);
73+
let end_y = start_y + PLAYER_VIEW_DISTANCE * 2;
74+
75+
let res = world.data_range(start_x..end_x, start_y..end_y);
76+
for elem in res {
77+
black_box(elem);
78+
}
79+
}
80+
});
81+
}

0 commit comments

Comments
 (0)