Core: Heap issues

git-svn-id: svn://ultimatepp.org/upp/trunk@13369 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2019-06-08 16:37:55 +00:00
parent 086efe4341
commit acd196b8dc
6 changed files with 84 additions and 50 deletions

View file

@ -12,7 +12,7 @@ void MemoryFree48(void *ptr);
void MemoryFreeThread();
void MemoryCheck();
int MemoryUsedKb();
int MemoryUsedKbMax();
void MemoryLimitKb(int kb);
size_t GetMemoryBlockSize(void *ptr);

View file

@ -1,4 +1,4 @@
void OutOfMemoryPanic(size_t size);
void OutOfMemoryPanic();
void *SysAllocRaw(size_t size, size_t reqsize);
void SysFreeRaw(void *ptr, size_t size);
@ -387,6 +387,7 @@ struct Heap : BlkHeap<HugeHeapDetail, 4096> {
static size_t sys_size; // blocks allocated directly from system (included in big too)
static size_t sys_count;
static size_t huge_chunks; // 32MB master pages
static size_t huge_4KB_count_max; // peak huge memory allocated
#ifdef HEAPDBG
static void DbgFreeFillK(void *ptr, int k);

View file

@ -39,6 +39,36 @@ inline void DeepCopyConstruct(T *t, const S *s, const S *end) {
template <class T>
class Buffer : Moveable< Buffer<T> > {
T *ptr;
void Malloc(size_t size) {
if(std::is_trivially_destructible<T>::value)
ptr = (T *)MemoryAlloc(size * sizeof(T));
else {
void *p = MemoryAlloc(size * sizeof(T) + 16);
*(size_t *)p = size;
ptr = (T *)((byte *)p + 16);
}
}
void New(size_t size) {
Malloc(size);
Construct(ptr, ptr + size);
}
void New(size_t size, const T& in) {
Malloc(size);
DeepCopyConstructFill(ptr, ptr + size, in);
}
void Free() {
if(ptr) {
if(std::is_trivially_destructible<T>::value)
MemoryFree(ptr);
else {
void *p = (byte *)ptr - 16;
size_t size = *(size_t *)p;
Destroy(ptr, ptr + size);
MemoryFree(p);
}
}
}
public:
operator T*() { return ptr; }
@ -48,22 +78,22 @@ public:
T *Get() { return ptr; }
const T *Get() const { return ptr; }
void Alloc(size_t size) { Clear(); ptr = new T[size]; }
void Alloc(size_t size, const T& in) { Clear(); ptr = new T[size]; Fill(ptr, ptr + size, in); }
void Alloc(size_t size) { Clear(); New(size); }
void Alloc(size_t size, const T& in) { Clear(); New(size, in); }
void Clear() { if(ptr) delete[] ptr; ptr = NULL; }
void Clear() { Free(); ptr = NULL; }
bool IsEmpty() const { return ptr == NULL; }
Buffer() { ptr = NULL; }
Buffer(size_t size) { ptr = new T[size]; }
Buffer(size_t size, const T& init) { ptr = new T[size]; Fill(ptr, ptr + size, init); }
~Buffer() { if(ptr) delete[] ptr; }
Buffer(size_t size) { New(size); }
Buffer(size_t size, const T& init) { New(size, init); }
~Buffer() { Free(); }
void operator=(Buffer&& v) { if(&v != this) { Clear(); ptr = v.ptr; v.ptr = NULL; } }
Buffer(Buffer&& v) { ptr = v.ptr; v.ptr = NULL; }
Buffer(size_t size, std::initializer_list<T> init) : Buffer(size) {
T *t = ptr; for(const auto& i : init) new (t++) T(i);
Buffer(size_t size, std::initializer_list<T> init) {
T *t = Malloc(size); for(const auto& i : init) new (t++) T(i);
}
Buffer(std::initializer_list<T> init) : Buffer(init.size(), init) {}
};

View file

@ -13,8 +13,7 @@ namespace Upp {
void OutOfMemoryPanic(size_t size)
{
char h[200];
sprintf(h, "Out of memory!\nRequested size: %lld B\nU++ allocated memory: %d KB",
(long long)size, MemoryUsedKb());
sprintf(h, "Out of memory!\nnU++ allocated memory: %d KB", MemoryUsedKb());
Panic(h);
}
@ -25,40 +24,34 @@ size_t Heap::big_count;
size_t Heap::sys_size;
size_t Heap::sys_count;
size_t Heap::huge_chunks;
size_t Heap::huge_4KB_count_max;
int MemoryUsedKb()
{
return int(4 * (Heap::huge_4KB_count - Heap::free_4KB));
}
int sKBLimit = INT_MAX;
void MemoryLimitKb(int kb)
int MemoryUsedKbMax()
{
sKBLimit = kb;
return int(4 * Heap::huge_4KB_count_max);
}
void DoPeakProfile();
void *SysAllocRaw(size_t size, size_t reqsize)
{
void *ptr = NULL;
if(MemoryUsedKb() < sKBLimit) {
#ifdef PLATFORM_WIN32
ptr = VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
#elif PLATFORM_LINUX
ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if(ptr == MAP_FAILED)
ptr = NULL;
#else
ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
if(ptr == MAP_FAILED)
ptr = NULL;
#endif
}
#ifdef PLATFORM_WIN32
ptr = VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
#elif PLATFORM_LINUX
ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if(ptr == MAP_FAILED)
ptr = NULL;
#else
ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
if(ptr == MAP_FAILED)
ptr = NULL;
#endif
if(!ptr)
OutOfMemoryPanic(size/*reqsize*/);
DoPeakProfile();
OutOfMemoryPanic(size);
return ptr;
}
@ -196,6 +189,7 @@ String AsString(const MemoryProfile& mem)
size_t asize = 0;
int fcount = 0;
size_t fsize = 0;
text << "Memory peak " << MemoryUsedKbMax() << "\n";
for(int i = 0; i < 1024; i++)
if(mem.allocated[i]) {
int sz = 4 * i;

View file

@ -30,6 +30,24 @@ EXITBLOCK {
}
#endif
int sKBLimit = INT_MAX;
void MemoryLimitKb(int kb)
{
sKBLimit = kb;
}
static MemoryProfile *sPeak;
MemoryProfile *PeakMemoryProfile()
{
if(sPeak)
return sPeak;
sPeak = (MemoryProfile *)MemoryAllocPermanent(sizeof(MemoryProfile));
memset((void *)sPeak, 0, sizeof(MemoryProfile));
return NULL;
}
void *Heap::HugeAlloc(size_t count) // count in 4kb pages
{
ASSERT(count);
@ -40,6 +58,14 @@ void *Heap::HugeAlloc(size_t count) // count in 4kb pages
#endif
huge_4KB_count += count;
if(huge_4KB_count > huge_4KB_count_max) {
huge_4KB_count_max = huge_4KB_count;
if(MemoryUsedKb() > sKBLimit)
Panic("MemoryLimitKb breached!");
if(sPeak)
Make(*sPeak);
}
if(!D::freelist[0]->next) { // initialization
for(int i = 0; i < 2; i++)

View file

@ -465,23 +465,6 @@ MemoryProfile::MemoryProfile()
ThreadHeap()->Make(*this);
}
static MemoryProfile *sPeak;
void DoPeakProfile()
{
if(sPeak)
ThreadHeap()->Make(*sPeak);
}
MemoryProfile *PeakMemoryProfile()
{
if(sPeak)
return sPeak;
sPeak = (MemoryProfile *)MemoryAllocPermanent(sizeof(MemoryProfile));
memset((void *)sPeak, 0, sizeof(MemoryProfile));
return NULL;
}
#endif
}