mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Core: Heap issues
git-svn-id: svn://ultimatepp.org/upp/trunk@13369 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
086efe4341
commit
acd196b8dc
6 changed files with 84 additions and 50 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue