Reduce history system's excessive memory usage from storing copies of images each step (#845)

* Limit saved undo history

* Do not commit path every mouse move event

* Reference count images in history system instead of cloning the image data

* Increase history storage step limit to 100

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
0HyperCube
2022-11-11 11:44:43 -08:00
committed by GitHub
co-authored by Keavon Chambers
parent be353878d0
commit 4cda84521f
10 changed files with 39 additions and 23 deletions
+3
View File
@@ -583,6 +583,7 @@ impl Document {
image_data,
mime,
} => {
let image_data = std::rc::Rc::new(image_data);
let layer = Layer::new(LayerDataType::Image(ImageLayer::new(mime, image_data)), transform);
self.set_layer(&path, layer, insert_index)?;
@@ -606,6 +607,7 @@ impl Document {
Operation::SetNodeGraphFrameImageData { layer_path, image_data } => {
let layer = self.layer_mut(&layer_path).expect("Setting NodeGraphFrame image data for invalid layer");
if let LayerDataType::NodeGraphFrame(node_graph_frame) = &mut layer.data {
let image_data = std::rc::Rc::new(image_data);
node_graph_frame.image_data = Some(crate::layers::nodegraph_layer::ImageData { image_data });
} else {
panic!("Incorrectly trying to set image data for a layer that is not an NodeGraphFrame layer type");
@@ -831,6 +833,7 @@ impl Document {
Operation::ImaginateSetImageData { layer_path, image_data } => {
let layer = self.layer_mut(&layer_path).expect("Setting Imaginate image data for invalid layer");
if let LayerDataType::Imaginate(imaginate) = &mut layer.data {
let image_data = std::rc::Rc::new(image_data);
imaginate.image_data = Some(ImaginateImageData { image_data });
} else {
panic!("Incorrectly trying to set image data for a layer that is not an Imaginate layer type");
+6 -5
View File
@@ -2,20 +2,21 @@
use serde::{Deserialize, Deserializer, Serializer};
pub fn as_base64<T, S>(key: &T, serializer: S) -> Result<S::Ok, S::Error>
pub fn as_base64<S>(key: &std::rc::Rc<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error>
where
T: AsRef<[u8]>,
S: Serializer,
{
serializer.serialize_str(&base64::encode(key.as_ref()))
serializer.serialize_str(&base64::encode(key.as_slice()))
}
pub fn from_base64<'a, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
pub fn from_base64<'a, D>(deserializer: D) -> Result<std::rc::Rc<Vec<u8>>, D::Error>
where
D: Deserializer<'a>,
{
use serde::de::Error;
String::deserialize(deserializer)
.and_then(|string| base64::decode(&string).map_err(|err| Error::custom(err.to_string())))
.and_then(|string| base64::decode(string).map_err(|err| Error::custom(err.to_string())))
.map(std::rc::Rc::new)
.map_err(serde::de::Error::custom)
}
+2 -2
View File
@@ -14,7 +14,7 @@ use std::fmt::Write;
pub struct ImageLayer {
pub mime: String,
#[serde(serialize_with = "base64_serde::as_base64", deserialize_with = "base64_serde::from_base64")]
pub image_data: Vec<u8>,
pub image_data: std::rc::Rc<Vec<u8>>,
// TODO: Have the browser dispose of this blob URL when this is dropped (like when the layer is deleted)
#[serde(skip)]
pub blob_url: Option<String>,
@@ -75,7 +75,7 @@ impl LayerData for ImageLayer {
}
impl ImageLayer {
pub fn new(mime: String, image_data: Vec<u8>) -> Self {
pub fn new(mime: String, image_data: std::rc::Rc<Vec<u8>>) -> Self {
Self {
mime,
image_data,
+1 -1
View File
@@ -53,7 +53,7 @@ pub enum ImaginateStatus {
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
pub struct ImaginateImageData {
#[serde(serialize_with = "base64_serde::as_base64", deserialize_with = "base64_serde::from_base64")]
pub image_data: Vec<u8>,
pub image_data: std::rc::Rc<Vec<u8>>,
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
+1 -1
View File
@@ -29,7 +29,7 @@ pub struct NodeGraphFrameLayer {
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
pub struct ImageData {
#[serde(serialize_with = "base64_serde::as_base64", deserialize_with = "base64_serde::from_base64")]
pub image_data: Vec<u8>,
pub image_data: std::rc::Rc<Vec<u8>>,
}
impl LayerData for NodeGraphFrameLayer {