From b7baa4fd0138e11fb1040d351662476582204baa Mon Sep 17 00:00:00 2001 From: cxl Date: Tue, 25 Jun 2019 15:47:29 +0000 Subject: [PATCH] Core: Heap improvements git-svn-id: svn://ultimatepp.org/upp/trunk@13437 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Core/Heap.h | 7 +++++-- uppsrc/Core/HeapImp.h | 4 +++- uppsrc/Core/hheap.cpp | 29 +++++++++++++++++++---------- uppsrc/Core/sheap.cpp | 2 ++ 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/uppsrc/Core/Heap.h b/uppsrc/Core/Heap.h index f4b558ecb..30bb0fd4e 100644 --- a/uppsrc/Core/Heap.h +++ b/uppsrc/Core/Heap.h @@ -1,5 +1,6 @@ -struct MemoryOptions { - int master_block = 16; // master block size +struct MemoryOptions { // sizes are in KB + int master_block = 16384; // master block size + int sys_block_limit = 16384; // > that this: allocate directly from the system int master_reserve = 1; // free master blocks kept in reserve }; @@ -128,6 +129,8 @@ void TinyFree(int size, void *ptr) #else +inline void MemorySetOptions(const MemoryOptions& opt) {} + inline void *MemoryAllocPermanent(size_t size) { return malloc(size); } inline void *MemoryAlloc(size_t size) { return new byte[size]; } inline void *MemoryAllocSz(size_t &size) { return new byte[size]; } diff --git a/uppsrc/Core/HeapImp.h b/uppsrc/Core/HeapImp.h index 2a2257d60..caa344133 100644 --- a/uppsrc/Core/HeapImp.h +++ b/uppsrc/Core/HeapImp.h @@ -273,7 +273,9 @@ struct Heap : BlkHeap { REMOTE_OUT_SZ = 2000, // maximum size of remote frees to be buffered to flush at once }; - static word HPAGE; + static word HPAGE; // size of master page, in 4KB units + static int max_free_hpages; // maximum free master pages kept in reserve (if more, they are returned to the system) + static word sys_block_limit; // > this (in 4KB) blocks are managed directly by system void *HugeAlloc(size_t count); // count in 4KB, client needs to not touch HugePrefix int HugeFree(void *ptr); diff --git a/uppsrc/Core/hheap.cpp b/uppsrc/Core/hheap.cpp index 9b83966dc..2e6cc8668 100644 --- a/uppsrc/Core/hheap.cpp +++ b/uppsrc/Core/hheap.cpp @@ -15,6 +15,15 @@ namespace Upp { // also able to deal with bigger blocks, those are directly allocated / freed from system word Heap::HPAGE = 16 * 256; // 16MB default value +word Heap::sys_block_limit = 16 * 256; // 16MB default value +int Heap::max_free_hpages = 4; // default value + +void MemorySetOptions(const MemoryOptions& opt) +{ + Heap::HPAGE = (word)clamp(opt.master_block / 4, 256, 65535); + Heap::sys_block_limit = (word)clamp((int)opt.sys_block_limit / 4, 16, (int)Heap::HPAGE); + Heap::max_free_hpages = opt.master_reserve; +} BlkHeader_<4096> HugeHeapDetail::freelist[20][1]; // only single global Huge heap... Heap::HugePage *Heap::huge_pages; @@ -79,7 +88,7 @@ void *Heap::HugeAlloc(size_t count) // count in 4kb pages Dbl_Self(D::freelist[i]); } - if(count > HPAGE) { // we are wasting 4KB to store just 4 bytes here, but this is >32MB after all.. + if(count > sys_block_limit) { // we are wasting 4KB to store just 4 bytes here, but this is n MB after all.. LTIMING("SysAlloc"); byte *sysblk = (byte *)SysAllocRaw((count + 1) * 4096, 0); BlkHeader *h = (BlkHeader *)(sysblk + 4096); @@ -95,9 +104,6 @@ void *Heap::HugeAlloc(size_t count) // count in 4kb pages word wcount = (word)count; - if(16 * free_4KB > huge_4KB_count) // keep number of free 4KB blocks in check - FreeSmallEmpty(INT_MAX, int(free_4KB - huge_4KB_count / 32)); - for(int pass = 0; pass < 2; pass++) { for(int i = Cv(wcount); i < __countof(D::freelist); i++) { BlkHeader *l = D::freelist[i]; @@ -105,7 +111,7 @@ void *Heap::HugeAlloc(size_t count) // count in 4kb pages while(h != l) { word sz = h->GetSize(); if(sz >= count) { - if(h->IsFirst() && h->IsLast()) + if(h->IsFirst() && h->IsLast()) // this is whole free page free_hpages--; void *ptr = MakeAlloc(h, wcount); MaxMem(); @@ -153,9 +159,11 @@ int Heap::HugeFree(void *ptr) } LTIMING("Huge Free"); huge_4KB_count -= h->GetSize(); - int sz = BlkHeap::Free(h)->GetSize(); - if(h->IsFirst() && h->IsLast()) { - if(0) { + h = BlkHeap::Free(h); + int sz = h->GetSize(); + if(h->IsFirst() && h->IsLast()) + if(free_hpages >= max_free_hpages) { // we have enough pages in the reserve, return to the system + h->UnlinkFree(); HugePage *p = NULL; while(huge_pages) { // remove the page from the set of huge pages HugePage *n = huge_pages->next; @@ -166,10 +174,11 @@ int Heap::HugeFree(void *ptr) huge_pages = n; } huge_pages = p; + huge_chunks--; SysFreeRaw(h, sz * 4096); } - free_hpages++; - } + else + free_hpages++; return sz; } diff --git a/uppsrc/Core/sheap.cpp b/uppsrc/Core/sheap.cpp index f9a91bc28..d59d3c9a5 100644 --- a/uppsrc/Core/sheap.cpp +++ b/uppsrc/Core/sheap.cpp @@ -191,6 +191,8 @@ void Heap::FreeK(void *ptr, Page *page, int k) free_4KB++; } empty[k] = page; + if(16 * free_4KB > huge_4KB_count) // keep number of free 4KB blocks in check + FreeSmallEmpty(INT_MAX, int(free_4KB - huge_4KB_count / 32)); } } }