/*- * Copyright 2007 Guram Dukashvili * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ //--------------------------------------------------------------------------- #include //--------------------------------------------------------------------------- namespace ksys { //--------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////// // Memory manager ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //--------------------------------------------------------------------------- uint8_t MemoryManager::globalMemoryManagerHolder_[sizeof(MemoryManager)]; //--------------------------------------------------------------------------- void MemoryManager::initialize() { interlockedCompareExchangeAcquire(globalMemoryManager().initMutex_,-1,0); if( globalMemoryManager().initCount_ == 0 ) new (globalMemoryManagerHolder_) MemoryManager; globalMemoryManager().initCount_++; interlockedIncrement(globalMemoryManager().initMutex_,1); } //--------------------------------------------------------------------------- void MemoryManager::cleanup() { interlockedCompareExchangeAcquire(globalMemoryManager().initMutex_,-1,0); if( globalMemoryManager().initCount_ == 1 ) globalMemoryManager().~MemoryManager(); globalMemoryManager().initCount_--; interlockedIncrement(globalMemoryManager().initMutex_,1); } //--------------------------------------------------------------------------- MemoryManager::~MemoryManager() { clear(); } //--------------------------------------------------------------------------- MemoryManager::MemoryManager() : clusterSize_(0), allocatedSystemMemory_(0), allocatedMemory_(0), lock_(false), interlocked_(true) { #if defined(__WIN32__) || defined(__WIN64__) SYSTEM_INFO si; GetSystemInfo(&si); HANDLE hToken; BOOL r = OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken ); if( r != 0 ){ LUID luid; TOKEN_PRIVILEGES tp; /*r = LookupPrivilegeValue( NULL, SE_INC_BASE_PRIORITY_NAME, &luid ); if( r != 0 ){ tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; r = AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL ); }*/ r = LookupPrivilegeValue( NULL, SE_LOCK_MEMORY_NAME, &luid ); if( r != 0 ){ tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; r = AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL ); if( r != 0 && GetLastError() != ERROR_NOT_ALL_ASSIGNED ){ if( (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA32_ON_WIN64) && !isWow64() ){ union { SIZE_T (WINAPI * pGetLargePageMinimum)(); FARPROC ph; }; ph = GetProcAddress(GetModuleHandleA("KERNEL32.DLL"),"GetLargePageMinimum"); if( pGetLargePageMinimum != NULL && pGetLargePageMinimum() > si.dwAllocationGranularity ){ clusterSize_ = pGetLargePageMinimum(); flags_ = MEM_LARGE_PAGES; bool locked; void * memory = sysalloc(clusterSize_,true,locked,true); if( memory == NULL ){ clusterSize_ = 0; } else { sysfree(memory,clusterSize_,locked,true); } } } } } CloseHandle(hToken); } if( clusterSize_ < si.dwAllocationGranularity ){ clusterSize_ = si.dwAllocationGranularity; flags_ = 0; } #else clusterSize_ = getpagesize() * 16; #endif align_ = 1; } //--------------------------------------------------------------------------- MemoryManager & MemoryManager::clear() { EmbeddedListNode * sdsNode = sizes_.first(), * sdsNode2; while( sdsNode != NULL ){ SizeDescriptors * sds = &SizeDescriptors::listObject(*sdsNode); for( intptr_t i = sds->count() - 1; i >= 0; i-- ){ SizeDescriptor * sd = sds->sizes_ + i; EmbeddedListNode * csNode = sd->clusters_.first(), * csNode2; while( csNode != NULL ){ Clusters * cs = &Clusters::listObject(*csNode); EmbeddedListNode * cNode = cs->lru_.first(); while( cNode != NULL ){ Cluster * c = &Cluster::listObject(*cNode); if( c->head_ == NULL ) sysfree(c->memory_,c->size_,c->locked_,true); cNode = cNode->next(); } csNode2 = csNode->next(); sysfree(cs,cs->size_,cs->locked_,true); csNode = csNode2; } } sdsNode2 = sdsNode->next(); sysfree(sds,sds->size_,sds->locked_,true); sdsNode = sdsNode2; } sizes_.clear(); clustersTree_.clear(); allocatedSystemMemory_ = 0; allocatedMemory_ = 0; return *this; } //--------------------------------------------------------------------------- EmbeddedListNode * MemoryManager::findSDSNode(uintptr_t size,uintptr_t & fsize,uintptr_t & lsize) { fsize = lsize = 0; EmbeddedListNode * sdsNode = sizes_.first(); while( sdsNode != NULL ){ SizeDescriptors * sds = &SizeDescriptors::listObject(*sdsNode); fsize = sds->sizes_[0].size_; lsize = sds->sizes_[sds->count() - 1].size_; if( size < fsize || size <= lsize ) break; sdsNode = sdsNode->next(); } return sdsNode; } //--------------------------------------------------------------------------- EmbeddedListNode * MemoryManager::findCSNode(SizeDescriptor * sd,uintptr_t size,bool & ffc) { EmbeddedListNode * csNode = sd->clusters_.first(); if( csNode != NULL ){ Clusters * cs = &Clusters::listObject(*csNode); ffc = cs->lru_.count() > 0 && Cluster::listObject(*cs->lru_.first()).count_ > 0; if( !ffc ){ uintptr_t a = 1; if( size == 3 ) a = clusterSize_ / 0x3000000u + (clusterSize_ < 0x3000000u); else if( size == 2 ) a = clusterSize_ / 0x20000u + (clusterSize_ < 0x20000u); else if( size == 1 ) a = clusterSize_ / 0x100u + (clusterSize_ < 0x100u); if( cs->free_.count() < a ) csNode = NULL; } } return csNode; } //--------------------------------------------------------------------------- void * MemoryManager::malloc(uintptr_t size,bool lock,bool & locked) { void * p = NULL; if( size > 0 ){ if( this == &globalMemoryManager() ) initialize(); { AutoLock ilock; if( interlocked_ ) ilock.setLocked(mutex_); size += -intptr_t(size) & (align_ - 1); uintptr_t fsize, lsize; EmbeddedListNode * sdsNode = findSDSNode(size,fsize,lsize); SizeDescriptors * sds = NULL; if( sdsNode == NULL || size < fsize ){ sds = (SizeDescriptors *) sysalloc(clusterSize_,lock,locked,true); if( sds != NULL ){ new (sds) SizeDescriptors; sds->size_ = clusterSize_; sds->count_ = 0; sds->locked_ = locked; uintptr_t k = sds->count(), j = (size / k) * k + 1; // zero size not used for( intptr_t i = k - 1; i >= 0; i-- ) new (sds->sizes_ + i) SizeDescriptor(sds,j + i); if( sdsNode == NULL ) sizes_.insToTail(*sds); else sizes_.insBefore(SizeDescriptors::listObject(*sdsNode),*sds); sdsNode = &SizeDescriptors::listNode(*sds); } } else { sds = &SizeDescriptors::listObject(*sdsNode); } if( sds != NULL ){ SizeDescriptor * sd = &sds->sizes_[(size - sds->sizes_[0].size_) / align_]; bool ffc = false; EmbeddedListNode * csNode = findCSNode(sd,size,ffc); Clusters * cs = NULL; if( csNode == NULL ){ cs = (Clusters *) sysalloc(clusterSize_,lock,locked,true); if( cs != NULL ){ new (cs) Clusters(sd,clusterSize_); cs->locked_ = locked; for( intptr_t i = cs->count() - 1; i >= 0; i-- ){ new (cs->clusters_ + i) Cluster(cs); cs->free_.insToHead(cs->clusters_[i]); } sd->clusters_.insToHead(*cs); csNode = &Clusters::listNode(*cs); } } else { cs = &Clusters::listObject(*csNode); } if( cs != NULL ){ EmbeddedList & list = ffc ? cs->lru_ : cs->free_; uintptr_t cc = 1, bs = clusterSize_; if( size >= 4 ){ } else if( size == 3 && clusterSize_ > 0x3000000u ){ cc = clusterSize_ / 0x3000000u; bs = 0x3000000u; } else if( size == 2 && clusterSize_ > 0x20000u ){ cc = clusterSize_ / 0x20000u; bs = 0x20000u; } else if( size == 1 && clusterSize_ > 0x100u ){ cc = clusterSize_ / 0x100u; bs = 0x100u; } Cluster * c, * chead = NULL; for( uintptr_t i = 0; i < cc; i++ ){ c = &Cluster::listObject(*list.first()); if( c->memory_ != NULL ){ chead = c; list.remove(*c); break; } if( chead == NULL ){ chead = c; c->size_ = size > clusterSize_ ? size + (-intptr_t(size) & (clusterSize_ - 1)) : clusterSize_; c->fsize_ = bs; c->bsize_ = size; c->memory_ = (uint8_t *) sysalloc(c->size_,lock,locked,true); if( c->memory_ == NULL ) break; c->locked_ = locked; c->initialize(); c->head_ = c; list.remove(*c); } else { c->cs_ = chead->cs_; c->size_ = chead->size_; c->fsize_ = chead->fsize_; c->bsize_ = chead->bsize_; c->memory_ = chead->memory_ + i * bs; c->head_ = chead; c->next_ = chead->next_; chead->next_ = c; c->initialize(); list.remove(*c); cs->lru_.insToHead(*c); } clustersTree_.insert(*c); } c = chead; if( c->memory_ != NULL ){ p = c->memory_ + c->index_ * size; if( size == 1 ){ c->index_ = *(uint8_t *) p; } else if( size == 2 ){ c->index_ = *(uint16_t *) p; } else if( size == 3 ){ c->index_ = *(uint32_t *) p & 0xFFFFFF; } else if( size > ~uint32_t(0) - 1 ){ c->index_ = *(uintptr_t *) p; } else { c->index_ = *(uint32_t *) p; } c->count_--; if( c->count_ == 0 ) cs->lru_.insToTail(*c); else cs->lru_.insToHead(*c); sds->count_++; allocatedMemory_ += size; locked = c->locked_; } } } } if( p == NULL && this == &globalMemoryManager() ) cleanup(); } return p; } //--------------------------------------------------------------------------- void * MemoryManager::realloc(void * ptr,uintptr_t size,bool lock,bool & locked) { if( size == 0 ){ if( ptr != NULL ) free(ptr); return NULL; } Cluster * cp = NULL; if( ptr != NULL ){ AutoLock ilock; if( interlocked_ ) ilock.setLocked(mutex_); Cluster c(NULL,ptr); cp = clustersTree_.find(c); if( cp == NULL ){ ilock.unLock(); return ::realloc(ptr,size); } if( (uintptr_t(ptr) - uintptr_t(cp->memory_)) % cp->bsize_ != 0 ){ ilock.unLock(); #if defined(__WIN32__) || defined(__WIN64__) SetLastError(ERROR_INVALID_DATA); #else errno = EINVAL; #endif int32_t err = oserror() + errorOffset; Exception e(err,__PRETTY_FUNCTION__); e.writeStdError(); return NULL; } locked = cp->locked_; if( size <= cp->bsize_ && size >= (cp->bsize_ & ~(align_ - 1)) ) return ptr; } void * p = malloc(size,lock,locked); if( p != NULL && cp != NULL ){ #if HAVE_BCOPY bcopy(p,ptr,size > cp->bsize_ ? cp->bsize_ : size); #else memcpy(p,ptr,size > cp->bsize_ ? cp->bsize_ : size); #endif free(ptr); } return p; } //--------------------------------------------------------------------------- void MemoryManager::free(void * ptr) { if( ptr != NULL ){ { AutoLock ilock; if( interlocked_ ) ilock.setLocked(mutex_); Cluster c(NULL,ptr), * cp = clustersTree_.find(c); if( cp == NULL ){ ilock.unLock(); ::free(ptr); return; } if( (uintptr_t(ptr) - uintptr_t(cp->memory_)) % cp->bsize_ != 0 ){ ilock.unLock(); #if defined(__WIN32__) || defined(__WIN64__) SetLastError(ERROR_INVALID_DATA); #else errno = EINVAL; #endif int32_t err = oserror() + errorOffset; Exception e(err,__PRETTY_FUNCTION__); e.writeStdError(); return; } uintptr_t j = cp->size_ / cp->bsize_; if( cp->bsize_ == 1 && j > 256 ){ j = 256; } else if( cp->bsize_ == 2 && j > 65536 ){ j = 65536; } else if( cp->bsize_ == 3 && j > 16777216 ){ j = 16777216; } if( cp->count_ >= j ){ #if defined(__WIN32__) || defined(__WIN64__) SetLastError(ERROR_INVALID_DATA); #else errno = EINVAL; #endif int32_t err = oserror() + errorOffset; Exception e(err,utf8::String("chunk already free ") + __PRETTY_FUNCTION__); e.writeStdError(); return; } if( cp->count_ > 0 ){ if( cp->bsize_ == 1 ){ *(uint8_t *) ptr = uint8_t(cp->index_); } else if( cp->bsize_ == 2 ){ *(uint16_t *) ptr = uint16_t(cp->index_); } else if( cp->bsize_ == 3 ){ *(uint16_t *) ptr = uint16_t(cp->index_); *((uint8_t *) ptr + sizeof(uint16_t)) = uint8_t(cp->index_ >> 16); } else if( cp->bsize_ > ~uint32_t(0) - 1 ){ *(uintptr_t *) ptr = cp->index_; } else { *(uint32_t *) ptr = uint32_t(cp->index_); } } cp->index_ = ((uint8_t *) ptr - cp->memory_) / cp->bsize_; cp->count_++; cp->cs_->sd_->sds_->count_--; allocatedMemory_ -= cp->bsize_; if( cp->count_ == j ){ Cluster * c = cp->head_; if( c != NULL ){ for(;;){ assert( c->count_ <= j ); if( c->count_ != j ) return; c = c->next_; if( c == NULL ) break; } c = cp->head_; for(;;){ c->cs_->lru_.remove(*c); if( c != c->head_ ){ clustersTree_.remove(*c); c->memory_ = NULL; c->cs_->free_.insToHead(*c); } c = c->next_; if( c == NULL ) break; } cp = cp->head_; } else { cp->cs_->lru_.remove(*cp); } clustersTree_.remove(*cp); sysfree(cp->memory_,cp->size_,cp->locked_,true); cp->memory_ = NULL; cp->cs_->free_.insToHead(*cp); if( cp->cs_->free_.count() == cp->cs_->count() ){ SizeDescriptor * sd = cp->cs_->sd_; sd->clusters_.remove(*cp->cs_); sysfree(cp->cs_,cp->cs_->size_,cp->cs_->locked_,true); if( sd->sds_->count_ == 0 ){ sizes_.remove(*sd->sds_); sysfree(sd->sds_,sd->sds_->size_,sd->sds_->locked_,true); } } } else { cp->cs_->lru_.remove(*cp); cp->cs_->lru_.insToHead(*cp); } } if( this == &globalMemoryManager() ) cleanup(); } } //--------------------------------------------------------------------------- MemoryManager & MemoryManager::sysfree(void * memory,uintptr_t size,bool locked,bool noThrow) { if( memory != NULL ){ #if defined(__WIN32__) || defined(__WIN64__) BOOL r = TRUE; if( locked ){ r = VirtualUnlock(memory,size); if( r == 0 ){ int32_t err = GetLastError() + errorOffset; if( !noThrow ) newObjectV1C2(err,__PRETTY_FUNCTION__)->throwSP(); } } if( r != 0 ){ r = VirtualFree(memory,size,MEM_DECOMMIT); if( r == 0 ){ int32_t err = GetLastError() + errorOffset; if( !noThrow ) newObjectV1C2(err,__PRETTY_FUNCTION__)->throwSP(); } } #else int r = 0; if( locked ){ r = munlock(memory,size); if( r != 0 ){ int32_t err = errno; if( !noThrow ) newObjectV1C2(err,__PRETTY_FUNCTION__)->throwSP(); } } if( r == 0 ){ errno = 0; ::free(memory); if( errno != 0 ){ int32_t err = errno; if( !noThrow ) newObjectV1C2(err,__PRETTY_FUNCTION__)->throwSP(); } } #endif allocatedSystemMemory_ -= size; } return *this; } //--------------------------------------------------------------------------- #if defined(__WIN32__) || defined(__WIN64__) static BOOL sysallocHelper(uintptr_t size) { SIZE_T minimumWorkingSetSize, maximumWorkingSetSize; BOOL r; r = GetProcessWorkingSetSize(GetCurrentProcess(),&minimumWorkingSetSize,&maximumWorkingSetSize); if( r != 0 ){ minimumWorkingSetSize += size; if( maximumWorkingSetSize < minimumWorkingSetSize ) maximumWorkingSetSize = minimumWorkingSetSize; r = SetProcessWorkingSetSize(GetCurrentProcess(),minimumWorkingSetSize,maximumWorkingSetSize); } return r; } #endif //--------------------------------------------------------------------------- void * MemoryManager::sysalloc(uintptr_t size,bool lock,bool & locked,bool noThrow) { void * memory = NULL; locked = false; #if defined(__WIN32__) || defined(__WIN64__) memory = VirtualAlloc(NULL,size,flags_ | MEM_COMMIT,PAGE_READWRITE); if( memory == NULL ){ int32_t err = GetLastError() + errorOffset; if( !noThrow ) newObjectV1C2(err,__PRETTY_FUNCTION__)->throwSP(); } else { l1: if( lock && !(locked = VirtualLock(memory,size) != 0) ){ int32_t err = GetLastError(); if( err == ERROR_WORKING_SET_QUOTA ){ if( sysallocHelper(size) != 0 ) goto l1; err = GetLastError(); } else if( err == ERROR_INVALID_PARAMETER ){ VirtualFree(memory,size,MEM_DECOMMIT); SetLastError(err); return NULL; } // Exception e(err + errorOffset,"VirtualLock(" + utf8::int2Str(size) + ") " + __PRETTY_FUNCTION__); // e.writeStdError(); } allocatedSystemMemory_ += size; } #else memory = ::malloc(size); if( memory == NULL ){ int32_t err = errno; if( !noThrow ) newObjectV1C2(err,__PRETTY_FUNCTION__)->throwSP(); } else { if( lock && !(locked = mlock(memory,size) == 0) ){ // int32_t err = errno; // Exception e(err,"mlock(" + utf8::int2Str(size) + ") " + __PRETTY_FUNCTION__); // e.writeStdError(); } allocatedSystemMemory_ += size; } #endif assert( (uintptr_t(memory) & (getpagesize() - 1)) == 0 ); // check address align return memory; } //--------------------------------------------------------------------------- void heapBenchmark() { AutoPtr rnd(newObject()); MemoryManager hm; uintptr_t elCount = 4 * 1024 * 1024; Array sizes; Array ptrs; sizes.resize(elCount); ptrs.resize(elCount); for( uintptr_t i = 0; i < elCount; i++ ){ sizes[i] = uintptr_t(rnd->random(128) + 1); ptrs[i] = NULL; } uint64_t t, seqMallocTime = 0, seqFreeTime = 0, rndTime, allocatedSystemMemory, allocatedMemory; t = gettimeofday(); for( uintptr_t i = 0; i < elCount; i++ ){ ptrs[i] = hm.malloc(sizes[i]); } seqMallocTime += gettimeofday() - t; allocatedSystemMemory = hm.allocatedSystemMemory(); allocatedMemory = hm.allocatedMemory(); t = gettimeofday(); for( uintptr_t i = 0; i < elCount; i++ ){ hm.free(ptrs[i]); ptrs[i] = NULL; } seqFreeTime += gettimeofday() - t; fprintf(stderr,"seq mallocs: %8"PRIu64".%04"PRIu64" mps, ellapsed %s\n", uint64_t(elCount) * 1000000u / seqMallocTime, uint64_t(elCount) * 10000u * 1000000u / seqMallocTime - uint64_t(elCount) * 1000000u / seqMallocTime * 10000u, (const char *) utf8::elapsedTime2Str(seqMallocTime).getOEMString() ); fprintf(stderr,"seq frees: %8"PRIu64".%04"PRIu64" fps, ellapsed %s\n", uint64_t(elCount) * 1000000u / seqFreeTime, uint64_t(elCount) * 10000u * 1000000u / seqFreeTime - uint64_t(elCount) * 1000000u / seqFreeTime * 10000u, (const char *) utf8::elapsedTime2Str(seqFreeTime).getOEMString() ); fprintf(stderr, "memory used area: %s\n", (const char *) formatByteLength( allocatedMemory, allocatedSystemMemory, "P" ).getOEMString() ); seqMallocTime = seqFreeTime = 0; t = gettimeofday(); for( uintptr_t i = 0; i < elCount; i++ ){ ptrs[i] = kmalloc(sizes[i]); } seqMallocTime += gettimeofday() - t; allocatedSystemMemory = hm.allocatedSystemMemory(); allocatedMemory = hm.allocatedMemory(); t = gettimeofday(); for( uintptr_t i = 0; i < elCount; i++ ){ kfree(ptrs[i]); ptrs[i] = NULL; } seqFreeTime += gettimeofday() - t; fprintf(stderr,"seq system mallocs: %8"PRIu64".%04"PRIu64" mps, ellapsed %s\n", uint64_t(elCount) * 1000000u / seqMallocTime, uint64_t(elCount) * 10000u * 1000000u / seqMallocTime - uint64_t(elCount) * 1000000u / seqMallocTime * 10000u, (const char *) utf8::elapsedTime2Str(seqMallocTime).getOEMString() ); fprintf(stderr,"seq system frees: %8"PRIu64".%04"PRIu64" fps, ellapsed %s\n", uint64_t(elCount) * 1000000u / seqFreeTime, uint64_t(elCount) * 10000u * 1000000u / seqFreeTime - uint64_t(elCount) * 1000000u / seqFreeTime * 10000u, (const char *) utf8::elapsedTime2Str(seqFreeTime).getOEMString() ); // random test Array indices; indices.resize(elCount); for( uintptr_t i = 0; i < elCount; i++ ){ indices[i] = uintptr_t(rnd->random(elCount)); } rndTime = 0; t = gettimeofday(); for( uintptr_t i = 0; i < elCount; i++ ){ if( ptrs[indices[i]] == NULL ){ ptrs[indices[i]] = hm.malloc(sizes[i]); } else { hm.free(ptrs[indices[i]]); ptrs[indices[i]] = NULL; } } rndTime += gettimeofday() - t; fprintf(stderr,"rnd mallocs - frees: %8"PRIu64".%04"PRIu64" mfps, ellapsed %s\n", uint64_t(elCount) * 1000000u / rndTime, uint64_t(elCount) * 10000u * 1000000u / rndTime - uint64_t(elCount) * 1000000u / rndTime * 10000u, (const char *) utf8::elapsedTime2Str(rndTime).getOEMString() ); allocatedSystemMemory = hm.allocatedSystemMemory(); allocatedMemory = hm.allocatedMemory(); fprintf(stderr, "memory used area: %s\n", (const char *) formatByteLength( allocatedMemory, allocatedSystemMemory, "P" ).getOEMString() ); for( uintptr_t i = 0; i < elCount; i++ ){ hm.free(ptrs[i]); ptrs[i] = NULL; } rndTime = 0; t = gettimeofday(); for( uintptr_t i = 0; i < elCount; i++ ){ if( ptrs[indices[i]] == NULL ){ ptrs[indices[i]] = kmalloc(sizes[i]); } else { kfree(ptrs[indices[i]]); ptrs[indices[i]] = NULL; } } rndTime += gettimeofday() - t; fprintf(stderr,"rnd system mallocs - frees: %8"PRIu64".%04"PRIu64" mfps, ellapsed %s\n", uint64_t(elCount) * 1000000u / rndTime, uint64_t(elCount) * 10000u * 1000000u / rndTime - uint64_t(elCount) * 1000000u / rndTime * 10000u, (const char *) utf8::elapsedTime2Str(rndTime).getOEMString() ); for( uintptr_t i = 0; i < elCount; i++ ){ kfree(ptrs[i]); ptrs[i] = NULL; } } //--------------------------------------------------------------------------- } // namespace ksys //---------------------------------------------------------------------------