Skip to content

Comments

Use Smol#35

Merged
NoahR02 merged 5 commits intomainfrom
feature/smol
Jul 11, 2025
Merged

Use Smol#35
NoahR02 merged 5 commits intomainfrom
feature/smol

Conversation

@NoahR02
Copy link
Collaborator

@NoahR02 NoahR02 commented Jul 10, 2025

Experiment: Use Smol to reduce heap allocations

Two different scenarios were measured for the tour example:

  1. The memory usage on the first render
  2. The memory usage n frames later (this should be about the same across frames)

Three different scenarios were measured for the 10k rows example:

  1. The memory usage on the first render
  2. The memory usage n frames later (this should be about the same across frames)
  3. The memory usage after generating 10k rows

Usability (as a user):

SmolString is invisible to the user in the view due to impl Into being used and the experience is better than before. In update however the usage is slightly worse when getting a target's id and storing it because you have to call .into().

Results (Summary):

Tour Measurements

TOUR EXAMPLE STARTING FRAME N FRAMES LATER
Without Smol allocations: 2991, bytes allocated: 1182586 allocations: 1903, bytes allocated: 818369
With Smol allocations: 2935, bytes allocated: 1181426 allocations: 1848, bytes allocated: 817833
Memory Saved Diff (bytes) 1160 bytes and 167.04 KB across 144 frames 536 bytes and 77.184 KB across 144 frames

10k Rows Measurements

10k Rows Example STARTING FRAME N FRAMES LATER 10K ROWS CLICKED AND SHOWING
Without Smol allocations: 2051, bytes allocated: 570760 allocations: 1338, bytes allocated: 392832 allocations: 751489, bytes allocated: 345547457
With Smol allocations: 2022, bytes allocated: 570357 allocations: 1309, bytes allocated: 392429 allocations: 661651, bytes allocated: 344849956
Memory Saved Diff (bytes) 403 bytes and 58.032 KB across 144 frames 403 bytes and 58.032 KB across 144 frames 697501 bytes and 100.440144 MB across 144 frames

How to Measure:

https://github.com/neoeinstein/stats_alloc

Clone down craft with the smol changes in one directory and then clone it down without the changes in another directory and then for each directory: save the following to a patch file and git apply the patch file at the root:

diff --git a/Cargo.lock b/Cargo.lock
index 8c544e3..505ebe6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -823,6 +823,7 @@ dependencies = [
  "rustc-hash 2.1.1",
  "smallvec",
  "smol_str 0.3.2",
+ "stats_alloc",
  "syntect",
  "taffy",
  "tinyvg-rs",
@@ -3705,6 +3706,12 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 
+[[package]]
+name = "stats_alloc"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c0e04424e733e69714ca1bbb9204c1a57f09f5493439520f9f68c132ad25eec"
+
 [[package]]
 name = "strict-num"
 version = "0.1.1"
diff --git a/crates/craft_core/Cargo.toml b/crates/craft_core/Cargo.toml
index 06a39d2..f193422 100644
--- a/crates/craft_core/Cargo.toml
+++ b/crates/craft_core/Cargo.toml
@@ -30,6 +30,7 @@ default = ["clipboard", "accesskit"]
 [dependencies]
 craft_logging = { path = "../craft_logger", version = "0.1.0" }
 
+stats_alloc = "0.1.10"
 smol_str = "0.3.2"
 
 [dependencies.cfg-if]
diff --git a/crates/craft_core/src/app.rs b/crates/craft_core/src/app.rs
index 85d5491..4329c4d 100644
--- a/crates/craft_core/src/app.rs
+++ b/crates/craft_core/src/app.rs
@@ -59,6 +59,15 @@ use craft_resource_manager::resource_type::ResourceType;
 use crate::animations::animation::{AnimationFlags};
 use crate::events::update_queue_entry::UpdateQueueEntry;
 
+extern crate stats_alloc;
+
+use stats_alloc::{StatsAlloc, Region, INSTRUMENTED_SYSTEM};
+use std::alloc::System;
+use std::process;
+
+#[global_allocator]
+static GLOBAL: &StatsAlloc<System> = &INSTRUMENTED_SYSTEM;
+
 macro_rules! get_tree {
         ($self:expr, $is_dev_tree:expr) => {{
             if !$is_dev_tree {
@@ -308,6 +317,8 @@ impl App {
     }
 
     fn on_request_redraw_internal(&mut self) {
+        let reg = Region::new(&GLOBAL);
+
         if self.window.is_none() {
             return;
         }
@@ -414,6 +425,8 @@ impl App {
         }
 
         self.view_introspection();
+        println!("Per-frame Allocations: {:#?}", reg.change());
+        // process::exit(0);
     }
 
     pub fn on_pointer_scroll(&mut self, pointer_scroll_update: PointerScrollUpdate) {

Results:

10k rows (WITHOUT Smol):

STARTING FRAME:

Per-frame Allocations: Stats {

  allocations: 2051,

  deallocations: 1207,

  reallocations: 493,

  bytes_allocated: 570760,

  bytes_deallocated: 339710,

  bytes_reallocated: 121657,

}

N FRAMES LATER:

Per-frame Allocations: Stats {

  allocations: 1338,

  deallocations: 1336,

  reallocations: 206,

  bytes_allocated: 392832,

  bytes_deallocated: 392272,

  bytes_reallocated: 71448,

}

10K ROWS CLICKED AND SHOWING:

Per-frame Allocations: Stats {

  allocations: 751489,

  deallocations: 751487,

  reallocations: 60762,

  bytes_allocated: 345547457,

  bytes_deallocated: 345546897,

  bytes_reallocated: 119599883,

}


10k rows (WITH Smol):

STARTING FRAME:

Per-frame Allocations: Stats {

  allocations: 2022,

  deallocations: 1206,

  reallocations: 493,

  bytes_allocated: 570357,

  bytes_deallocated: 339618,

  bytes_reallocated: 121657,

}

N FRAMES LATER:

Per-frame Allocations: Stats {

  allocations: 1309,

  deallocations: 1307,

  reallocations: 206,

  bytes_allocated: 392429,

  bytes_deallocated: 391869,

  bytes_reallocated: 71448,

}

10K ROWS CLICKED AND SHOWING:

Per-frame Allocations: Stats {

  allocations: 661651,

  deallocations: 661649,

  reallocations: 60762,

  bytes_allocated: 344849956,

  bytes_deallocated: 344849396,

  bytes_reallocated: 119599663,

}


Tour (WITHOUT Smol):

STARTING FRAME:

Per-frame Allocations: Stats {

  allocations: 2991,

  deallocations: 1715,

  reallocations: 963,

  bytes_allocated: 1182586,

  bytes_deallocated: 707643,

  bytes_reallocated: 407916,

}

N FRAMES LATER:

Per-frame Allocations: Stats {

  allocations: 1903,

  deallocations: 1901,

  reallocations: 484,

  bytes_allocated: 818369,

  bytes_deallocated: 817809,

  bytes_reallocated: 325752,

}


Tour (WITH Smol):

STARTING FRAME:

Per-frame Allocations: Stats {

  allocations: 2935,

  deallocations: 1714,

  reallocations: 963,

  bytes_allocated: 1181426,

  bytes_deallocated: 707560,

  bytes_reallocated: 407916,

}

N FRAMES LATER:

Per-frame Allocations: Stats {

  allocations: 1848,

  deallocations: 1846,

  reallocations: 484,

  bytes_allocated: 817833,

  bytes_deallocated: 817273,

  bytes_reallocated: 325752,

}

@NoahR02 NoahR02 merged commit 2a36c00 into main Jul 11, 2025
6 checks passed
@NoahR02 NoahR02 deleted the feature/smol branch July 13, 2025 02:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants