Core: Heap improvements

git-svn-id: svn://ultimatepp.org/upp/trunk@13437 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2019-06-25 15:47:29 +00:00
parent 68f8a11b0f
commit b7baa4fd01
4 changed files with 29 additions and 13 deletions

View file

@ -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]; }

View file

@ -273,7 +273,9 @@ struct Heap : BlkHeap<HugeHeapDetail, 4096> {
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);

View file

@ -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;
}

View file

@ -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));
}
}
}