pub struct StatsBump { /* private fields */ }Expand description
Bump arena with instrumentation. Auto-grows like GrowableBump.
Implementations§
Source§impl StatsBump
impl StatsBump
Sourcepub fn new() -> Self
pub fn new() -> Self
New arena with a 4 KiB initial chunk.
Examples found in repository?
examples/perf_features.rs (line 139)
52fn main() -> io::Result<()> {
53 let canon = SIZES[SIZES.len() - 1];
54
55 let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
56 .join("..")
57 .join(".subms")
58 .join("features")
59 .join("rust.json");
60 let existing = std::fs::read_to_string(&path).unwrap_or_default();
61 let mut manifest = SubMsFeatureManifest::load_str("rust", &existing);
62 // Stamp the box these numbers came from. The bench runs wherever it is
63 // invoked, so an unstamped manifest is indistinguishable from a fleet
64 // capture; the renderer will not publish one it cannot attribute.
65 let (source, instance) = SubMsP99Source::from_env();
66 manifest.set_p99_source(source, instance.as_deref());
67
68 // ---------- typed: one Copy type, slot handles, reuse on free ----------
69 #[cfg(feature = "typed")]
70 {
71 use subms_arena_allocator::TypedArena;
72 let sweep: Vec<(usize, u64)> = SIZES
73 .iter()
74 .map(|&n| {
75 let mut arena: TypedArena<u64> = TypedArena::with_capacity(n);
76 let (p50, _) = run_p50_p99(n, |i| {
77 std::hint::black_box(arena.alloc(i as u64));
78 });
79 (n, p50)
80 })
81 .collect();
82 let (cat, reason) = classify_feature(&sweep, None, None);
83
84 let mut arena: TypedArena<u64> = TypedArena::with_capacity(canon);
85 let (_, alloc99) = run_p50_p99(canon, |i| {
86 std::hint::black_box(arena.alloc(i as u64));
87 });
88 // Every timed op here takes the slot the previous one freed, so the
89 // reuse path is what is measured rather than the append path.
90 let mut churn: TypedArena<u64> = TypedArena::with_capacity(2);
91 let (_, free99) = run_p50_p99(canon, |i| {
92 let slot = churn.alloc(i as u64);
93 churn.free(slot);
94 });
95 let mut p99 = BTreeMap::new();
96 p99.insert("alloc".to_string(), alloc99);
97 p99.insert("free".to_string(), free99);
98 manifest.set_feature("typed", cat, &p99, &reason);
99 }
100
101 // ---------- growable: a new chunk when the active one runs out ----------
102 #[cfg(feature = "growable")]
103 {
104 use subms_arena_allocator::GrowableBump;
105 let sweep: Vec<(usize, u64)> = SIZES
106 .iter()
107 .map(|&n| {
108 let mut a = GrowableBump::new();
109 let (p50, _) = run_p50_p99(n, |i| {
110 std::hint::black_box(a.alloc_copy(i as u64));
111 });
112 (n, p50)
113 })
114 .collect();
115 let (cat, reason) = classify_feature(&sweep, None, None);
116
117 let mut a = GrowableBump::new();
118 let (_, alloc99) = run_p50_p99(canon, |i| {
119 std::hint::black_box(a.alloc_copy(i as u64));
120 });
121 let mut filled = GrowableBump::new();
122 for i in 0..canon {
123 filled.alloc_copy(i as u64);
124 }
125 let (_, reset99) = run_p50_p99(1, |_| filled.reset());
126 let mut p99 = BTreeMap::new();
127 p99.insert("alloc".to_string(), alloc99);
128 p99.insert("reset".to_string(), reset99);
129 manifest.set_feature("growable", cat, &p99, &reason);
130 }
131
132 // ---------- stats: live counters on the alloc path ----------
133 #[cfg(feature = "stats")]
134 {
135 use subms_arena_allocator::StatsBump;
136 let sweep: Vec<(usize, u64)> = SIZES
137 .iter()
138 .map(|&n| {
139 let mut a = StatsBump::new();
140 let (p50, _) = run_p50_p99(n, |i| {
141 std::hint::black_box(a.alloc_copy(i as u64));
142 });
143 (n, p50)
144 })
145 .collect();
146 let (cat, reason) = classify_feature(&sweep, None, None);
147
148 let mut a = StatsBump::new();
149 let (_, alloc99) = run_p50_p99(canon, |i| {
150 std::hint::black_box(a.alloc_copy(i as u64));
151 });
152 let (_, snap99) = run_p50_p99(canon, |_| {
153 std::hint::black_box(a.stats());
154 });
155 let mut p99 = BTreeMap::new();
156 p99.insert("alloc".to_string(), alloc99);
157 p99.insert("stats".to_string(), snap99);
158 manifest.set_feature("stats", cat, &p99, &reason);
159 }
160
161 // ---------- aligned: explicit per-allocation alignment ----------
162 #[cfg(feature = "aligned")]
163 {
164 use subms_arena_allocator::AlignedBump;
165 let sweep: Vec<(usize, u64)> = SIZES
166 .iter()
167 .map(|&n| {
168 let mut a = AlignedBump::with_capacity(n * 16 + 4096);
169 let (p50, _) = run_p50_p99(n, |_| {
170 std::hint::black_box(a.alloc_aligned(8, 8).len());
171 });
172 (n, p50)
173 })
174 .collect();
175 let (cat, reason) = classify_feature(&sweep, None, None);
176
177 let mut a = AlignedBump::with_capacity(canon * 16 + 4096);
178 let (_, alloc99) = run_p50_p99(canon, |_| {
179 std::hint::black_box(a.alloc_aligned(8, 8).len());
180 });
181 let mut p99 = BTreeMap::new();
182 p99.insert("alloc_aligned".to_string(), alloc99);
183 manifest.set_feature("aligned", cat, &p99, &reason);
184 }
185
186 std::fs::create_dir_all(path.parent().unwrap())?;
187 std::fs::write(&path, manifest.to_json())?;
188 io::stdout().write_all(manifest.to_json().as_bytes())?;
189 Ok(())
190}Sourcepub fn with_capacity(initial: usize) -> Self
pub fn with_capacity(initial: usize) -> Self
New arena with the requested initial chunk size.
Examples found in repository?
examples/sample_app.rs (line 180)
177fn stats_sizing() {
178 use subms_arena_allocator::StatsBump;
179 println!("\n== stats: size the arena from real load ==");
180 let mut scratch = StatsBump::with_capacity(4096);
181 for _tick in 0..1_000 {
182 for i in 0..8u64 {
183 scratch.alloc_copy(Level {
184 price_ticks: 10_000 + i,
185 qty: 1,
186 });
187 }
188 scratch.reset();
189 }
190 let s = scratch.stats();
191 println!(
192 " {} allocs over 1000 ticks, peak {}B, wasted {}B",
193 s.allocations, s.peak_bytes, s.bytes_wasted,
194 );
195 assert_eq!(s.allocations, 8_000, "counters survive reset");
196 assert!(s.peak_bytes > 0, "peak recorded");
197}Sourcepub fn alloc_copy<T: Copy>(&mut self, value: T) -> &mut T
pub fn alloc_copy<T: Copy>(&mut self, value: T) -> &mut T
Allocate a Copy value. Updates the counters.
Examples found in repository?
examples/sample_app.rs (lines 183-186)
177fn stats_sizing() {
178 use subms_arena_allocator::StatsBump;
179 println!("\n== stats: size the arena from real load ==");
180 let mut scratch = StatsBump::with_capacity(4096);
181 for _tick in 0..1_000 {
182 for i in 0..8u64 {
183 scratch.alloc_copy(Level {
184 price_ticks: 10_000 + i,
185 qty: 1,
186 });
187 }
188 scratch.reset();
189 }
190 let s = scratch.stats();
191 println!(
192 " {} allocs over 1000 ticks, peak {}B, wasted {}B",
193 s.allocations, s.peak_bytes, s.bytes_wasted,
194 );
195 assert_eq!(s.allocations, 8_000, "counters survive reset");
196 assert!(s.peak_bytes > 0, "peak recorded");
197}More examples
examples/perf_features.rs (line 141)
52fn main() -> io::Result<()> {
53 let canon = SIZES[SIZES.len() - 1];
54
55 let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
56 .join("..")
57 .join(".subms")
58 .join("features")
59 .join("rust.json");
60 let existing = std::fs::read_to_string(&path).unwrap_or_default();
61 let mut manifest = SubMsFeatureManifest::load_str("rust", &existing);
62 // Stamp the box these numbers came from. The bench runs wherever it is
63 // invoked, so an unstamped manifest is indistinguishable from a fleet
64 // capture; the renderer will not publish one it cannot attribute.
65 let (source, instance) = SubMsP99Source::from_env();
66 manifest.set_p99_source(source, instance.as_deref());
67
68 // ---------- typed: one Copy type, slot handles, reuse on free ----------
69 #[cfg(feature = "typed")]
70 {
71 use subms_arena_allocator::TypedArena;
72 let sweep: Vec<(usize, u64)> = SIZES
73 .iter()
74 .map(|&n| {
75 let mut arena: TypedArena<u64> = TypedArena::with_capacity(n);
76 let (p50, _) = run_p50_p99(n, |i| {
77 std::hint::black_box(arena.alloc(i as u64));
78 });
79 (n, p50)
80 })
81 .collect();
82 let (cat, reason) = classify_feature(&sweep, None, None);
83
84 let mut arena: TypedArena<u64> = TypedArena::with_capacity(canon);
85 let (_, alloc99) = run_p50_p99(canon, |i| {
86 std::hint::black_box(arena.alloc(i as u64));
87 });
88 // Every timed op here takes the slot the previous one freed, so the
89 // reuse path is what is measured rather than the append path.
90 let mut churn: TypedArena<u64> = TypedArena::with_capacity(2);
91 let (_, free99) = run_p50_p99(canon, |i| {
92 let slot = churn.alloc(i as u64);
93 churn.free(slot);
94 });
95 let mut p99 = BTreeMap::new();
96 p99.insert("alloc".to_string(), alloc99);
97 p99.insert("free".to_string(), free99);
98 manifest.set_feature("typed", cat, &p99, &reason);
99 }
100
101 // ---------- growable: a new chunk when the active one runs out ----------
102 #[cfg(feature = "growable")]
103 {
104 use subms_arena_allocator::GrowableBump;
105 let sweep: Vec<(usize, u64)> = SIZES
106 .iter()
107 .map(|&n| {
108 let mut a = GrowableBump::new();
109 let (p50, _) = run_p50_p99(n, |i| {
110 std::hint::black_box(a.alloc_copy(i as u64));
111 });
112 (n, p50)
113 })
114 .collect();
115 let (cat, reason) = classify_feature(&sweep, None, None);
116
117 let mut a = GrowableBump::new();
118 let (_, alloc99) = run_p50_p99(canon, |i| {
119 std::hint::black_box(a.alloc_copy(i as u64));
120 });
121 let mut filled = GrowableBump::new();
122 for i in 0..canon {
123 filled.alloc_copy(i as u64);
124 }
125 let (_, reset99) = run_p50_p99(1, |_| filled.reset());
126 let mut p99 = BTreeMap::new();
127 p99.insert("alloc".to_string(), alloc99);
128 p99.insert("reset".to_string(), reset99);
129 manifest.set_feature("growable", cat, &p99, &reason);
130 }
131
132 // ---------- stats: live counters on the alloc path ----------
133 #[cfg(feature = "stats")]
134 {
135 use subms_arena_allocator::StatsBump;
136 let sweep: Vec<(usize, u64)> = SIZES
137 .iter()
138 .map(|&n| {
139 let mut a = StatsBump::new();
140 let (p50, _) = run_p50_p99(n, |i| {
141 std::hint::black_box(a.alloc_copy(i as u64));
142 });
143 (n, p50)
144 })
145 .collect();
146 let (cat, reason) = classify_feature(&sweep, None, None);
147
148 let mut a = StatsBump::new();
149 let (_, alloc99) = run_p50_p99(canon, |i| {
150 std::hint::black_box(a.alloc_copy(i as u64));
151 });
152 let (_, snap99) = run_p50_p99(canon, |_| {
153 std::hint::black_box(a.stats());
154 });
155 let mut p99 = BTreeMap::new();
156 p99.insert("alloc".to_string(), alloc99);
157 p99.insert("stats".to_string(), snap99);
158 manifest.set_feature("stats", cat, &p99, &reason);
159 }
160
161 // ---------- aligned: explicit per-allocation alignment ----------
162 #[cfg(feature = "aligned")]
163 {
164 use subms_arena_allocator::AlignedBump;
165 let sweep: Vec<(usize, u64)> = SIZES
166 .iter()
167 .map(|&n| {
168 let mut a = AlignedBump::with_capacity(n * 16 + 4096);
169 let (p50, _) = run_p50_p99(n, |_| {
170 std::hint::black_box(a.alloc_aligned(8, 8).len());
171 });
172 (n, p50)
173 })
174 .collect();
175 let (cat, reason) = classify_feature(&sweep, None, None);
176
177 let mut a = AlignedBump::with_capacity(canon * 16 + 4096);
178 let (_, alloc99) = run_p50_p99(canon, |_| {
179 std::hint::black_box(a.alloc_aligned(8, 8).len());
180 });
181 let mut p99 = BTreeMap::new();
182 p99.insert("alloc_aligned".to_string(), alloc99);
183 manifest.set_feature("aligned", cat, &p99, &reason);
184 }
185
186 std::fs::create_dir_all(path.parent().unwrap())?;
187 std::fs::write(&path, manifest.to_json())?;
188 io::stdout().write_all(manifest.to_json().as_bytes())?;
189 Ok(())
190}Sourcepub fn alloc_raw(&mut self, layout: Layout) -> *mut u8
pub fn alloc_raw(&mut self, layout: Layout) -> *mut u8
Allocate layout.size() bytes aligned to layout.align().
Updates the counters.
Sourcepub fn reset(&mut self)
pub fn reset(&mut self)
Rewind. Keeps the largest chunk. Stats are preserved.
Examples found in repository?
examples/sample_app.rs (line 188)
177fn stats_sizing() {
178 use subms_arena_allocator::StatsBump;
179 println!("\n== stats: size the arena from real load ==");
180 let mut scratch = StatsBump::with_capacity(4096);
181 for _tick in 0..1_000 {
182 for i in 0..8u64 {
183 scratch.alloc_copy(Level {
184 price_ticks: 10_000 + i,
185 qty: 1,
186 });
187 }
188 scratch.reset();
189 }
190 let s = scratch.stats();
191 println!(
192 " {} allocs over 1000 ticks, peak {}B, wasted {}B",
193 s.allocations, s.peak_bytes, s.bytes_wasted,
194 );
195 assert_eq!(s.allocations, 8_000, "counters survive reset");
196 assert!(s.peak_bytes > 0, "peak recorded");
197}Sourcepub fn stats(&self) -> BumpStats
pub fn stats(&self) -> BumpStats
Snapshot the live counters.
Examples found in repository?
examples/sample_app.rs (line 190)
177fn stats_sizing() {
178 use subms_arena_allocator::StatsBump;
179 println!("\n== stats: size the arena from real load ==");
180 let mut scratch = StatsBump::with_capacity(4096);
181 for _tick in 0..1_000 {
182 for i in 0..8u64 {
183 scratch.alloc_copy(Level {
184 price_ticks: 10_000 + i,
185 qty: 1,
186 });
187 }
188 scratch.reset();
189 }
190 let s = scratch.stats();
191 println!(
192 " {} allocs over 1000 ticks, peak {}B, wasted {}B",
193 s.allocations, s.peak_bytes, s.bytes_wasted,
194 );
195 assert_eq!(s.allocations, 8_000, "counters survive reset");
196 assert!(s.peak_bytes > 0, "peak recorded");
197}More examples
examples/perf_features.rs (line 153)
52fn main() -> io::Result<()> {
53 let canon = SIZES[SIZES.len() - 1];
54
55 let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
56 .join("..")
57 .join(".subms")
58 .join("features")
59 .join("rust.json");
60 let existing = std::fs::read_to_string(&path).unwrap_or_default();
61 let mut manifest = SubMsFeatureManifest::load_str("rust", &existing);
62 // Stamp the box these numbers came from. The bench runs wherever it is
63 // invoked, so an unstamped manifest is indistinguishable from a fleet
64 // capture; the renderer will not publish one it cannot attribute.
65 let (source, instance) = SubMsP99Source::from_env();
66 manifest.set_p99_source(source, instance.as_deref());
67
68 // ---------- typed: one Copy type, slot handles, reuse on free ----------
69 #[cfg(feature = "typed")]
70 {
71 use subms_arena_allocator::TypedArena;
72 let sweep: Vec<(usize, u64)> = SIZES
73 .iter()
74 .map(|&n| {
75 let mut arena: TypedArena<u64> = TypedArena::with_capacity(n);
76 let (p50, _) = run_p50_p99(n, |i| {
77 std::hint::black_box(arena.alloc(i as u64));
78 });
79 (n, p50)
80 })
81 .collect();
82 let (cat, reason) = classify_feature(&sweep, None, None);
83
84 let mut arena: TypedArena<u64> = TypedArena::with_capacity(canon);
85 let (_, alloc99) = run_p50_p99(canon, |i| {
86 std::hint::black_box(arena.alloc(i as u64));
87 });
88 // Every timed op here takes the slot the previous one freed, so the
89 // reuse path is what is measured rather than the append path.
90 let mut churn: TypedArena<u64> = TypedArena::with_capacity(2);
91 let (_, free99) = run_p50_p99(canon, |i| {
92 let slot = churn.alloc(i as u64);
93 churn.free(slot);
94 });
95 let mut p99 = BTreeMap::new();
96 p99.insert("alloc".to_string(), alloc99);
97 p99.insert("free".to_string(), free99);
98 manifest.set_feature("typed", cat, &p99, &reason);
99 }
100
101 // ---------- growable: a new chunk when the active one runs out ----------
102 #[cfg(feature = "growable")]
103 {
104 use subms_arena_allocator::GrowableBump;
105 let sweep: Vec<(usize, u64)> = SIZES
106 .iter()
107 .map(|&n| {
108 let mut a = GrowableBump::new();
109 let (p50, _) = run_p50_p99(n, |i| {
110 std::hint::black_box(a.alloc_copy(i as u64));
111 });
112 (n, p50)
113 })
114 .collect();
115 let (cat, reason) = classify_feature(&sweep, None, None);
116
117 let mut a = GrowableBump::new();
118 let (_, alloc99) = run_p50_p99(canon, |i| {
119 std::hint::black_box(a.alloc_copy(i as u64));
120 });
121 let mut filled = GrowableBump::new();
122 for i in 0..canon {
123 filled.alloc_copy(i as u64);
124 }
125 let (_, reset99) = run_p50_p99(1, |_| filled.reset());
126 let mut p99 = BTreeMap::new();
127 p99.insert("alloc".to_string(), alloc99);
128 p99.insert("reset".to_string(), reset99);
129 manifest.set_feature("growable", cat, &p99, &reason);
130 }
131
132 // ---------- stats: live counters on the alloc path ----------
133 #[cfg(feature = "stats")]
134 {
135 use subms_arena_allocator::StatsBump;
136 let sweep: Vec<(usize, u64)> = SIZES
137 .iter()
138 .map(|&n| {
139 let mut a = StatsBump::new();
140 let (p50, _) = run_p50_p99(n, |i| {
141 std::hint::black_box(a.alloc_copy(i as u64));
142 });
143 (n, p50)
144 })
145 .collect();
146 let (cat, reason) = classify_feature(&sweep, None, None);
147
148 let mut a = StatsBump::new();
149 let (_, alloc99) = run_p50_p99(canon, |i| {
150 std::hint::black_box(a.alloc_copy(i as u64));
151 });
152 let (_, snap99) = run_p50_p99(canon, |_| {
153 std::hint::black_box(a.stats());
154 });
155 let mut p99 = BTreeMap::new();
156 p99.insert("alloc".to_string(), alloc99);
157 p99.insert("stats".to_string(), snap99);
158 manifest.set_feature("stats", cat, &p99, &reason);
159 }
160
161 // ---------- aligned: explicit per-allocation alignment ----------
162 #[cfg(feature = "aligned")]
163 {
164 use subms_arena_allocator::AlignedBump;
165 let sweep: Vec<(usize, u64)> = SIZES
166 .iter()
167 .map(|&n| {
168 let mut a = AlignedBump::with_capacity(n * 16 + 4096);
169 let (p50, _) = run_p50_p99(n, |_| {
170 std::hint::black_box(a.alloc_aligned(8, 8).len());
171 });
172 (n, p50)
173 })
174 .collect();
175 let (cat, reason) = classify_feature(&sweep, None, None);
176
177 let mut a = AlignedBump::with_capacity(canon * 16 + 4096);
178 let (_, alloc99) = run_p50_p99(canon, |_| {
179 std::hint::black_box(a.alloc_aligned(8, 8).len());
180 });
181 let mut p99 = BTreeMap::new();
182 p99.insert("alloc_aligned".to_string(), alloc99);
183 manifest.set_feature("aligned", cat, &p99, &reason);
184 }
185
186 std::fs::create_dir_all(path.parent().unwrap())?;
187 std::fs::write(&path, manifest.to_json())?;
188 io::stdout().write_all(manifest.to_json().as_bytes())?;
189 Ok(())
190}Sourcepub fn clear_stats(&mut self)
pub fn clear_stats(&mut self)
Zero the counters. The chunk_count is restored to the current
retained chunk count rather than zero, so the snapshot remains
meaningful immediately after.
Trait Implementations§
Auto Trait Implementations§
impl !Send for StatsBump
impl !Sync for StatsBump
impl Freeze for StatsBump
impl RefUnwindSafe for StatsBump
impl Unpin for StatsBump
impl UnsafeUnpin for StatsBump
impl UnwindSafe for StatsBump
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more