ultimatepp/uppdev/Heap/main.cpp
cxl 4a1c627474 Adding uppdev....
git-svn-id: svn://ultimatepp.org/upp/trunk@328 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2008-08-15 08:36:24 +00:00

411 lines
8.8 KiB
C++

$uvs: PENDING CONFLICT
#include <Core/Core.h>
using namespace Upp;
$uvs: REPOSITORY INSERT
void LMemoryCheck()
{
$uvs: END REPOSITORY INSERT
$uvs: REPOSITORY DELETE
#define RESERVE_CHUNK 4 * 1024 * 1024
static byte **free_raw64_page;
static int free_raw64_alloc;
static int free_raw64_count;
int sMediumKb;
byte *Alloc64KBRaw() {
sMediumKb += 64;
if(free_raw64_count) {
byte *ptr = free_raw64_page[--free_raw64_count];
VirtualAlloc(ptr, 65536, MEM_COMMIT, PAGE_READWRITE);
return ptr;
}
static byte *ptr = NULL;
static byte *limit = NULL;
if(ptr >= limit) {
ptr = (byte *) VirtualAlloc(NULL, RESERVE_CHUNK, MEM_RESERVE, PAGE_READWRITE);
limit = ptr + RESERVE_CHUNK;
}
VirtualAlloc(ptr, 65536, MEM_COMMIT, PAGE_READWRITE);
byte *p = ptr;
ptr += 65536;
return p;
}
void Free64KBRaw(byte *ptr)
{
sMediumKb -= 64;
if(free_raw64_count >= free_raw64_alloc) {
byte **prev = free_raw64_page;
if(free_raw64_alloc)
free_raw64_alloc *= 2;
else
free_raw64_alloc = 100000;
free_raw64_page = (byte **)malloc(sizeof(byte *) * free_raw64_alloc);
if(prev) {
memcpy(free_raw64_page, prev, free_raw64_count * sizeof(byte *));
free(prev);
}
}
free_raw64_page[free_raw64_count++] = ptr;
VirtualFree(ptr, 65536, MEM_DECOMMIT);
}
void *AllocBigRaw(size_t size)
{
return VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
}
void FreeBigRaw(void *ptr, size_t size)
{
VirtualFree(ptr, 0, MEM_RELEASE);
}
struct MLink;
struct MHeader {
byte free;
byte d1, d2, d3;
word size;
word prev;
MLink *Block() { return (MLink *)(this + 1); }
MHeader *Next() { return (MHeader *)((byte *)this + size) + 1; }
MHeader *Prev() { return (MHeader *)((byte *)this - prev) - 1; }
};
struct MLink {
MLink *next;
MLink *prev;
void LinkSelf() { prev = next = this; }
void Unlink() { prev->next = next; next->prev = prev; }
void Link(MLink *lnk) { prev = lnk; next = lnk->next; next->prev = this; lnk->next = this; }
MHeader *Header() { return (MHeader *)this - 1; }
};
#define BINS 113
#define MAXBLOCK 65504
static word BinSz[BINS];
static byte sSzBin[MAXBLOCK / 8 + 1];
static byte sBlBin[MAXBLOCK / 8 + 1];
static MLink freebin[BINS];
static int binaccel[BINS / 8 + 1];
static MLink mall;
static MLink ball;
void Init()
{
int p = 24;
int bi = 0;
while(p < MAXBLOCK) {
BinSz[bi++] = p;
int add = minmax(6 * p / 100 / 32 * 32, 32, 2048);
p += add;
}
ASSERT(bi == BINS - 1);
BinSz[BINS - 1] = MAXBLOCK;
int k = 0;
for(int i = 0; i <= MAXBLOCK / 8; i++) {
while(i * 8 + 7 > BinSz[k]) k++;
sSzBin[i] = k;
}
k = BINS - 1;
for(int i = MAXBLOCK / 8; i >= 0; i--) {
while(i * 8 < BinSz[k]) k--;
sBlBin[i] = k;
}
sBlBin[0] = 0;
for(int i = 0; i < BINS; i++)
freebin[i].LinkSelf();
mall.LinkSelf();
ball.LinkSelf();
binaccel[BINS / 8] = 1;
}
inline int SzBin(int n)
{
return sSzBin[(n - 1) >> 3];
}
inline int BlBin(int n)
{
return sBlBin[n >> 3];
}
void LinkFree(MLink *b, int size)
{
int q = BlBin(size);
b->Link(&freebin[q]);
$uvs: YOUR INSERT (REPOSITORY DELETE)
// binaccel[q >> 3]++;
$uvs: END YOUR INSERT (REPOSITORY DELETE)
$uvs: YOUR DELETE (REPOSITORY DELETE)
binaccel[q >> 3]++;
$uvs: END YOUR DELETE (REPOSITORY DELETE)
}
MLink *AddChunk()
{
ASSERT(sizeof(MHeader) == 8);
ASSERT(sizeof(MLink) <= 16);
MLink *ml = (MLink *)Alloc64KBRaw();
ml->Link(&mall);
MHeader *bh = (MHeader *)((byte *)ml + 16);
bh->size = MAXBLOCK;
bh->prev = 0;
bh->free = true;
MLink *b = bh->Block();
LinkFree(b, MAXBLOCK);
bh = bh->Next();
bh->prev = MAXBLOCK;
bh->size = 0;
bh->free = false;
return b;
}
void *DivideBlock(MLink *b, int size, int ii)
{
b->Unlink();
$uvs: YOUR INSERT (REPOSITORY DELETE)
// binaccel[ii >> 3]--;
$uvs: END YOUR INSERT (REPOSITORY DELETE)
$uvs: YOUR DELETE (REPOSITORY DELETE)
binaccel[ii >> 3]--;
$uvs: END YOUR DELETE (REPOSITORY DELETE)
MHeader *bh = b->Header();
ASSERT(bh->size >= size);
bh->free = false;
int sz2 = bh->size - size - sizeof(MHeader);
if(sz2 >= 32) {
MHeader *bh2 = (MHeader *)((byte *)b + size);
bh2->prev = size;
bh2->free = true;
LinkFree(bh2->Block(), sz2);
bh->Next()->prev = bh2->size = sz2;
bh->size = size;
}
return b;
}
void *Alloc(size_t size) {
static inited;
if(!inited) {
Init();
inited = true;
}
if(size > MAXBLOCK) {
MLink *b = (MLink *)AllocBigRaw(size + 40);
b->Link(&ball);
*(size_t *)((byte *)b + 16) = size;
MHeader *h = (MHeader *)((byte *)b + 32);
h->size = 0;
h->free = false;
return (byte *)b + 40;
}
if(size < 256)
size = 256;
int ii = SzBin(size);
size = BinSz[ii];
while(ii < BINS) {
/* int q = ii >> 3;
if(binaccel[q] == 0) {
while(binaccel[q] == 0) q++;
ii = q << 3;
}
else {*/
MLink *b = &freebin[ii];
MLink *n = b->next;
if(b != n)
return DivideBlock(n, size, ii);
ii++;
// }
}
return DivideBlock(AddChunk(), size, BINS - 1);
}
void Free(void *ptr) {
MLink *b = (MLink *)ptr;
MHeader *bh = b->Header();
if(bh->size == 0) {
ASSERT(((dword)bh & 4095) == 32);
b = (MLink *)((byte *)bh - 32);
b->Unlink();
FreeBigRaw(b, *(size_t *)((byte *)b + 16));
return;
}
if(bh->prev) {
MHeader *p = bh->Prev();
if(p->free) {
b = p->Block();
b->Unlink();
p->size += bh->size + sizeof(MHeader);
p->Next()->prev = p->size;
bh = p;
}
}
MHeader *n = bh->Next();
if(n->free) {
n->Block()->Unlink();
bh->size += n->size + sizeof(MHeader);
n->Next()->prev = bh->size;
}
bh->free = true;
LinkFree(b, bh->size);
$uvs: END REPOSITORY DELETE
}
void DumpHeap()
{
LOG("--------------------------------------------------------");
$uvs: REPOSITORY INSERT
LOG("heap");
MLink *m = s_mall.next;
while(m != &s_mall) {
$uvs: END REPOSITORY INSERT
$uvs: REPOSITORY DELETE
MLink *m = mall.next;
while(m != &mall) {
$uvs: END REPOSITORY DELETE
MHeader *h = (MHeader *)((byte *)m + 16);
while(h->size) {
LOG((h->free ? "FREE" : "USED") << " " << h->size);
h = h->Next();
}
m = m->next;
LOG("===========");
}
$uvs: REPOSITORY INSERT
LOG("......");
$uvs: END REPOSITORY INSERT
}
void *ptr[8192];
$uvs: REPOSITORY INSERT
void *LAlloc(int sz) { size_t s = sz; return LAlloc(s); }
$uvs: END REPOSITORY INSERT
void Benchmark()
{
RTIMING("Benchmark");
void *ptr[8192];
$uvs: REPOSITORY INSERT
for(int q = 0; q < 20; q++) {
for(int i = 0; i < 8192; i++)
ptr[i] = LAlloc(2048);
for(int i = 0; i < 8192; i++)
LFree(ptr[i]);
$uvs: END REPOSITORY INSERT
$uvs: REPOSITORY DELETE
for(int q = 0; q < 2000; q++) {
for(int i = 0; i < 8192; i++)
ptr[i] = Alloc(2048);
for(int i = 0; i < 8192; i++)
Free(ptr[i]);
$uvs: END REPOSITORY DELETE
}
}
CONSOLE_APP_MAIN {
$uvs: REPOSITORY INSERT
sLInit();
for(int i = 0; i < BINS; i++)
LOG(i << ": " << sBinSz[i]);
for(int i = 32; i <= MAXBLOCK; i++)
LOG(i << ": bin " << (int)sSzBin(i) << " - " << sBinSz[sSzBin(i)]
<< ", bl " << (int)sBlBin(i) << " - " << sBinSz[sBlBin(i)]);
$uvs: END REPOSITORY INSERT
Benchmark();
DumpHeap();
$uvs: REPOSITORY INSERT
LMemoryShrink();
DumpHeap();
memset(ptr, 0, sizeof(ptr));
for(int n = 1; n < 5000000; n++) {
int q = rand() & 511;
if(ptr[q])
LFree(ptr[q]);
int sz = 5 * ((rand() & 16383) + 270);
ptr[q] = LAlloc(sz);
}
DumpHeap();
for(int q = 0; q < 512; q++)
if(ptr[q])
LFree(ptr[q]);
DumpHeap();
LMemoryShrink();
LOG("Final");
DumpHeap();
return;
void *p1, *p2, *p3;
p1 = LAlloc(500);
DumpHeap();
p2 = LAlloc(300);
DumpHeap();
p3 = LAlloc(400);
DumpHeap();
LFree(p2);
DumpHeap();
LFree(p1);
DumpHeap();
LFree(p3);
DumpHeap();
}
$uvs: END REPOSITORY INSERT
$uvs: REPOSITORY DELETE
return;
Init();
for(int i = 0; i < BINS; i++)
LOG(i << ": " << BinSz[i]);
for(int i = 32; i <= MAXBLOCK; i++)
LOG(i << ": bin " << (int)SzBin(i) << " - " << BinSz[SzBin(i)]
<< ", bl " << (int)BlBin(i) << " - " << BinSz[BlBin(i)]);
void *p1, *p2, *p3;
p1 = Alloc(500);
DumpHeap();
p2 = Alloc(300);
DumpHeap();
p3 = Alloc(400);
DumpHeap();
Free(p2);
DumpHeap();
Free(p1);
DumpHeap();
Free(p3);
DumpHeap();
memset(ptr, 0, sizeof(ptr));
for(int n = 1; n < 500; n++) {
int q = rand() & 63;
if(ptr[q])
Free(ptr[q]);
DumpHeap();
int sz = (rand() & 16383) + 270;
DUMP(sz);
ptr[q] = Alloc(sz);
DumpHeap();
}
for(int q = 0; q < 64; q++)
if(ptr[q]) {
Free(ptr[q]);
DumpHeap();
}
}
$uvs: END REPOSITORY DELETE