3131#define MAX_ALLOC_SIZES 1000
3232#define MAX_LINE_LENGTH 1024
3333#define MAX_BUCKETS 16
34+ #define MAX_UNIQUE_BUCKETS 9 /* Maximum number of unique bucket sizes to create */
3435#define MAX_ALLOCATIONS 10000
3536
37+ /* Configuration notes:
38+ * - MAX_UNIQUE_BUCKETS: Limits the total number of unique bucket sizes
39+ * This helps control memory overhead and bucket management complexity
40+ * Default: 9 buckets (can be adjusted based on memory constraints)
41+ */
42+
3643/* Memory overhead constants - these should match wolfSSL's actual values */
3744#define WOLFSSL_HEAP_SIZE 64 /* Approximate size of WOLFSSL_HEAP structure */
3845#define WOLFSSL_HEAP_HINT_SIZE 32 /* Approximate size of WOLFSSL_HEAP_HINT structure */
@@ -75,7 +82,7 @@ int calculate_total_overhead(int num_buckets) {
7582}
7683
7784/* Function to parse memory allocation logs with concurrent usage tracking */
78- int parse_memory_logs (const char * filename , AllocSize * alloc_sizes , int * num_sizes ) {
85+ int parse_memory_logs (const char * filename , AllocSize * alloc_sizes , int * num_sizes , int * peak_heap_usage ) {
7986 FILE * file = fopen (filename , "r" );
8087 if (!file ) {
8188 printf ("Error: Could not open file %s\n" , filename );
@@ -87,6 +94,7 @@ int parse_memory_logs(const char* filename, AllocSize* alloc_sizes, int* num_siz
8794 AllocationEvent events [MAX_ALLOCATIONS ];
8895 int num_events = 0 ;
8996 int timestamp = 0 ;
97+ * peak_heap_usage = 0 ; /* Initialize peak heap usage */
9098
9199 while (fgets (line , sizeof (line ), file ) && num_events < MAX_ALLOCATIONS ) {
92100 /* Look for lines containing "Alloc:" or "Free:" */
@@ -184,6 +192,32 @@ int parse_memory_logs(const char* filename, AllocSize* alloc_sizes, int* num_siz
184192 }
185193 }
186194
195+ /* Calculate peak heap usage by simulating the allocation timeline */
196+ /* This tracks the maximum total memory that was allocated concurrently */
197+ int current_heap_usage = 0 ;
198+ int max_heap_usage = 0 ;
199+
200+ /* Create a timeline of heap usage changes */
201+ for (int i = 0 ; i < num_events ; i ++ ) {
202+ if (events [i ].active ) {
203+ /* Allocation - add to current heap usage */
204+ current_heap_usage += events [i ].size ;
205+ } else {
206+ /* Free - subtract from current heap usage */
207+ current_heap_usage -= events [i ].size ;
208+ if (current_heap_usage < 0 ) {
209+ current_heap_usage = 0 ; /* Handle mismatched free/alloc */
210+ }
211+ }
212+
213+ /* Track peak usage */
214+ if (current_heap_usage > max_heap_usage ) {
215+ max_heap_usage = current_heap_usage ;
216+ }
217+ }
218+
219+ * peak_heap_usage = max_heap_usage ;
220+
187221 return 0 ;
188222}
189223
@@ -198,6 +232,14 @@ int compare_alloc_counts(const void* a, const void* b) {
198232}
199233
200234/* Function to optimize bucket sizes */
235+ /*
236+ * Optimization heuristic:
237+ * - Always include the largest allocation size
238+ * - For other sizes, only create a new bucket if the waste from using
239+ * existing buckets is >= padding size per bucket
240+ * - This reduces bucket management overhead when waste is minimal
241+ * - Limited to MAX_UNIQUE_BUCKETS total unique bucket sizes
242+ */
201243void optimize_buckets (AllocSize * alloc_sizes , int num_sizes , int * buckets ,
202244 int * dist , int * num_buckets )
203245{
@@ -260,8 +302,8 @@ void optimize_buckets(AllocSize* alloc_sizes, int num_sizes, int* buckets,
260302 dist [* num_buckets ] = (largest_concurrent > 0 ) ? largest_concurrent : 1 ;
261303 (* num_buckets )++ ;
262304
263- /* Add significant allocation sizes, avoiding duplicates */
264- for (i = 0 ; i < num_significant && * num_buckets < MAX_BUCKETS ; i ++ ) {
305+ /* Add significant allocation sizes, considering padding overhead */
306+ for (i = 0 ; i < num_significant && * num_buckets < MAX_UNIQUE_BUCKETS ; i ++ ) {
265307 int size = significant_sizes [i ];
266308
267309 /* Skip if this size is already included (like the largest size) */
@@ -276,6 +318,32 @@ void optimize_buckets(AllocSize* alloc_sizes, int num_sizes, int* buckets,
276318 }
277319
278320 if (!already_included ) {
321+ /* Check if this size can be efficiently handled by existing buckets */
322+ int best_existing_bucket = -1 ;
323+ int min_waste = INT_MAX ;
324+ int padding_size = calculate_padding_size ();
325+
326+ /* Find the best existing bucket for this size */
327+ for (j = 0 ; j < * num_buckets ; j ++ ) {
328+ int bucket_data_size = buckets [j ] - padding_size ;
329+ if (bucket_data_size >= size ) {
330+ int waste = bucket_data_size - size ;
331+ if (waste < min_waste ) {
332+ min_waste = waste ;
333+ best_existing_bucket = j ;
334+ }
335+ }
336+ }
337+
338+ /* Only create a new bucket if the waste from existing buckets is significant */
339+ /* If waste is less than padding size, it's better to use existing bucket */
340+ if (best_existing_bucket >= 0 && min_waste < padding_size ) {
341+ /* Use existing bucket - don't create a new one */
342+ /* This size will be handled by the existing bucket */
343+ continue ;
344+ }
345+
346+ /* Create new bucket for this size */
279347 buckets [* num_buckets ] = calculate_bucket_size_with_padding (size );
280348
281349 /* Calculate distribution based on concurrent usage and frequency */
@@ -313,8 +381,8 @@ void optimize_buckets(AllocSize* alloc_sizes, int num_sizes, int* buckets,
313381 }
314382
315383 /* If we still have space, add some medium-frequency sizes */
316- if (* num_buckets < MAX_BUCKETS ) {
317- for (i = 0 ; i < num_sizes && * num_buckets < MAX_BUCKETS ; i ++ ) {
384+ if (* num_buckets < MAX_UNIQUE_BUCKETS ) {
385+ for (i = 0 ; i < num_sizes && * num_buckets < MAX_UNIQUE_BUCKETS ; i ++ ) {
318386 int size = alloc_sizes_by_freq [i ].size ;
319387
320388 /* Skip if already included */
@@ -329,6 +397,32 @@ void optimize_buckets(AllocSize* alloc_sizes, int num_sizes, int* buckets,
329397 }
330398
331399 if (!already_included && alloc_sizes_by_freq [i ].count >= 3 ) {
400+ /* Check if this size can be efficiently handled by existing buckets */
401+ int best_existing_bucket = -1 ;
402+ int min_waste = INT_MAX ;
403+ int padding_size = calculate_padding_size ();
404+
405+ /* Find the best existing bucket for this size */
406+ for (j = 0 ; j < * num_buckets ; j ++ ) {
407+ int bucket_data_size = buckets [j ] - padding_size ;
408+ if (bucket_data_size >= size ) {
409+ int waste = bucket_data_size - size ;
410+ if (waste < min_waste ) {
411+ min_waste = waste ;
412+ best_existing_bucket = j ;
413+ }
414+ }
415+ }
416+
417+ /* Only create a new bucket if the waste from existing buckets is significant */
418+ /* If waste is less than padding size, it's better to use existing bucket */
419+ if (best_existing_bucket >= 0 && min_waste < padding_size ) {
420+ /* Use existing bucket - don't create a new one */
421+ /* This size will be handled by the existing bucket */
422+ continue ;
423+ }
424+
425+ /* Create new bucket for this size */
332426 buckets [* num_buckets ] = calculate_bucket_size_with_padding (size );
333427 dist [* num_buckets ] = 2 ; /* Default to 2 buckets for medium frequency */
334428 (* num_buckets )++ ;
@@ -354,6 +448,17 @@ void optimize_buckets(AllocSize* alloc_sizes, int num_sizes, int* buckets,
354448 }
355449
356450 free (alloc_sizes_by_freq );
451+
452+ /* Print optimization summary */
453+ printf ("Optimization Summary:\n" );
454+ printf ("Padding size per bucket: %d bytes\n" , calculate_padding_size ());
455+ printf ("Maximum unique buckets allowed: %d\n" , MAX_UNIQUE_BUCKETS );
456+ printf ("Total buckets created: %d\n" , * num_buckets );
457+ if (* num_buckets >= MAX_UNIQUE_BUCKETS ) {
458+ printf ("Note: Reached maximum bucket limit (%d). Some allocations may use larger buckets.\n" , MAX_UNIQUE_BUCKETS );
459+ }
460+ printf ("Note: Allocations with waste < padding size use existing buckets to reduce overhead\n" );
461+ printf ("Note: Bucket limit helps balance memory efficiency vs. management overhead\n\n" );
357462}
358463
359464/* Function to calculate memory efficiency metrics */
@@ -364,8 +469,10 @@ void calculate_memory_efficiency(AllocSize* alloc_sizes, int num_sizes,
364469 float total_waste = 0.0 ;
365470 int total_allocations = 0 ;
366471 int allocations_handled = 0 ;
472+ int padding_size = calculate_padding_size ();
367473
368474 printf ("Memory Efficiency Analysis:\n" );
475+ printf ("Note: Allocations with waste < %d bytes (padding size) use existing buckets\n" , padding_size );
369476 printf ("Size Count Concurrent Bucket Waste Coverage\n" );
370477 printf ("---- ----- ---------- ------ ----- --------\n" );
371478
@@ -479,13 +586,15 @@ int main(int argc, char** argv)
479586
480587 AllocSize alloc_sizes [MAX_ALLOC_SIZES ];
481588 int num_sizes = 0 ;
589+ int peak_heap_usage = 0 ;
482590
483591 /* Parse memory allocation logs */
484- if (parse_memory_logs (argv [1 ], alloc_sizes , & num_sizes ) != 0 ) {
592+ if (parse_memory_logs (argv [1 ], alloc_sizes , & num_sizes , & peak_heap_usage ) != 0 ) {
485593 return 1 ;
486594 }
487595
488- printf ("Found %d unique allocation sizes\n\n" , num_sizes );
596+ printf ("Found %d unique allocation sizes\n" , num_sizes );
597+ printf ("Peak heap usage: %d bytes (maximum concurrent memory usage)\n\n" , peak_heap_usage );
489598
490599 /* Sort allocation sizes */
491600 qsort (alloc_sizes , num_sizes , sizeof (AllocSize ), compare_alloc_sizes );
0 commit comments