Skip to content

Commit 1b0f1a3

Browse files
committed
feat(heap): reorganize heap struct to satisfy cache alignements
1 parent 073544f commit 1b0f1a3

2 files changed

Lines changed: 32 additions & 9 deletions

File tree

core/heap.h

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
#define SLAB_CACHE_SIZE 64
3636
#define SLAB_ORDERS 5 // orders 5, 6, 7, 8, 9
3737

38+
// Cache line size (typically 64 bytes on x86/ARM)
39+
#define CACHE_LINE_SIZE 64
40+
3841
// Memory modes
3942
#define MMOD_INTERNAL 0xff
4043
#define MMOD_EXTERNAL_SIMPLE 0xfd
@@ -61,20 +64,29 @@ typedef struct block_t {
6164
} *block_p;
6265

6366
// Small object slab cache for fast alloc/free of common sizes
67+
// count is FIRST - checked before stack access, avoids cache miss
6468
typedef struct slab_cache_t {
69+
i64_t count; // current stack depth (check first!)
6570
block_p stack[SLAB_CACHE_SIZE]; // LIFO stack of freed blocks
66-
i64_t count; // current stack depth
6771
} slab_cache_t;
6872

6973
typedef struct heap_t {
70-
i64_t id;
74+
// ===== Cache line 1: hottest fields (allocation fast path) =====
75+
i64_t avail; // 8B - bitmask checked every alloc
76+
i64_t id; // 8B - heap identity checked in free
77+
block_p foreign_blocks; // 8B - checked in worker free path
78+
block_p backed_blocks; // 8B - file-backed blocks
79+
i64_t _pad_cacheline1[4]; // 32B - pad to 64B cache line
80+
81+
// ===== Slab caches (count field is first in each - fast path check) =====
82+
slab_cache_t slabs[SLAB_ORDERS]; // small object caches for orders 5-9
83+
84+
// ===== Freelists (accessed for non-slab allocations) =====
7185
block_p freelist[MAX_POOL_ORDER + 2]; // free list of blocks by order
72-
i64_t avail; // mask of available blocks by order
73-
slab_cache_t slabs[SLAB_ORDERS]; // small object caches for orders 6-9
74-
block_p foreign_blocks; // foreign blocks (to be freed by the owner)
75-
block_p backed_blocks; // backed blocks (to be unmapped)
76-
memstat_t memstat;
77-
c8_t swap_path[64]; // swap directory path
86+
87+
// ===== Cold fields (rarely accessed) =====
88+
memstat_t memstat; // statistics
89+
c8_t swap_path[64]; // swap directory path (init only)
7890
} *heap_p;
7991

8092
heap_p heap_create(i64_t id);

core/mmap.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,19 @@ raw_p mmap_stack(i64_t size) {
9999

100100
raw_p mmap_alloc(i64_t size) {
101101
raw_p ptr;
102+
int flags = MAP_ANONYMOUS | MAP_SHARED | MAP_NONBLOCK | MAP_POPULATE;
103+
104+
// Try huge pages for large allocations (>= 2MB) - reduces TLB misses
105+
#ifdef MAP_HUGETLB
106+
if (size >= (2 << 20)) {
107+
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, flags | MAP_HUGETLB, -1, 0);
108+
if (ptr != MAP_FAILED)
109+
return ptr;
110+
// Fall back to regular pages if huge pages unavailable
111+
}
112+
#endif
102113

103-
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED | MAP_NONBLOCK | MAP_POPULATE, -1, 0);
114+
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0);
104115

105116
if (ptr == MAP_FAILED)
106117
return NULL;

0 commit comments

Comments
 (0)