#include #include #include #include // Reproduce the exact structures from hakmem_tiny.h #define TINY_NUM_CLASSES 8 #define TINY_SLAB_SIZE (64 * 1024) #define SLAB_REGISTRY_SIZE 1024 #define TINY_TLS_MAG_CAP 2048 // Mini-mag structure typedef struct { void* next; } MiniMagBlock; typedef struct { MiniMagBlock* head; uint16_t count; uint16_t capacity; } PageMiniMag; // Slab structure typedef struct TinySlab { void* base; uint64_t* bitmap; uint16_t free_count; uint16_t total_count; uint8_t class_idx; uint8_t _padding[3]; struct TinySlab* next; atomic_uintptr_t remote_head; atomic_uint remote_count; pthread_t owner_tid; uint16_t hint_word; uint8_t summary_words; uint8_t _pad_sum[1]; uint64_t* summary; PageMiniMag mini_mag; } TinySlab; // Registry entry typedef struct { uintptr_t slab_base; void* owner; } SlabRegistryEntry; // TLS Magazine typedef struct { void* ptr; } TinyMagItem; typedef struct { TinyMagItem items[TINY_TLS_MAG_CAP]; int top; int cap; } TinyTLSMag; // SuperSlab structures typedef struct TinySlabMeta { void* freelist; uint16_t used; uint16_t capacity; uint32_t owner_tid; } TinySlabMeta; #define SLABS_PER_SUPERSLAB 32 typedef struct SuperSlab { uint64_t magic; uint8_t size_class; uint8_t active_slabs; uint16_t _pad0; uint32_t slab_bitmap; TinySlabMeta slabs[SLABS_PER_SUPERSLAB]; } __attribute__((aligned(64))) SuperSlab; // Bitmap words per class static const uint8_t g_tiny_bitmap_words[TINY_NUM_CLASSES] = { 128, 64, 32, 16, 8, 4, 2, 1 }; static const uint16_t g_tiny_blocks_per_slab[TINY_NUM_CLASSES] = { 8192, 4096, 2048, 1024, 512, 256, 128, 64 }; int main() { printf("=== HAKMEM Memory Overhead Breakdown ===\n\n"); // Structure sizes printf("Structure Sizes:\n"); printf(" TinySlab: %lu bytes\n", sizeof(TinySlab)); printf(" TinyTLSMag: %lu bytes\n", sizeof(TinyTLSMag)); printf(" SlabRegistryEntry: %lu bytes\n", sizeof(SlabRegistryEntry)); printf(" SuperSlab: %lu bytes\n", sizeof(SuperSlab)); printf(" TinySlabMeta: %lu bytes\n", sizeof(TinySlabMeta)); printf("\n"); // Test scenario: 1M × 16B allocations (class 1) int class_idx = 1; // 16B int num_allocs = 1000000; printf("Test Scenario: %d × 16B allocations\n\n", num_allocs); // Calculate theoretical data size size_t data_size = num_allocs * 16; printf("Theoretical Data: %.2f MB\n", data_size / (1024.0 * 1024.0)); // Calculate slabs needed int blocks_per_slab = g_tiny_blocks_per_slab[class_idx]; // 4096 for 16B int slabs_needed = (num_allocs + blocks_per_slab - 1) / blocks_per_slab; printf("Slabs needed: %d (4096 blocks per slab)\n\n", slabs_needed); // Component 1: Global Registry size_t registry_size = SLAB_REGISTRY_SIZE * sizeof(SlabRegistryEntry); printf("Component 1: Global Slab Registry\n"); printf(" Entries: %d\n", SLAB_REGISTRY_SIZE); printf(" Size: %.2f KB (fixed)\n\n", registry_size / 1024.0); // Component 2: TLS Magazine (per thread, assume 1 thread) size_t tls_mag_size = TINY_NUM_CLASSES * sizeof(TinyTLSMag); printf("Component 2: TLS Magazine (per thread)\n"); printf(" Classes: %d\n", TINY_NUM_CLASSES); printf(" Capacity per class: %d items\n", TINY_TLS_MAG_CAP); printf(" Size: %.2f KB per thread\n\n", tls_mag_size / 1024.0); // Component 3: Per-slab metadata size_t slab_metadata_size = slabs_needed * sizeof(TinySlab); printf("Component 3: Slab Metadata\n"); printf(" Slabs: %d\n", slabs_needed); printf(" Size per slab: %lu bytes\n", sizeof(TinySlab)); printf(" Total: %.2f KB\n\n", slab_metadata_size / 1024.0); // Component 4: Bitmaps (primary + summary) int bitmap_words = g_tiny_bitmap_words[class_idx]; // 64 for class 1 int summary_words = (bitmap_words + 63) / 64; // 1 for class 1 size_t bitmap_size = slabs_needed * bitmap_words * sizeof(uint64_t); size_t summary_size = slabs_needed * summary_words * sizeof(uint64_t); printf("Component 4: Bitmaps\n"); printf(" Primary bitmap: %d words × %d slabs = %.2f KB\n", bitmap_words, slabs_needed, bitmap_size / 1024.0); printf(" Summary bitmap: %d words × %d slabs = %.2f KB\n", summary_words, slabs_needed, summary_size / 1024.0); printf(" Total: %.2f KB\n\n", (bitmap_size + summary_size) / 1024.0); // Component 5: Slab data regions size_t slab_data = slabs_needed * TINY_SLAB_SIZE; printf("Component 5: Slab Data Regions\n"); printf(" Slabs: %d × 64 KB = %.2f MB\n\n", slabs_needed, slab_data / (1024.0 * 1024.0)); // Total overhead calculation size_t total_metadata = registry_size + tls_mag_size + slab_metadata_size + bitmap_size + summary_size; size_t total_memory = total_metadata + slab_data; printf("=== TOTAL BREAKDOWN ===\n"); printf("Data used: %.2f MB (actual allocations)\n", data_size / (1024.0 * 1024.0)); printf("Slab wasted space: %.2f MB (unused blocks in slabs)\n", (slab_data - data_size) / (1024.0 * 1024.0)); printf("Metadata overhead: %.2f MB\n", total_metadata / (1024.0 * 1024.0)); printf(" - Registry: %.2f MB\n", registry_size / (1024.0 * 1024.0)); printf(" - TLS Magazine: %.2f MB\n", tls_mag_size / (1024.0 * 1024.0)); printf(" - Slab metadata: %.2f MB\n", slab_metadata_size / (1024.0 * 1024.0)); printf(" - Bitmaps: %.2f MB\n", (bitmap_size + summary_size) / (1024.0 * 1024.0)); printf("Total memory: %.2f MB\n", total_memory / (1024.0 * 1024.0)); printf("Overhead %%: %.1f%%\n", ((total_memory - data_size) / (double)data_size) * 100.0); return 0; }