Files
hakmem/archive/tools/calculate_overhead.c

171 lines
5.8 KiB
C
Raw Permalink Normal View History

#include <stdio.h>
#include <stdint.h>
#include <pthread.h>
#include <stdatomic.h>
// 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;
}