Small cache experiments

This commit is contained in:
Imbris 2019-09-22 22:18:09 -04:00
parent debcb11e18
commit f182733074
6 changed files with 191 additions and 7 deletions

22
Cargo.lock generated
View File

@ -93,6 +93,25 @@ dependencies = [
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "arr_macro"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arr_macro_impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "arr_macro_impl"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "arrayref"
version = "0.3.5"
@ -3733,6 +3752,7 @@ dependencies = [
name = "veloren-world"
version = "0.3.0"
dependencies = [
"arr_macro 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"hashbrown 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"minifb 0.12.0 (git+https://github.com/emoon/rust_minifb.git)",
@ -3943,6 +3963,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344"
"checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94"
"checksum approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
"checksum arr_macro 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d262b83f2f573121554ad6e764cd444303df85d86e5fcebc81903ddcf8dd3a97"
"checksum arr_macro_impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8decbe97ffec939e44228d91e5d0829ceb1616c6ed0984c09df164b1e7ebaafc"
"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
"checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14"

View File

@ -12,6 +12,7 @@ hashbrown = { version = "0.6.0", features = ["serde"] }
lazy_static = "1.4.0"
rand = "0.7.2"
rand_chacha = "0.2.1"
arr_macro = "0.1.2"
[dev-dependencies]
minifb = { git = "https://github.com/emoon/rust_minifb.git" }

View File

@ -3,7 +3,7 @@ mod natural;
use crate::{
column::{ColumnGen, ColumnSample},
generator::{Generator, TownGen},
util::{HashCache, RandomField, Sampler, SamplerMut},
util::{RandomField, Sampler, SamplerMut, SmallCache},
World, CONFIG,
};
use common::{
@ -16,7 +16,7 @@ use vek::*;
pub struct BlockGen<'a> {
world: &'a World,
column_cache: HashCache<Vec2<i32>, Option<ColumnSample<'a>>>,
column_cache: SmallCache<Option<ColumnSample<'a>>>,
column_gen: ColumnGen<'a>,
}
@ -24,14 +24,14 @@ impl<'a> BlockGen<'a> {
pub fn new(world: &'a World, column_gen: ColumnGen<'a>) -> Self {
Self {
world,
column_cache: HashCache::with_capacity(64),
column_cache: SmallCache::default(),
column_gen,
}
}
fn sample_column(
column_gen: &ColumnGen<'a>,
cache: &mut HashCache<Vec2<i32>, Option<ColumnSample<'a>>>,
cache: &mut SmallCache<Option<ColumnSample<'a>>>,
wpos: Vec2<i32>,
) -> Option<ColumnSample<'a>> {
cache
@ -41,7 +41,7 @@ impl<'a> BlockGen<'a> {
fn get_cliff_height(
column_gen: &ColumnGen<'a>,
cache: &mut HashCache<Vec2<i32>, Option<ColumnSample<'a>>>,
cache: &mut SmallCache<Option<ColumnSample<'a>>>,
wpos: Vec2<f32>,
close_cliffs: &[(Vec2<i32>, u32); 9],
cliff_hill: f32,

View File

@ -2,7 +2,7 @@ use super::{BlockGen, StructureInfo, StructureMeta};
use crate::{
all::ForestKind,
column::{ColumnGen, ColumnSample},
util::{HashCache, RandomPerm, Sampler, UnitChooser},
util::{RandomPerm, Sampler, SmallCache, UnitChooser},
CONFIG,
};
use common::{assets, terrain::Structure};
@ -17,7 +17,7 @@ static QUIRKY_RAND: RandomPerm = RandomPerm::new(0xA634460F);
pub fn structure_gen<'a>(
column_gen: &ColumnGen<'a>,
column_cache: &mut HashCache<Vec2<i32>, Option<ColumnSample<'a>>>,
column_cache: &mut SmallCache<Option<ColumnSample<'a>>>,
idx: usize,
st_pos: Vec2<i32>,
st_seed: u32,

View File

@ -4,6 +4,7 @@ pub mod hash_cache;
pub mod random;
pub mod sampler;
pub mod seed_expan;
pub mod small_cache;
pub mod structure;
pub mod unit_chooser;
@ -14,6 +15,7 @@ pub use self::{
hash_cache::HashCache,
random::{RandomField, RandomPerm},
sampler::{Sampler, SamplerMut},
small_cache::SmallCache,
structure::StructureGen2d,
unit_chooser::UnitChooser,
};

View File

@ -0,0 +1,159 @@
use arr_macro::arr;
use vek::*;
fn calc_idx(v: Vec2<i32>) -> usize {
let mut x = v.x as u32;
let mut y = v.y as u32;
x = x.wrapping_mul(0x6eed0e9d);
y = y.wrapping_mul(0x2f72b421);
(x ^ y) as usize
}
pub struct SmallCache<V: Default> {
index: [Option<Vec2<i32>>; 137],
data: [V; 137],
random: u32,
}
impl<V: Default> Default for SmallCache<V> {
fn default() -> Self {
Self {
index: arr![None; 137],
data: arr![V::default(); 137],
random: 1,
}
}
}
impl<V: Default> SmallCache<V> {
pub fn get<F: FnOnce(Vec2<i32>) -> V>(&mut self, key: Vec2<i32>, f: F) -> &V {
let idx = calc_idx(key) % 128;
// Search
if self.index[idx].as_ref().map(|k| k == &key).unwrap_or(false) {
return &self.data[idx];
} else if self.index[idx + 1]
.as_ref()
.map(|k| k == &key)
.unwrap_or(false)
{
return &self.data[idx + 1];
} else if self.index[idx + 4]
.as_ref()
.map(|k| k == &key)
.unwrap_or(false)
{
return &self.data[idx + 4];
} else if self.index[idx + 9]
.as_ref()
.map(|k| k == &key)
.unwrap_or(false)
{
return &self.data[idx + 9];
}
// Not present so insert
for i in 0..4 {
let idx = idx + i * i;
if self.index[idx].is_none() {
self.index[idx] = Some(key.clone());
self.data[idx] = f(key);
return &self.data[idx];
}
}
// No space randomly remove someone
let step = super::seed_expan::diffuse(self.random) as usize % 4;
let idx = step * step + idx;
self.random = self.random.wrapping_add(1);
self.index[idx] = Some(key.clone());
self.data[idx] = f(key);
&self.data[idx]
}
}
/*pub struct SmallCache<V: Default> {
index: [Option<Vec2<i32>>; 128],
data: [V; 128],
random: u32,
}
impl<V: Default> Default for SmallCache<V> {
fn default() -> Self {
Self {
index: arr![None; 128],
data: arr![V::default(); 128],
random: 1,
}
}
}
impl<V: Default> SmallCache<V> {
pub fn get<F: FnOnce(Vec2<i32>) -> V>(&mut self, key: Vec2<i32>, f: F) -> &V {
let idx = calc_idx(key) % 32 * 4;
// Search
if self.index[idx].as_ref().map(|k| k == &key).unwrap_or(false) {
return &self.data[idx];
} else if self.index[idx + 1]
.as_ref()
.map(|k| k == &key)
.unwrap_or(false)
{
return &self.data[idx + 1];
} else if self.index[idx + 2]
.as_ref()
.map(|k| k == &key)
.unwrap_or(false)
{
return &self.data[idx + 2];
} else if self.index[idx + 3]
.as_ref()
.map(|k| k == &key)
.unwrap_or(false)
{
return &self.data[idx + 3];
}
// Not present so insert
for i in 0..4 {
let idx = idx + i;
if self.index[idx].is_none() {
self.index[idx] = Some(key.clone());
self.data[idx] = f(key);
return &self.data[idx];
}
}
let idx = idx + super::seed_expan::diffuse(self.random) as usize % 4;
self.random = self.random.wrapping_add(1);
self.index[idx] = Some(key.clone());
self.data[idx] = f(key);
&self.data[idx]
}
}*/
/*const ZCACHE_SIZE: usize = 32;
#[derive(Default)]
pub struct ZestSmallCache<K: Eq + Clone, V: Default> {
index: [Option<K>; ZCACHE_SIZE],
cache: [V; ZCACHE_SIZE],
not_cached: V,
}
impl<K: Eq + Clone, V: Default> ZestSmallCache<K, V> {
pub fn get<F: FnOnce(K) -> V>(&mut self, key: K, cache: bool, f: F) -> &V {
for i in 0..ZCACHE_SIZE {
if self.index[i].as_ref().map(|k| k == &key).unwrap_or(false) {
return &self.cache[i];
}
}
if !cache {
self.not_cached = f(key);
return &self.not_cached;
}
for i in 0..ZCACHE_SIZE {
if self.index[i].is_none() {
self.index[i] = Some(key.clone());
self.cache[i] = f(key.clone());
return &self.cache[i];
}
}
self.index[0] = Some(key.clone());
self.cache[0] = f(key);
&self.cache[0]
}
}*/