Optimization ChunkNoiseFunctionComponent (#1037)

* feat(chunk): optimize heap allocations of destiny function

* refactor: applied `cargo fmt` and linting error

* fix(benches): fix lint errors
This commit is contained in:
LCW
2025-07-10 17:30:14 +09:00
committed by GitHub
parent ef658a906d
commit b1098bfbc1
3 changed files with 101 additions and 17 deletions

View File

@@ -70,3 +70,7 @@ harness = false
[[bench]]
name = "chunk_gen"
harness = false
[[bench]]
name = "noise_router"
harness = false

View File

@@ -0,0 +1,34 @@
use criterion::{Criterion, criterion_group, criterion_main};
use pumpkin_data::noise_router::OVERWORLD_BASE_NOISE_ROUTER;
use pumpkin_world::generation::{
GlobalRandomConfig,
noise_router::{
chunk_density_function::ChunkNoiseFunctionBuilderOptions,
chunk_noise_router::ChunkNoiseRouter, proto_noise_router::ProtoNoiseRouters,
},
};
use std::hint::black_box;
fn bench_noise_router_creation(c: &mut Criterion) {
let base_routers = &OVERWORLD_BASE_NOISE_ROUTER;
let random_config = GlobalRandomConfig::new(0, false);
let proto_routers = ProtoNoiseRouters::generate(base_routers, &random_config);
let proto_noise_router = proto_routers.noise;
let builder_options = ChunkNoiseFunctionBuilderOptions::new(4, 8, 4, 4, 0, 0, 3);
// Benchmarking
c.bench_function("noise_router_creation_with_pooling", |b| {
b.iter(|| {
let router = ChunkNoiseRouter::generate(
black_box(&proto_noise_router),
black_box(&builder_options),
);
black_box(router);
})
});
}
criterion_group!(benches, bench_noise_router_creation);
criterion_main!(benches);

View File

@@ -1,3 +1,4 @@
use std::cell::RefCell;
use std::mem;
use super::{
@@ -9,6 +10,36 @@ use pumpkin_util::math::{lerp, lerp3, vector2::Vector2};
use crate::generation::{biome_coords, positions::chunk_pos};
thread_local! {
static F64_BUFFER_POOL: RefCell<Vec<Vec<f64>>> = const {
RefCell::new(Vec::new())
};
}
#[inline]
fn get_buffer(len: usize) -> Box<[f64]> {
F64_BUFFER_POOL.with(|pool| {
let mut buffers = pool.borrow_mut();
if let Some(mut buf) = buffers.pop() {
if buf.len() != len {
buf.resize(len, 0.0);
} else {
buf.fill(0.0);
}
buf.into_boxed_slice()
} else {
vec![0.0; len].into_boxed_slice()
}
})
}
#[inline]
fn recycle_buffer(buf: Box<[f64]>) {
F64_BUFFER_POOL.with(|pool| {
pool.borrow_mut().push(Vec::from(buf));
});
}
pub struct WrapperData {
// Our relative position within the cell
pub(crate) cell_x_block_position: usize,
@@ -136,18 +167,14 @@ impl DensityInterpolator {
// These are all dummy values to be populated when sampling values
Self {
input_index,
start_buffer: vec![
0.0;
start_buffer: get_buffer(
(builder_options.vertical_cell_count + 1)
* (builder_options.horizontal_cell_count + 1)
]
.into_boxed_slice(),
end_buffer: vec![
0.0;
* (builder_options.horizontal_cell_count + 1),
),
end_buffer: get_buffer(
(builder_options.vertical_cell_count + 1)
* (builder_options.horizontal_cell_count + 1)
]
.into_boxed_slice(),
* (builder_options.horizontal_cell_count + 1),
),
first_pass: Default::default(),
second_pass: Default::default(),
third_pass: Default::default(),
@@ -214,6 +241,19 @@ impl DensityInterpolator {
}
}
impl Drop for DensityInterpolator {
fn drop(&mut self) {
recycle_buffer(std::mem::replace(
&mut self.start_buffer,
Vec::new().into_boxed_slice(),
));
recycle_buffer(std::mem::replace(
&mut self.end_buffer,
Vec::new().into_boxed_slice(),
));
}
}
impl MutableChunkNoiseFunctionComponentImpl for DensityInterpolator {
fn sample(
&mut self,
@@ -336,6 +376,15 @@ impl MutableChunkNoiseFunctionComponentImpl for FlatCache {
}
}
impl Drop for FlatCache {
fn drop(&mut self) {
recycle_buffer(std::mem::replace(
&mut self.cache,
Vec::new().into_boxed_slice(),
));
}
}
impl FlatCache {
pub fn new(
input_index: usize,
@@ -347,8 +396,7 @@ impl FlatCache {
) -> Self {
Self {
input_index,
cache: vec![0.0; (horizontal_biome_end + 1) * (horizontal_biome_end + 1)]
.into_boxed_slice(),
cache: get_buffer((horizontal_biome_end + 1) * (horizontal_biome_end + 1)),
start_biome_x,
start_biome_z,
horizontal_biome_end,
@@ -589,13 +637,11 @@ impl CellCache {
) -> Self {
Self {
input_index,
cache: vec![
0.0;
cache: get_buffer(
build_options.horizontal_cell_block_count
* build_options.horizontal_cell_block_count
* build_options.vertical_cell_block_count
]
.into_boxed_slice(),
* build_options.vertical_cell_block_count,
),
min_value,
max_value,
}