From db036500650862e55b786167654378bc680a047d Mon Sep 17 00:00:00 2001 From: Fl1tzi Date: Mon, 26 Feb 2024 01:22:02 +0100 Subject: [PATCH] major memory improvement by moving the image cache to fs --- Cargo.toml | 5 +- src/device.rs | 25 ++----- src/image_rendering.rs | 8 ++- src/main.rs | 10 +++ src/modules.rs | 147 +++++++++++++++++++++-------------------- src/modules/blank.rs | 6 +- src/modules/counter.rs | 8 +-- src/modules/image.rs | 27 +++----- src/modules/space.rs | 6 +- 9 files changed, 115 insertions(+), 127 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9fe9511..bc69a6b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,5 +19,6 @@ rusttype = "0.9.3" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } font-loader = "0.11.0" -clru = "0.6.1" -once_cell = "1.19.0" \ No newline at end of file +once_cell = "1.19.0" +ring = "0.17" +base64 = "0.21" diff --git a/src/device.rs b/src/device.rs index a41a72f..6e24bdf 100644 --- a/src/device.rs +++ b/src/device.rs @@ -3,11 +3,9 @@ use crate::{ modules::{start_module, HostEvent, MODULE_REGISTRY}, unwrap_or_error, }; -use clru::CLruCache; use deck_driver as streamdeck; use hidapi::HidApi; -use image::DynamicImage; -use std::{collections::HashMap, fmt::Display, num::NonZeroUsize, sync::Arc}; +use std::{collections::HashMap, fmt::Display, sync::Arc}; use streamdeck::{ asynchronous::{AsyncStreamDeck, ButtonStateUpdate}, info::Kind, @@ -16,10 +14,7 @@ use streamdeck::{ use tokio::{ process::Command, runtime::Runtime, - sync::{ - mpsc::{self, error::TrySendError}, - Mutex, - }, + sync::mpsc::{self, error::TrySendError}, }; use tracing::{debug, error, info_span, trace, warn}; @@ -46,11 +41,6 @@ impl Display for Device { } } -/// image cache -/// -/// (button, key), image data -pub type ImageCache = CLruCache<(u8, u32), Arc>; - /// Handles everything related to a single device pub struct Device { modules: HashMap, @@ -61,7 +51,6 @@ pub struct Device { selected_space: Option, is_dead_handle: Arc>, serial: String, - image_cache: Arc>, } impl Device { @@ -104,9 +93,6 @@ impl Device { selected_space: None, is_dead_handle, serial, - image_cache: Arc::new(Mutex::new(CLruCache::new( - NonZeroUsize::new(button_count.into()).unwrap(), - ))), }) } @@ -147,11 +133,10 @@ impl Device { let ser = self.serial.clone(); let dev = self.device.clone(); let b = btn.clone(); - let image_cache = self.image_cache.clone(); - runtime.spawn(async move { - start_module(ser, b, *module, dev, module_receiver, image_cache).await - }); + runtime.spawn( + async move { start_module(ser, b, *module, dev, module_receiver).await }, + ); } // if the receiver already dropped the listener then just directly insert none. // Optimizes performance because the key_listener just does not try to send the event. diff --git a/src/image_rendering.rs b/src/image_rendering.rs index e643244..8b00df9 100644 --- a/src/image_rendering.rs +++ b/src/image_rendering.rs @@ -5,11 +5,13 @@ use image::imageops; use image::{io::Reader, DynamicImage, ImageBuffer, Rgb, RgbImage}; use imageproc::drawing::draw_text_mut; use rusttype::Scale; -use std::io; +use std::{io, path::Path}; +use tracing::trace; -/// Loads an image from a path +/// Retrieve an image from a path #[allow(dead_code)] -pub fn load_image(path: String) -> io::Result { +pub fn retrieve_image(path: &Path) -> io::Result { + trace!("Retrieving image from filesystem"); Ok(Reader::open(path)? .decode() .expect("Unable to decode image")) diff --git a/src/main.rs b/src/main.rs index a34adc7..0d7cc71 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ use hidapi::HidApi; use rusttype::Font; use std::{ collections::HashMap, + fs, process::exit, sync::{Arc, Mutex, OnceLock}, time::Duration, @@ -24,6 +25,7 @@ mod modules; mod type_definition; pub static GLOBAL_FONT: OnceLock = OnceLock::new(); +pub static CACHE_DIR: &'static str = "microdeck"; #[macro_export] macro_rules! skip_if_none { @@ -64,6 +66,14 @@ fn main() { } }; + // create cache dir + if let Some(mut path) = dirs::cache_dir() { + path.push(CACHE_DIR); + if path.exists() == false { + fs::create_dir(path).expect("Could not create cache directory"); + } + } + // load font let font = match config.global.font_family { Some(ref f) => font_loader::system_fonts::get( diff --git a/src/modules.rs b/src/modules.rs index 91b83f7..e2c0aa8 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -10,21 +10,24 @@ use self::space::Space; // other things use crate::config::{Button, ButtonConfigError}; -use crate::device::ImageCache; -use crate::image_rendering::{load_image, ImageBuilder}; +use crate::image_rendering::{retrieve_image, ImageBuilder}; use ::image::imageops::FilterType; +use ::image::io::Reader as ImageReader; use ::image::DynamicImage; use async_trait::async_trait; +use base64::engine::{general_purpose, Engine}; pub use deck_driver as streamdeck; +use dirs::cache_dir; use futures_util::Future; use once_cell::sync::Lazy; +use ring::digest; use std::collections::HashMap; -use std::{error::Error, pin::Pin, sync::Arc}; +use std::{error::Error, path::PathBuf, pin::Pin, sync::Arc}; use streamdeck::info::ImageFormat; use streamdeck::info::Kind; use streamdeck::AsyncStreamDeck; use streamdeck::StreamDeckError; -use tokio::sync::{mpsc, Mutex}; +use tokio::sync::mpsc; use tracing::{debug, error, trace}; pub static MODULE_REGISTRY: Lazy = Lazy::new(|| ModuleRegistry::default()); @@ -41,7 +44,7 @@ pub enum HostEvent { pub type ModuleObject = Box; pub type ModuleFuture = Pin> + Send>>; -pub type ModuleInitFunction = fn(Arc