Skip to content

Commit

Permalink
memory_leak test and fix icons hashmap
Browse files Browse the repository at this point in the history
  • Loading branch information
emanuele-em committed Nov 6, 2023
1 parent 8e22c06 commit cb36109
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ tokio-util = { version = "0.7.8", features = ["codec"] }
futures-util = { version = "0.3.28", features = ["sink"] }

sysinfo = "0.29.10"
base64 = "0.21.5"
data-encoding = "2.4.0"

# [patch.crates-io]
# tokio = { path = "../tokio/tokio" }
Expand Down
4 changes: 2 additions & 2 deletions benches/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn criterion_benchmark(c: &mut Criterion) {
"/System/Library/CoreServices/Finder.app/Contents/MacOS/Finder",
);

c.bench_function("get png with system", |b| {
c.bench_function("get_png", |b| {
b.iter(|| {
icons::IconCache::default()
.get_png(test_app.clone())
Expand All @@ -62,7 +62,7 @@ fn criterion_benchmark(c: &mut Criterion) {
});

let mut cache = icons::IconCache::default();
c.bench_function("get_png with system", |b| {
c.bench_function("get_png (cached)", |b| {
b.iter(|| {
cache.get_png(test_app.clone()).unwrap();
})
Expand Down
48 changes: 29 additions & 19 deletions src/macos/icons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,33 +29,33 @@ impl IconCache {
Ok(self.icons.get(e.get()).unwrap())
}
Entry::Vacant(e) => {
let tif = unsafe { tif_data_for_executable(e.key())? };
let icon = tif_to_png(&tif)?;
let tiff = unsafe { tiff_data_for_executable(e.key())? };
let mut hasher = DefaultHasher::new();
icon.hash(&mut hasher);
let icon_hash = hasher.finish();
e.insert(icon_hash);
let icon = self.icons.entry(icon_hash).or_insert(icon);
tiff.hash(&mut hasher);
let tiff_hash = hasher.finish();
let icon = self.icons.entry(tiff_hash).or_insert_with(||
tiff_to_png(&tiff)
);
Ok(icon)
}
}
}
}

pub fn tif_to_png(tif: &[u8]) -> Result<Vec<u8>> {
let tif_image = image::load_from_memory(tif)?;
pub fn tiff_to_png(tiff: &[u8]) -> Vec<u8> {
let tiff_image = image::load_from_memory(tiff).unwrap();
let mut png_image: Vec<u8> = Vec::new();
let encoder = image::codecs::png::PngEncoder::new(&mut png_image);
encoder.write_image(
tif_image.as_rgba8().unwrap(),
tif_image.width(),
tif_image.height(),
tiff_image.as_rgba8().unwrap(),
tiff_image.width(),
tiff_image.height(),
image::ColorType::Rgba8,
)?;
Ok(png_image)
).unwrap();
png_image
}

unsafe fn tif_data_for_executable(executable: &Path) -> Result<Vec<u8>> {
unsafe fn tiff_data_for_executable(executable: &Path) -> Result<Vec<u8>> {
let mut sys = System::new();
sys.refresh_processes_specifics(ProcessRefreshKind::new());
for (pid, process) in sys.processes() {
Expand All @@ -67,9 +67,9 @@ unsafe fn tif_data_for_executable(executable: &Path) -> Result<Vec<u8>> {
];
if !app.is_null() {
let img: id = msg_send![app, icon];
let tif: id = msg_send![img, TIFFRepresentation];
let length: usize = msg_send![tif, length];
let bytes: *const u8 = msg_send![tif, bytes];
let tiff: id = msg_send![img, TIFFRepresentation];
let length: usize = msg_send![tiff, length];
let bytes: *const u8 = msg_send![tiff, bytes];
let data = std::slice::from_raw_parts(bytes, length).to_vec();
return Ok(data);
}
Expand All @@ -81,7 +81,7 @@ unsafe fn tif_data_for_executable(executable: &Path) -> Result<Vec<u8>> {
#[cfg(test)]
mod tests {
use super::*;
use base64::{engine::general_purpose, Engine as _};
use data_encoding::BASE64;

#[test]
fn png() {
Expand All @@ -90,7 +90,17 @@ mod tests {
let vec = icon_cache.get_png(path).unwrap();
assert!(!vec.is_empty());
dbg!(vec.len());
let base64_png = general_purpose::STANDARD.encode(vec);
let base64_png = BASE64.encode(vec);
dbg!(base64_png);
}

#[ignore]
#[test]
fn memory_leak() {
let path = PathBuf::from("/System/Library/CoreServices/Finder.app/Contents/MacOS/Finder");
for _ in 0..500 {
_ = unsafe { &tiff_data_for_executable(&path) };
}
}

}

0 comments on commit cb36109

Please sign in to comment.