optimize mi_bin

This commit is contained in:
daanx 2025-02-11 14:27:01 -08:00
parent d3897635ad
commit c62d276835
2 changed files with 43 additions and 42 deletions

View file

@ -58,26 +58,22 @@ static inline bool mi_page_queue_is_special(const mi_page_queue_t* pq) {
// We use `wsize` for the size in "machine word sizes", // We use `wsize` for the size in "machine word sizes",
// i.e. byte size == `wsize*sizeof(void*)`. // i.e. byte size == `wsize*sizeof(void*)`.
static inline uint8_t mi_bin(size_t size) { static inline uint8_t mi_bin(size_t size) {
size_t wsize = _mi_wsize_from_size(size); size_t wsize = _mi_wsize_from_size(size);
uint8_t bin; #if defined(MI_ALIGN4W)
if (wsize <= 1) { if mi_likely(wsize <= 4) {
bin = 1; return (wsize <= 1 ? 1 : (wsize+1)&~1); // round to double word sizes
} }
#if defined(MI_ALIGN4W) #elif defined(MI_ALIGN2W)
else if (wsize <= 4) { if mi_likely(wsize <= 8) {
bin = (uint8_t)((wsize+1)&~1); // round to double word sizes return (wsize <= 1 ? 1 : (wsize+1)&~1); // round to double word sizes
} }
#elif defined(MI_ALIGN2W) #else
else if (wsize <= 8) { if mi_likely(wsize <= 8) {
bin = (uint8_t)((wsize+1)&~1); // round to double word sizes return (wsize == 0 ? 1 : wsize);
} }
#else #endif
else if (wsize <= 8) { else if mi_unlikely(wsize > MI_LARGE_OBJ_WSIZE_MAX) {
bin = (uint8_t)wsize; return MI_BIN_HUGE;
}
#endif
else if (wsize > MI_LARGE_OBJ_WSIZE_MAX) {
bin = MI_BIN_HUGE;
} }
else { else {
#if defined(MI_ALIGN4W) #if defined(MI_ALIGN4W)
@ -85,15 +81,14 @@ static inline uint8_t mi_bin(size_t size) {
#endif #endif
wsize--; wsize--;
// find the highest bit // find the highest bit
uint8_t b = (uint8_t)mi_bsr(wsize); // note: wsize != 0 const size_t b = mi_bsr(wsize); // note: wsize != 0
// and use the top 3 bits to determine the bin (~12.5% worst internal fragmentation). // and use the top 3 bits to determine the bin (~12.5% worst internal fragmentation).
// - adjust with 3 because we use do not round the first 8 sizes // - adjust with 3 because we use do not round the first 8 sizes
// which each get an exact bin // which each get an exact bin
bin = ((b << 2) + (uint8_t)((wsize >> (b - 2)) & 0x03)) - 3; const size_t bin = ((b << 2) + ((wsize >> (b - 2)) & 0x03)) - 3;
mi_assert_internal(bin < MI_BIN_HUGE); mi_assert_internal(bin > 0 && bin < MI_BIN_HUGE);
return bin;
} }
mi_assert_internal(bin > 0 && bin <= MI_BIN_HUGE);
return bin;
} }

View file

@ -32,7 +32,10 @@ static void test_manage_os_memory(void);
int main() { int main() {
mi_version(); mi_version();
mi_stats_reset(); mi_stats_reset();
test_manage_os_memory();
mi_bins();
// test_manage_os_memory();
// test_large_pages(); // test_large_pages();
// detect double frees and heap corruption // detect double frees and heap corruption
// double_free1(); // double_free1();
@ -40,7 +43,7 @@ int main() {
// corrupt_free(); // corrupt_free();
// block_overflow1(); // block_overflow1();
// block_overflow2(); // block_overflow2();
test_canary_leak(); // test_canary_leak();
// test_aslr(); // test_aslr();
// invalid_free(); // invalid_free();
// test_reserved(); // test_reserved();
@ -48,8 +51,6 @@ int main() {
// test_heap_walk(); // test_heap_walk();
// alloc_huge(); // alloc_huge();
// mi_bins();
void* p1 = malloc(78); void* p1 = malloc(78);
void* p2 = malloc(24); void* p2 = malloc(24);
@ -314,7 +315,7 @@ static void test_large_pages(void) {
// bin size experiments // bin size experiments
// ------------------------------ // ------------------------------
#if 0 #if 1
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@ -376,31 +377,34 @@ static inline size_t _mi_wsize_from_size(size_t size) {
return (size + sizeof(uintptr_t) - 1) / sizeof(uintptr_t); return (size + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
} }
// #define MI_ALIGN2W
// Return the bin for a given field size. // Return the bin for a given field size.
// Returns MI_BIN_HUGE if the size is too large. // Returns MI_BIN_HUGE if the size is too large.
// We use `wsize` for the size in "machine word sizes", // We use `wsize` for the size in "machine word sizes",
// i.e. byte size == `wsize*sizeof(void*)`. // i.e. byte size == `wsize*sizeof(void*)`.
extern inline uint8_t _mi_bin8(size_t size) { static inline size_t mi_bin(size_t wsize) {
size_t wsize = _mi_wsize_from_size(size); // size_t wsize = _mi_wsize_from_size(size);
uint8_t bin; // size_t bin;
if (wsize <= 1) { /*if (wsize <= 1) {
bin = 1; bin = 1;
} }
*/
#if defined(MI_ALIGN4W) #if defined(MI_ALIGN4W)
else if (wsize <= 4) { if (wsize <= 4) {
bin = (uint8_t)((wsize+1)&~1); // round to double word sizes return (wsize <= 1 ? 1 : (wsize+1)&~1); // round to double word sizes
} }
#elif defined(MI_ALIGN2W) #elif defined(MI_ALIGN2W)
else if (wsize <= 8) { if (wsize <= 8) {
bin = (uint8_t)((wsize+1)&~1); // round to double word sizes return (wsize <= 1 ? 1 : (wsize+1)&~1); // round to double word sizes
} }
#else #else
else if (wsize <= 8) { if (wsize <= 8) {
bin = (uint8_t)wsize; return (wsize == 0 ? 1 : wsize);
} }
#endif #endif
else if (wsize > MI_LARGE_WSIZE_MAX) { else if (wsize > MI_LARGE_WSIZE_MAX) {
bin = MI_BIN_HUGE; return MI_BIN_HUGE;
} }
else { else {
#if defined(MI_ALIGN4W) #if defined(MI_ALIGN4W)
@ -408,15 +412,17 @@ extern inline uint8_t _mi_bin8(size_t size) {
#endif #endif
wsize--; wsize--;
// find the highest bit // find the highest bit
uint8_t b = mi_bsr32((uint32_t)wsize); const size_t b = _mi_bsr(wsize); // note: wsize != 0
// and use the top 3 bits to determine the bin (~12.5% worst internal fragmentation). // and use the top 3 bits to determine the bin (~12.5% worst internal fragmentation).
// - adjust with 3 because we use do not round the first 8 sizes // - adjust with 3 because we use do not round the first 8 sizes
// which each get an exact bin // which each get an exact bin
bin = ((b << 2) + (uint8_t)((wsize >> (b - 2)) & 0x03)) - 3; const size_t bin = ((b << 2) + ((wsize >> (b - 2)) & 0x03)) - 3;
assert(bin > 0 && bin < MI_BIN_HUGE);
return bin;
} }
return bin;
} }
static inline uint8_t _mi_bin4(size_t size) { static inline uint8_t _mi_bin4(size_t size) {
size_t wsize = _mi_wsize_from_size(size); size_t wsize = _mi_wsize_from_size(size);
uint8_t bin; uint8_t bin;
@ -472,7 +478,7 @@ static size_t _mi_binx8(size_t bsize) {
} }
static inline size_t mi_bin(size_t wsize) { static inline size_t mi_binx(size_t wsize) {
uint8_t bin; uint8_t bin;
if (wsize <= 1) { if (wsize <= 1) {
bin = 1; bin = 1;