diff --git a/uppsrc/Core/HeapImp.h b/uppsrc/Core/HeapImp.h index d3c32adca..dcb103e22 100644 --- a/uppsrc/Core/HeapImp.h +++ b/uppsrc/Core/HeapImp.h @@ -283,7 +283,7 @@ struct Heap : BlkHeap { int HugeFree(void *ptr); bool HugeTryRealloc(void *ptr, size_t count); - static int Ksz(int k) { + static int Ksz(int k) { // small block size classes static int sz[] = { // 0 1 2 3 4 5 6 7 8 9 10 11 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, @@ -384,7 +384,7 @@ struct Heap : BlkHeap { static Heap aux; // Single global auxiliary heap to store orphans and global list of free pages static size_t huge_4KB_count; // total number of 4KB pages in small/large/huge blocks - static int free_4KB; // empty 4KB pages + static int free_4KB; // number of empty 4KB pages (linked in aux.empty) static size_t big_size; // blocks >~64KB static size_t big_count; static size_t sys_size; // blocks allocated directly from system (included in big too) @@ -424,6 +424,7 @@ struct Heap : BlkHeap { void *Allok(int k); void Free(void *ptr, Page *page, int k); void Free(void *ptr, int k); + void Free4KB(int k, Page *page); static bool FreeSmallEmpty(int size4KB, int count = INT_MAX); diff --git a/uppsrc/Core/heap.cpp b/uppsrc/Core/heap.cpp index fea80b4c9..f68487258 100644 --- a/uppsrc/Core/heap.cpp +++ b/uppsrc/Core/heap.cpp @@ -144,10 +144,7 @@ void Heap::Shutdown() if(empty[i]) { ASSERT(empty[i]->freelist); ASSERT(empty[i]->active == 0); - empty[i]->heap = &aux; - empty[i]->next = aux.empty[i]; - aux.empty[i] = empty[i]; - free_4KB++; + Free4KB(i, empty[i]); LLOG("Orphan empty " << (void *)empty[i]); } } diff --git a/uppsrc/Core/sheap.cpp b/uppsrc/Core/sheap.cpp index 4a98dd9a3..5675685ca 100644 --- a/uppsrc/Core/sheap.cpp +++ b/uppsrc/Core/sheap.cpp @@ -184,28 +184,35 @@ void Heap::FreeK(void *ptr, Page *page, int k) page->Unlink(); if(this == &aux) { LLOG("...is aux " << asString(free_4KB)); - page->next = empty[k]; - empty[k] = page; - free_4KB++; + Mutex::Lock __(mutex); + Free4KB(k, page); } else { if(empty[k]) { // Keep one hot empty page per klass in thread, put rest to 'aux' global storage - LLOG("Global free " << k << " " << (void *)empty[k]); Mutex::Lock __(mutex); - if(free_4KB < max_free_spages) { // only keep max_free_spages, release if more - empty[k]->heap = &aux; - empty[k]->next = aux.empty[k]; - aux.empty[k] = empty[k]; - free_4KB++; - } - else - aux.HugeFree(empty[k]); + Free4KB(k, empty[k]); // Free current hot page to reserve/huge } - empty[k] = page; + empty[k] = page; // this empty page is now hot } } } +void Heap::Free4KB(int k, Page *page) +{ // put empty 4KB to aux reserve or back to huge blocks if the reserve is full + LLOG("Global Free4KB " << k << " " << (void *)empty); + if(free_4KB < max_free_spages) { // only keep max_free_spages, release if more + page->heap = &aux; + page->next = aux.empty[k]; + aux.empty[k] = page; + free_4KB++; + LLOG("Reserve 4KB " << asString(free_4KB)); + } + else { + aux.HugeFree(page); + LLOG("HugeFree 4KB " << asString(free_4KB)); + } +} + force_inline void Heap::Free(void *ptr, Page *page, int k) {