Line data Source code
1 : #include "mem.h"
2 :
3 : Telemetry telemetry = {0};
4 :
5 : #ifndef ROUGH_DEBUG
6 : #define ROUGH_DEBUG 0
7 : #endif
8 :
9 : /**
10 : * @brief Update the peak heap usage counter if @p updated_current_bytes exceeds it.
11 : *
12 : * Uses atomic compare-and-swap to record the highest observed heap footprint.
13 : *
14 : * @param updated_current_bytes Newly observed heap usage value.
15 : */
16 1294 : static void telemetry_update_peak(const size_t updated_current_bytes)
17 : {
18 1294 : size_t observed_peak = __atomic_load_n(&telemetry.peak_heap_bytes,__ATOMIC_SEQ_CST);
19 :
20 1294 : while(updated_current_bytes > observed_peak)
21 : {
22 248 : if(__atomic_compare_exchange_n(
23 : &telemetry.peak_heap_bytes,
24 : &observed_peak,
25 : updated_current_bytes,
26 : false,
27 : __ATOMIC_SEQ_CST,
28 : __ATOMIC_SEQ_CST))
29 : {
30 248 : break;
31 : }
32 : }
33 1294 : }
34 :
35 : /**
36 : * @brief Track the maximum alignment overhead observed at runtime.
37 : *
38 : * @param updated_current_overhead Current alignment padding consumption in bytes.
39 : */
40 1425 : static void telemetry_update_alignment_peak(const size_t updated_current_overhead)
41 : {
42 1425 : size_t observed_peak = __atomic_load_n(&telemetry.peak_alignment_overhead_bytes,__ATOMIC_SEQ_CST);
43 :
44 1425 : while(updated_current_overhead > observed_peak)
45 : {
46 159 : if(__atomic_compare_exchange_n(
47 : &telemetry.peak_alignment_overhead_bytes,
48 : &observed_peak,
49 : updated_current_overhead,
50 : false,
51 : __ATOMIC_SEQ_CST,
52 : __ATOMIC_SEQ_CST))
53 : {
54 159 : break;
55 : }
56 : }
57 1425 : }
58 :
59 : /**
60 : * @brief Record the highest number of simultaneously active descriptors.
61 : *
62 : * @param updated_active_descriptors Current count of active descriptors.
63 : */
64 1268 : static void telemetry_update_active_peak(const size_t updated_active_descriptors)
65 : {
66 1268 : size_t observed_peak = __atomic_load_n(&telemetry.peak_active_descriptors,__ATOMIC_SEQ_CST);
67 :
68 1268 : while(updated_active_descriptors > observed_peak)
69 : {
70 158 : if(__atomic_compare_exchange_n(
71 : &telemetry.peak_active_descriptors,
72 : &observed_peak,
73 : updated_active_descriptors,
74 : false,
75 : __ATOMIC_SEQ_CST,
76 : __ATOMIC_SEQ_CST))
77 : {
78 158 : break;
79 : }
80 : }
81 1268 : }
82 :
83 748 : void telemetry_realloc_optimized_counter(void)
84 : {
85 748 : __atomic_fetch_add(&telemetry.optimized_resizes_counter,1,__ATOMIC_SEQ_CST);
86 748 : }
87 :
88 1268 : void telemetry_new_allocations_counter(void)
89 : {
90 1268 : __atomic_fetch_add(&telemetry.fresh_allocations_counter,1,__ATOMIC_SEQ_CST);
91 1268 : }
92 :
93 1 : void telemetry_new_callocations_counter(void)
94 : {
95 1 : __atomic_fetch_add(&telemetry.zero_initialized_allocations_counter,1,__ATOMIC_SEQ_CST);
96 1 : }
97 :
98 26 : void telemetry_aligned_reallocations_counter(void)
99 : {
100 26 : __atomic_fetch_add(&telemetry.heap_reallocations_counter,1,__ATOMIC_SEQ_CST);
101 : #if ROUGH_DEBUG
102 : printf("telemetry.heap_reallocations_counter: %zu\n",telemetry.heap_reallocations_counter);
103 : #endif
104 26 : }
105 :
106 27 : void telemetry_realloc_noop_counter(void)
107 : {
108 27 : __atomic_fetch_add(&telemetry.exact_size_resizes_counter,1,__ATOMIC_SEQ_CST);
109 : #if ROUGH_DEBUG
110 : printf("telemetry.exact_size_resizes_counter: %zu\n",telemetry.exact_size_resizes_counter);
111 : #endif
112 27 : }
113 :
114 1268 : void telemetry_free_counter(void)
115 : {
116 1268 : __atomic_fetch_add(&telemetry.release_operations_counter,1,__ATOMIC_SEQ_CST);
117 : #if ROUGH_DEBUG
118 : printf("telemetry.release_operations_counter: %zu\n",telemetry.release_operations_counter);
119 : #endif
120 1268 : }
121 :
122 1268 : void telemetry_free_total_bytes(const size_t amount_of_bytes)
123 : {
124 1268 : __atomic_fetch_add(&telemetry.total_heap_bytes_released,amount_of_bytes,__ATOMIC_SEQ_CST);
125 : #if ROUGH_DEBUG
126 : printf("telemetry.total_heap_bytes_released: %zu\n",telemetry.total_heap_bytes_released);
127 : #endif
128 1268 : }
129 :
130 0 : void telemetry_release_unused_operation(void)
131 : {
132 0 : __atomic_fetch_add(&telemetry.release_unused_operations_counter,1,__ATOMIC_SEQ_CST);
133 0 : }
134 :
135 0 : void telemetry_release_unused_bytes(const size_t amount_of_bytes)
136 : {
137 0 : if(amount_of_bytes == 0)
138 : {
139 0 : return;
140 : }
141 :
142 0 : __atomic_fetch_add(&telemetry.release_unused_bytes_total,amount_of_bytes,__ATOMIC_SEQ_CST);
143 : }
144 :
145 1294 : void telemetry_add(const size_t amount_of_bytes)
146 : {
147 1294 : const size_t updated_current_bytes = __atomic_add_fetch(
148 : &telemetry.current_heap_bytes,
149 : amount_of_bytes,
150 : __ATOMIC_SEQ_CST);
151 :
152 1294 : __atomic_fetch_add(&telemetry.total_heap_bytes_acquired,amount_of_bytes,__ATOMIC_SEQ_CST);
153 1294 : telemetry_update_peak(updated_current_bytes);
154 :
155 : #if ROUGH_DEBUG
156 : printf("+%zu\n",amount_of_bytes);
157 : #endif
158 1294 : }
159 :
160 1828 : void telemetry_effective_add(const size_t amount_of_bytes)
161 : {
162 1828 : __atomic_fetch_add(&telemetry.total_payload_bytes_acquired,amount_of_bytes,__ATOMIC_SEQ_CST);
163 1828 : __atomic_add_fetch(&telemetry.current_payload_bytes,amount_of_bytes,__ATOMIC_SEQ_CST);
164 :
165 : #if ROUGH_DEBUG
166 : printf("+%zu\n",amount_of_bytes);
167 : #endif
168 1828 : }
169 :
170 1268 : void telemetry_reduce(const size_t amount_of_bytes)
171 : {
172 1268 : __atomic_sub_fetch(&telemetry.current_heap_bytes,amount_of_bytes,__ATOMIC_SEQ_CST);
173 : #if ROUGH_DEBUG
174 : printf("-%zu\n",amount_of_bytes);
175 : #endif
176 1268 : }
177 :
178 1482 : void telemetry_effective_reduce(const size_t amount_of_bytes)
179 : {
180 1482 : __atomic_sub_fetch(&telemetry.current_payload_bytes,amount_of_bytes,__ATOMIC_SEQ_CST);
181 : #if ROUGH_DEBUG
182 : printf("-%zu\n",amount_of_bytes);
183 : #endif
184 1482 : }
185 :
186 0 : void telemetry_allocation_failure(void)
187 : {
188 0 : __atomic_fetch_add(&telemetry.heap_allocation_failures_counter,1,__ATOMIC_SEQ_CST);
189 0 : }
190 :
191 0 : void telemetry_reallocation_failure(void)
192 : {
193 0 : __atomic_fetch_add(&telemetry.heap_reallocation_failures_counter,1,__ATOMIC_SEQ_CST);
194 0 : }
195 :
196 1425 : void telemetry_alignment_overhead_add(const size_t amount_of_bytes)
197 : {
198 1425 : if(amount_of_bytes == 0)
199 : {
200 0 : return;
201 : }
202 :
203 1425 : const size_t updated_current_overhead = __atomic_add_fetch(
204 : &telemetry.current_alignment_overhead_bytes,
205 : amount_of_bytes,
206 : __ATOMIC_SEQ_CST);
207 :
208 1425 : __atomic_fetch_add(&telemetry.total_alignment_overhead_bytes,amount_of_bytes,__ATOMIC_SEQ_CST);
209 1425 : telemetry_update_alignment_peak(updated_current_overhead);
210 : }
211 :
212 1730 : void telemetry_alignment_overhead_reduce(const size_t amount_of_bytes)
213 : {
214 1730 : if(amount_of_bytes == 0)
215 : {
216 0 : return;
217 : }
218 :
219 1730 : size_t current_overhead = __atomic_load_n(&telemetry.current_alignment_overhead_bytes,__ATOMIC_SEQ_CST);
220 :
221 1730 : if(amount_of_bytes >= current_overhead)
222 : {
223 592 : __atomic_store_n(&telemetry.current_alignment_overhead_bytes,0,__ATOMIC_SEQ_CST);
224 : } else {
225 1138 : __atomic_sub_fetch(&telemetry.current_alignment_overhead_bytes,amount_of_bytes,__ATOMIC_SEQ_CST);
226 : }
227 : }
228 :
229 27 : void telemetry_noop_resize_event(void)
230 : {
231 27 : const size_t updated_streak = __atomic_add_fetch(
232 : &telemetry.noop_resize_streak_current,
233 : 1,
234 : __ATOMIC_SEQ_CST);
235 :
236 27 : size_t observed_peak = __atomic_load_n(&telemetry.noop_resize_streak_peak,__ATOMIC_SEQ_CST);
237 :
238 27 : while(updated_streak > observed_peak)
239 : {
240 1 : if(__atomic_compare_exchange_n(
241 : &telemetry.noop_resize_streak_peak,
242 : &observed_peak,
243 : updated_streak,
244 : false,
245 : __ATOMIC_SEQ_CST,
246 : __ATOMIC_SEQ_CST))
247 : {
248 1 : break;
249 : }
250 : }
251 27 : }
252 :
253 2042 : void telemetry_reset_noop_streak(void)
254 : {
255 2042 : __atomic_store_n(&telemetry.noop_resize_streak_current,0,__ATOMIC_SEQ_CST);
256 2042 : }
257 :
258 651 : void telemetry_string_padding_event(void)
259 : {
260 651 : __atomic_fetch_add(&telemetry.concat_zero_padding_counter,1,__ATOMIC_SEQ_CST);
261 651 : }
262 :
263 1268 : void telemetry_active_descriptor_acquire(void)
264 : {
265 1268 : const size_t updated_active = __atomic_add_fetch(
266 : &telemetry.active_descriptors,
267 : 1,
268 : __ATOMIC_SEQ_CST);
269 :
270 1268 : telemetry_update_active_peak(updated_active);
271 1268 : }
272 :
273 1268 : void telemetry_active_descriptor_release(void)
274 : {
275 1268 : size_t current_active = __atomic_load_n(&telemetry.active_descriptors,__ATOMIC_SEQ_CST);
276 :
277 1268 : while(current_active > 0)
278 : {
279 1268 : if(__atomic_compare_exchange_n(
280 : &telemetry.active_descriptors,
281 : ¤t_active,
282 1268 : current_active - 1,
283 : false,
284 : __ATOMIC_SEQ_CST,
285 : __ATOMIC_SEQ_CST))
286 : {
287 1268 : break;
288 : }
289 : }
290 1268 : }
291 :
292 0 : void telemetry_overflow_guard_failure(void)
293 : {
294 0 : __atomic_fetch_add(&telemetry.overflow_guard_failures_counter,1,__ATOMIC_SEQ_CST);
295 0 : }
296 :
297 0 : void init_telemetry(void)
298 : {
299 0 : memset(&telemetry,0x0,sizeof(Telemetry));
300 0 : }
301 :
302 1 : void telemetry_show(void)
303 : {
304 1 : printf("Telemetry: Outstanding heap bytes (expected 0): %s\n",bkbmbgbtbpbeb(telemetry.current_heap_bytes));
305 1 : printf("Telemetry: Outstanding payload bytes (expected 0): %s\n",bkbmbgbtbpbeb(telemetry.current_payload_bytes));
306 1 : printf("Telemetry: Peak heap footprint: %s\n",bkbmbgbtbpbeb(telemetry.peak_heap_bytes));
307 1 : printf("Telemetry: Free operations count: %s\n",form(telemetry.release_operations_counter));
308 1 : printf("Telemetry: Bytes released to the OS: %s\n",bkbmbgbtbpbeb(telemetry.total_heap_bytes_released));
309 1 : printf("Telemetry: Shrink calls that forced immediate buffer release: %s\n",form(telemetry.release_unused_operations_counter));
310 1 : printf("Telemetry: Bytes returned by those forced releases: %s\n",bkbmbgbtbpbeb(telemetry.release_unused_bytes_total));
311 1 : printf("Telemetry: Fresh allocation count: %s\n",form(telemetry.fresh_allocations_counter));
312 1 : printf("Telemetry: Zero-initialized allocation count: %s\n",form(telemetry.zero_initialized_allocations_counter));
313 1 : printf("Telemetry: Optimized resize count: %s\n",form(telemetry.optimized_resizes_counter));
314 1 : printf("Telemetry: Realignment resize count: %s\n",form(telemetry.heap_reallocations_counter));
315 1 : printf("Telemetry: Total aligned bytes requested: %s\n",bkbmbgbtbpbeb(telemetry.total_heap_bytes_acquired));
316 1 : printf("Telemetry: Total payload bytes requested: %s\n",bkbmbgbtbpbeb(telemetry.total_payload_bytes_acquired));
317 1 : printf("Telemetry: Exact-size resize count: %s\n",form(telemetry.exact_size_resizes_counter));
318 1 : printf("Telemetry: Allocation failures intercepted: %s\n",form(telemetry.heap_allocation_failures_counter));
319 1 : printf("Telemetry: Reallocation failures intercepted: %s\n",form(telemetry.heap_reallocation_failures_counter));
320 1 : printf("Telemetry: Current alignment overhead: %s\n",bkbmbgbtbpbeb(telemetry.current_alignment_overhead_bytes));
321 1 : printf("Telemetry: Peak alignment overhead: %s\n",bkbmbgbtbpbeb(telemetry.peak_alignment_overhead_bytes));
322 1 : printf("Telemetry: Total alignment overhead accrued: %s\n",bkbmbgbtbpbeb(telemetry.total_alignment_overhead_bytes));
323 1 : printf("Telemetry: Current no-op resize streak: %s\n",form(telemetry.noop_resize_streak_current));
324 1 : printf("Telemetry: Longest no-op resize streak: %s\n",form(telemetry.noop_resize_streak_peak));
325 1 : printf("Telemetry: String padding injections: %s\n",form(telemetry.concat_zero_padding_counter));
326 1 : printf("Telemetry: Active descriptors: %s\n",form(telemetry.active_descriptors));
327 1 : printf("Telemetry: Peak active descriptors: %s\n",form(telemetry.peak_active_descriptors));
328 1 : printf("Telemetry: Overflow guards triggered: %s\n",form(telemetry.overflow_guard_failures_counter));
329 1 : }
|