Invalidate Caches based on the received input (#1067)
* Invalidate Caches based on the received input * Add comments * Fix missing *
This commit is contained in:
parent
ccb698ffa8
commit
4ea3802df1
|
|
@ -359,6 +359,12 @@ dependencies = [
|
|||
"dyn-any",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "boxcar"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38c99613cb3cd7429889a08dfcf651721ca971c86afa30798461f8eee994de47"
|
||||
|
||||
[[package]]
|
||||
name = "brotli"
|
||||
version = "3.3.4"
|
||||
|
|
@ -1663,6 +1669,7 @@ dependencies = [
|
|||
"autoquant",
|
||||
"bezier-rs",
|
||||
"borrow_stack",
|
||||
"boxcar",
|
||||
"bytemuck",
|
||||
"compilation-client",
|
||||
"dyn-any",
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ quantization = ["autoquant"]
|
|||
|
||||
[dependencies]
|
||||
autoquant = { git = "https://github.com/truedoctor/autoquant", optional = true, features = ["fitting"] }
|
||||
graphene-core = {path = "../gcore", features = ["async", "std" ], default-features = false}
|
||||
graphene-core = {path = "../gcore", features = ["async", "std", "serde" ], default-features = false}
|
||||
borrow_stack = {path = "../borrow_stack"}
|
||||
dyn-any = {path = "../../libraries/dyn-any", features = ["derive"]}
|
||||
graph-craft = {path = "../graph-craft"}
|
||||
|
|
@ -38,12 +38,13 @@ image = "*"
|
|||
dyn-clone = "1.0"
|
||||
|
||||
log = "0.4"
|
||||
bezier-rs = { path = "../../libraries/bezier-rs" }
|
||||
bezier-rs = { path = "../../libraries/bezier-rs" , features = ["serde"] }
|
||||
kurbo = { git = "https://github.com/linebender/kurbo.git", features = [
|
||||
"serde",
|
||||
] }
|
||||
glam = { version = "0.22", features = ["serde"] }
|
||||
node-macro = { path="../node-macro" }
|
||||
boxcar = "0.1.0"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
|
|
|
|||
|
|
@ -1,50 +1,77 @@
|
|||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use graphene_core::Node;
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
/// Caches the output of a given Node and acts as a proxy
|
||||
#[derive(Default)]
|
||||
pub struct CacheNode<T> {
|
||||
cache: OnceCell<T>,
|
||||
// We have to use an append only data structure to make sure the references
|
||||
// to the cache entries are always valid
|
||||
cache: boxcar::Vec<(u64, T)>,
|
||||
}
|
||||
impl<'i, T: 'i> Node<'i, T> for CacheNode<T> {
|
||||
impl<'i, T: 'i + Hash> Node<'i, T> for CacheNode<T> {
|
||||
type Output = &'i T;
|
||||
fn eval<'s: 'i>(&'s self, input: T) -> Self::Output {
|
||||
self.cache.get_or_init(|| {
|
||||
trace!("Creating new cache node");
|
||||
input
|
||||
})
|
||||
let mut hasher = DefaultHasher::new();
|
||||
input.hash(&mut hasher);
|
||||
let hash = hasher.finish();
|
||||
|
||||
if let Some((_, cached_value)) = self.cache.iter().find(|(h, _)| *h == hash) {
|
||||
return cached_value;
|
||||
} else {
|
||||
trace!("Cache miss");
|
||||
let index = self.cache.push((hash, input));
|
||||
return &self.cache[index].1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CacheNode<T> {
|
||||
pub const fn new() -> CacheNode<T> {
|
||||
CacheNode { cache: OnceCell::new() }
|
||||
pub fn new() -> CacheNode<T> {
|
||||
CacheNode { cache: boxcar::Vec::new() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Caches the output of a given Node and acts as a proxy
|
||||
/// It provides two modes of operation, it can either be set
|
||||
/// when calling the node with a `Some<T>` variant or the last
|
||||
/// value that was added is returned when calling it with `None`
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
pub struct LetNode<T> {
|
||||
cache: OnceCell<T>,
|
||||
// We have to use an append only data structure to make sure the references
|
||||
// to the cache entries are always valid
|
||||
// TODO: We only ever access the last value so there is not really a reason for us
|
||||
// to store the previous entries. This should be reworked in the future
|
||||
cache: boxcar::Vec<(u64, T)>,
|
||||
}
|
||||
impl<'i, T: 'i> Node<'i, Option<T>> for LetNode<T> {
|
||||
impl<'i, T: 'i + Hash> Node<'i, Option<T>> for LetNode<T> {
|
||||
type Output = &'i T;
|
||||
fn eval<'s: 'i>(&'s self, input: Option<T>) -> Self::Output {
|
||||
match input {
|
||||
Some(input) => {
|
||||
self.cache.set(input).unwrap_or_else(|_| error!("Let node was set twice but is not mutable"));
|
||||
self.cache.get().unwrap()
|
||||
let mut hasher = DefaultHasher::new();
|
||||
input.hash(&mut hasher);
|
||||
let hash = hasher.finish();
|
||||
|
||||
if let Some((cached_hash, cached_value)) = self.cache.iter().last() {
|
||||
if hash == *cached_hash {
|
||||
return cached_value;
|
||||
}
|
||||
}
|
||||
trace!("Cache miss");
|
||||
let index = self.cache.push((hash, input));
|
||||
return &self.cache[index].1;
|
||||
}
|
||||
None => self.cache.get().expect("Let node was not initialized"),
|
||||
None => &self.cache.iter().last().expect("Let node was not initialized").1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> LetNode<T> {
|
||||
pub const fn new() -> LetNode<T> {
|
||||
LetNode { cache: OnceCell::new() }
|
||||
pub fn new() -> LetNode<T> {
|
||||
LetNode { cache: boxcar::Vec::new() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue