From 6faff2e349afbbbadff27eabb770580bea31c3ae Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 3 Jun 2024 20:23:01 +0200 Subject: [PATCH] Cache now correctly hashed the data The cache previously used the subject ID as the key. However, the data is prone to change, and it is now checked for updates. --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/data/structs.rs | 34 ++++++++++++++++++++++++++++++++++ src/simulator/cache.rs | 20 +++++++++++++++----- src/simulator/mod.rs | 4 ++-- 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 12adf67..dcde9dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -813,7 +813,7 @@ dependencies = [ [[package]] name = "pharmsol" -version = "0.1.13" +version = "0.1.14" dependencies = [ "anyhow", "argmin", diff --git a/Cargo.toml b/Cargo.toml index e131aed..ccd0e83 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pharmsol" -version = "0.1.13" +version = "0.1.14" edition = "2021" authors = [ "Julián D. Otálvaro ", diff --git a/src/data/structs.rs b/src/data/structs.rs index c40c4ae..ebf3fd8 100644 --- a/src/data/structs.rs +++ b/src/data/structs.rs @@ -1,5 +1,6 @@ use crate::data::*; use serde::Deserialize; +use std::hash::{DefaultHasher, Hash, Hasher}; use std::{collections::HashMap, fmt}; /// [Data] is a collection of [Subject]s, which are collections of [Occasion]s, which are collections of [Event]s @@ -133,6 +134,39 @@ impl Subject { pub fn id(&self) -> &String { &self.id } + + // Hasher for subject + pub fn hash(&self) -> u64 { + let mut hasher = DefaultHasher::new(); + + // Hash the subject ID + self.id().hash(&mut hasher); + + // Hash each occasion + for occasion in &self.occasions() { + occasion.index().hash(&mut hasher); + for event in &occasion.events { + match event { + Event::Observation(observation) => { + observation.time().to_bits().hash(&mut hasher); + observation.value().to_bits().hash(&mut hasher); + observation.outeq().hash(&mut hasher); + } + Event::Infusion(infusion) => { + infusion.time().to_bits().hash(&mut hasher); + infusion.duration().to_bits().hash(&mut hasher); + infusion.amount().to_bits().hash(&mut hasher); + } + Event::Bolus(bolus) => { + bolus.time().to_bits().hash(&mut hasher); + bolus.amount().to_bits().hash(&mut hasher); + } + } + } + } + + hasher.finish() + } } /// An [Occasion] is a collection of events, for a given [Subject], that are from a specific occasion diff --git a/src/simulator/cache.rs b/src/simulator/cache.rs index 723bc7f..2ef3900 100644 --- a/src/simulator/cache.rs +++ b/src/simulator/cache.rs @@ -1,3 +1,4 @@ +use crate::data::Subject; use crate::simulator::likelihood::SubjectPredictions; use dashmap::DashMap; use lazy_static::lazy_static; @@ -8,12 +9,21 @@ const CACHE_SIZE: usize = 10000; #[derive(Clone, Debug, PartialEq, Hash)] struct CacheKey { - subject: String, + subject: SubjectHash, support_point: SupportPointHash, } impl Eq for CacheKey {} +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +struct SubjectHash(u64); + +impl SubjectHash { + fn new(subject: &Subject) -> Self { + SubjectHash(subject.hash()) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] struct SupportPointHash(u64); @@ -33,9 +43,9 @@ lazy_static! { static ref CACHE: DashMap = DashMap::with_capacity(CACHE_SIZE); } -pub(crate) fn get_entry(subject: &str, support_point: &Vec) -> Option { +pub(crate) fn get_entry(subject: &Subject, support_point: &Vec) -> Option { let cache_key = CacheKey { - subject: subject.to_owned(), + subject: SubjectHash::new(subject), support_point: SupportPointHash::new(support_point), }; @@ -46,12 +56,12 @@ pub(crate) fn get_entry(subject: &str, support_point: &Vec) -> Option, predictions: SubjectPredictions, ) { let cache_key = CacheKey { - subject: subject.to_owned(), + subject: SubjectHash::new(subject), support_point: SupportPointHash::new(support_point), }; diff --git a/src/simulator/mod.rs b/src/simulator/mod.rs index 14b1773..883b9ad 100644 --- a/src/simulator/mod.rs +++ b/src/simulator/mod.rs @@ -71,7 +71,7 @@ impl Equation { let mut yout = vec![]; for occasion in subject.occasions() { // Check for a cache entry - let pred = get_entry(subject.id(), support_point); + let pred = get_entry(subject, support_point); if let Some(pred) = pred { return pred; } @@ -119,7 +119,7 @@ impl Equation { } // Insert the cache entry let pred: SubjectPredictions = yout.into(); - insert_entry(subject.id(), support_point, pred.clone()); + insert_entry(subject, support_point, pred.clone()); pred } #[inline(always)]