// Report heap sizes and occupancy before and after GC void MemMgr::ReportHeapSizes(const char *phase) { POLYUNSIGNED alloc = 0, nonAlloc = 0, inAlloc = 0, inNonAlloc = 0; for (unsigned i = 0; i < nlSpaces; i++) { LocalMemSpace *sp = lSpaces[i]; if (sp->allocationSpace) { alloc += sp->spaceSize(); inAlloc += sp->allocatedSpace(); } else { nonAlloc += sp->spaceSize(); inNonAlloc += sp->allocatedSpace(); } } Log("Heap: %s Major heap used ", phase); LogSize(inNonAlloc); Log(" of "); LogSize(nonAlloc); Log(" (%1.0f%%). Alloc space used ", (float)inNonAlloc / (float)nonAlloc * 100.0F); LogSize(inAlloc); Log(" of "); LogSize(alloc); Log(" (%1.0f%%). Total space ", (float)inAlloc / (float)alloc * 100.0F); LogSize(spaceForHeap); Log(" %1.0f%% full.\n", (float)(inAlloc + inNonAlloc) / (float)spaceForHeap * 100.0F); }
// Set the initial size based on any parameters specified on the command line void HeapSizeParameters::SetHeapParameters(unsigned minsize, unsigned maxsize, unsigned percent) { minHeapSize = K_to_words(minsize); // If these overflow assume the result will be zero maxHeapSize = K_to_words(maxsize); POLYUNSIGNED memsize = 0; if (minHeapSize == 0 || maxHeapSize == 0) memsize = GetPhysicalMemorySize() / sizeof(PolyWord); // If no maximum is given default it to 80% of the physical memory. // This allows some space for the OS and other things. if (maxHeapSize == 0 || maxHeapSize > MAXIMUMADDRESS) { if (memsize == 0) maxHeapSize = MAXIMUMADDRESS; else maxHeapSize = memsize - memsize / 5; } // Set the initial size to the minimum if that has been provided. POLYUNSIGNED initialSize = minHeapSize; if (initialSize == 0) { // If no -H option was given set the default initial size to a quarter of the memory. if (memsize == 0) // Unable to determine memory size so default to 64M. initialSize = 64 * 1024 * 1024; else initialSize = memsize / 4; } // Initially we divide the space equally between the major and // minor heaps. That means that there will definitely be space // for the first minor GC to copy its data. This division can be // changed later on. gMem.SetSpaceForHeap(initialSize); gMem.SetSpaceBeforeMinorGC(initialSize/2); lastFreeSpace = initialSize; highWaterMark = initialSize; if (percent == 0) userGCRatio = 1.0 / 9.0; // Default to 10% GC to 90% application else userGCRatio = (float)percent / (float)(100 - percent); predictedRatio = lastMajorGCRatio = userGCRatio; if (debugOptions & DEBUG_HEAPSIZE) { Log("Heap: Initial settings: Initial heap "); LogSize(initialSize); Log(" minimum "); LogSize(minHeapSize); Log(" maximum "); LogSize(maxHeapSize); Log(" target ratio %f\n", userGCRatio); } }
// Estimate the GC cost for a given heap size. The result is the ratio of // GC time to application time. // This is really guesswork. double HeapSizeParameters::costFunction(POLYUNSIGNED heapSize, bool withSharing, bool withSharingCost) { POLYUNSIGNED heapSpace = gMem.SpaceForHeap() < highWaterMark ? gMem.SpaceForHeap() : highWaterMark; POLYUNSIGNED currentFreeSpace = heapSpace - currentSpaceUsed; POLYUNSIGNED averageFree = (lastFreeSpace + currentFreeSpace) / 2; POLYUNSIGNED spaceUsed = currentSpaceUsed; if (heapSize <= currentSpaceUsed) return 1.0E6; // If we run the sharing pass the live space will be smaller. if (withSharing) spaceUsed -= (POLYUNSIGNED)((double)currentSpaceUsed * sharingRecoveryRate); POLYUNSIGNED estimatedFree = heapSize - spaceUsed; // The cost scales as the inverse of the amount of free space. double result = lastMajorGCRatio * (double)averageFree / (double)estimatedFree; // If we run the sharing pass the GC cost will increase. if (withSharing && withSharingCost) result += result*sharingCostFactor; // The paging contribution depends on the page limit double pagingCost = 0.0; if (pagingLimitSize != 0) { double factor = ((double)heapSize - (double)pagingLimitSize) / (double)pagingLimitSize * PAGINGCOSTSTEEPNESS; pagingCost = PAGINGCOSTFACTOR * exp(factor); result += pagingCost; } if (debugOptions & DEBUG_HEAPSIZE) { Log("Heap: Cost for heap of size "); LogSize(heapSize); Log(" is %2.2f with paging contributing %2.2f with%s sharing pass.\n", result, pagingCost, withSharing ? "" : "out"); } return result; }
// Called in the minor GC if a GC thread needs to grow the heap. // Returns zero if the heap cannot be grown. "space" is the space required for the // object (and length field) in case this is larger than the default size. LocalMemSpace *HeapSizeParameters::AddSpaceInMinorGC(POLYUNSIGNED space, bool isMutable) { // See how much space is allocated to the major heap. POLYUNSIGNED spaceAllocated = gMem.CurrentHeapSize() - gMem.CurrentAllocSpace(); // The new segment is either the default size or as large as // necessary for the object. POLYUNSIGNED spaceSize = gMem.DefaultSpaceSize(); if (space > spaceSize) spaceSize = space; // We allow for extension if the total heap size after extending it // plus one allocation area of the default size would not be more // than the allowed heap size. if (spaceAllocated + spaceSize + gMem.DefaultSpaceSize() <= gMem.SpaceForHeap()) { LocalMemSpace *sp = gMem.NewLocalSpace(spaceSize, isMutable); // Return the space or zero if it failed // If this is the first time the allocation failed report it. if (sp == 0 && (debugOptions & DEBUG_HEAPSIZE) && lastAllocationSucceeded) { Log("Heap: Allocation of new heap segment size "); LogSize(spaceSize); Log(" failed. Limit reached?\n"); } lastAllocationSucceeded = sp != 0; return sp; } return 0; // Insufficient space }
void SymbianLog::printMessage(const char* level, const char* msg, PLATFORM_VA_LIST argList) { iSemaphore.Wait(); StringBuffer currentTime = createCurrentTime(true); TInt err = file.Open(fsSession, iLogName, EFileWrite|EFileShareAny); TInt pos = 0; if (err == KErrNotFound) { // First time: file does not exist. Create it. err = file.Create(fsSession, iLogName, EFileWrite|EFileShareAny); if (err != KErrNone) { setErrorF(err, "SymbianLog: could not open log file (code %d)", err); goto finally; } StringBuffer header = createHeader(); RBuf8 data; data.Assign(stringBufferToNewBuf8(header)); file.Write(data); data.Close(); } else { err = file.Seek(ESeekEnd, pos); if (err != KErrNone) { setErrorF(err, "SymbianLog: seek error on log file (code %d)", err); goto finally; } } { // Write the data StringBuffer line, data; line.sprintf("%s -%s- %s", currentTime.c_str(), level, msg); data.vsprintf(line.c_str(), argList); data.append("\n"); RBuf8 buf; buf.Assign(stringBufferToNewBuf8(data)); file.Write(buf); buf.Close(); } finally: file.Close(); // we need closed file to operate on it if ( LogSize() > SYMBIAN_LOG_SIZE ){ // roll log file RollLogFile(); } iSemaphore.Signal(); }
// Called after a minor GC. Currently does nothing. // See also adjustHeapSize for adjustments after a major GC. bool HeapSizeParameters::AdjustSizeAfterMinorGC(POLYUNSIGNED spaceAfterGC, POLYUNSIGNED spaceBeforeGC) { POLYUNSIGNED spaceCopiedOut = spaceAfterGC-spaceBeforeGC; TIMEDATA gc, total; minorGCsSinceMajor++; // The major costs are cumulative so we use those gc.add(majorGCSystemCPU); gc.add(majorGCUserCPU); total.add(gc); total.add(majorNonGCSystemCPU); total.add(majorNonGCUserCPU); float g = gc.toSeconds() / total.toSeconds(); if (debugOptions & DEBUG_HEAPSIZE) { Log("Heap: Space before "); LogSize(spaceBeforeGC); Log(", space after "); LogSize(spaceAfterGC); Log("\n"); Log("Heap: Minor resizing factors g = %f, recent pf = %ld, cumulative pf = %ld\n", g, minorGCPageFaults, majorGCPageFaults); } if (highWaterMark < gMem.CurrentHeapSize()) highWaterMark = gMem.CurrentHeapSize(); POLYUNSIGNED nextLimit = highWaterMark + highWaterMark / 32; if (nextLimit > gMem.SpaceForHeap()) nextLimit = gMem.SpaceForHeap(); // Set the space available for the allocation area to be the difference between the // total heap size and the allowed heap size together with as much space as we copied // on this GC. That allows for the next minor GC to copy the same amount without // extending the heap. If the next minor GC adds more than this the heap will be // extended and a corresponding amount deducted so that the heap shrinks again. POLYUNSIGNED nonAlloc = gMem.CurrentHeapSize() - gMem.CurrentAllocSpace() + spaceCopiedOut; // TODO: If we have limited the space to the high water mark + 1/32 but that is less // than we really need we should increase it further. POLYUNSIGNED allowedAlloc = nonAlloc >= nextLimit ? 0 : nextLimit - nonAlloc; // If we hit the limit at the last major GC we have to be much more careful. // If the minor GC cannot allocate a major GC space when it needs it the minor // GC will fail immediately and a major GC will be started. It's better to // risk doing more minor GCs than we need by making the allocation area smaller // rather than run out of space. if (allocationFailedBeforeLastMajorGC) allowedAlloc = allowedAlloc / 2; if (gMem.CurrentAllocSpace() != allowedAlloc) { if (debugOptions & DEBUG_HEAPSIZE) { Log("Heap: Adjusting space for allocation area from "); LogSize(gMem.SpaceBeforeMinorGC()); Log(" to "); LogSize(allowedAlloc); Log("\n"); } gMem.SetSpaceBeforeMinorGC(allowedAlloc); if (allowedAlloc < gMem.DefaultSpaceSize() * 2 || minorGCPageFaults > 100) return false; // Trigger full GC immediately. } // Trigger a full GC if the live data is very large or if we have exceeeded // the target ratio over several GCs (this smooths out small variations). if ((minorGCsSinceMajor > 4 && g > predictedRatio*0.8) || majorGCPageFaults > 100) fullGCNextTime = true; return true; }
// Called at the end of collection. This is where we should do the // fine adjustment of the heap size to minimise the GC time. // Growing the heap is just a matter of adjusting the limits. We // don't actually need to allocate the space here. // See also adjustHeapSizeAfterMinorGC for adjustments after a minor GC. void HeapSizeParameters::AdjustSizeAfterMajorGC(POLYUNSIGNED wordsRequired) { // Cumulative times since the last major GC TIMEDATA gc, nonGc; gc.add(majorGCSystemCPU); gc.add(majorGCUserCPU); nonGc.add(majorNonGCSystemCPU); nonGc.add(majorNonGCUserCPU); if (highWaterMark < heapSizeAtStart) highWaterMark = heapSizeAtStart; POLYUNSIGNED heapSpace = gMem.SpaceForHeap() < highWaterMark ? gMem.SpaceForHeap() : highWaterMark; currentSpaceUsed = 0; for (unsigned i = 0; i < gMem.nlSpaces; i++) { currentSpaceUsed += gMem.lSpaces[i]->allocatedSpace(); } POLYUNSIGNED currentFreeSpace = heapSpace - currentSpaceUsed; if (currentFreeSpace < wordsRequired) currentFreeSpace = 0; else currentFreeSpace -= wordsRequired; // The times for all the minor GCs up to this. The cost of this (major) GC // is actually in minorGCUserCPU/minorGCSystemCPU. TIMEDATA minorGC; minorGC.add(gc); minorGC.sub(minorGCUserCPU); minorGC.sub(minorGCSystemCPU); if (performSharingPass) { // We ran the sharing pass last time: calculate the actual recovery rate. POLYUNSIGNED originalSpaceUsed = currentSpaceUsed + sharingWordsRecovered; sharingRecoveryRate = (double)sharingWordsRecovered / (double)originalSpaceUsed; if (debugOptions & DEBUG_HEAPSIZE) Log("Heap: Sharing recovery rate was %0.3f and cost %0.3f seconds (%0.3f%% of total).\n", sharingRecoveryRate, sharingCPU.toSeconds(), sharingCPU.toSeconds() / gc.toSeconds()); // The cost factor is the ratio of the cost of sharing to the cost without. sharingCostFactor = sharingCPU.toSeconds() / (gc.toSeconds() - sharingCPU.toSeconds()); // Subtract the sharing cost from the GC cost because the initial estimate is // the cost without running the sharing pass. gc.sub(sharingCPU); } if (gc.toSeconds() != 0.0 && nonGc.toSeconds() != 0.0) lastMajorGCRatio = gc.toSeconds() / nonGc.toSeconds(); if (debugOptions & DEBUG_HEAPSIZE) { Log("Heap: GC cpu time %2.3f non-gc time %2.3f ratio %0.3f for free space ", gc.toSeconds(), nonGc.toSeconds(), lastMajorGCRatio); LogSize((lastFreeSpace + currentFreeSpace)/2); Log("\n"); Log("Heap: GC real time %2.3f non-gc time %2.3f ratio %0.3f\n", majorGCReal.toSeconds(), majorNonGCReal.toSeconds(), majorGCReal.toSeconds()/majorNonGCReal.toSeconds()); Log("Heap: Total of minor GCs %2.3f, %2.3f of total\n", minorGC.toSeconds(), minorGC.toSeconds() / gc.toSeconds()); } // Calculate the paging threshold. if (pagingLimitSize != 0 || majorGCPageFaults != 0) { if (majorGCPageFaults == 0) majorGCPageFaults = 1; // Less than one // Some paging detected. The expression here is the inverse of the one used to // compute the paging contribution in the cost function. double scaleFactor = 1.0 + log((double)majorGCPageFaults / PAGINGCOUNTFACTOR) / PAGINGCOSTSTEEPNESS; ASSERT(scaleFactor > 0.0); POLYUNSIGNED newLimit = (POLYUNSIGNED)((double)heapSpace / scaleFactor); if (pagingLimitSize == 0) pagingLimitSize = newLimit; else pagingLimitSize = (newLimit + pagingLimitSize) / 2; } if (allocationFailedBeforeLastMajorGC) { // If the last allocation failed then we may well have reached the // maximum available memory. Set the paging limit to be the current // heap size. We want to avoid hitting the limit because typically // that happens when we try to extend the major heap in a minor GC // resulting in the minor GC failing and a major GC starting. if (pagingLimitSize == 0 || heapSizeAtStart < pagingLimitSize) pagingLimitSize = heapSizeAtStart; } if (pagingLimitSize != 0 && (debugOptions & DEBUG_HEAPSIZE)) { Log("Heap: Paging threshold adjusted to "); LogSize(pagingLimitSize); Log(" with %ld page faults\n", majorGCPageFaults); } // Calculate the new heap size and the predicted cost. POLYUNSIGNED newHeapSize; double cost; bool atTarget = getCostAndSize(newHeapSize, cost, false); // If we have been unable to allocate any more memory we may already // be at the limit. if (allocationFailedBeforeLastMajorGC && newHeapSize > heapSizeAtStart) { cost = costFunction(heapSizeAtStart, false, true); atTarget = false; } if (atTarget) { // We are at the target level. We don't want to attempt sharing. performSharingPass = false; cumulativeSharingSaving = 0; } else { POLYUNSIGNED newHeapSizeWithSharing; double costWithSharing; // Get the cost and heap size if sharing was enabled. If we are at the // limit, though, we need to work using the size we can achieve. if (! allocationFailedBeforeLastMajorGC) (void)getCostAndSize(newHeapSizeWithSharing, costWithSharing, true); else { newHeapSizeWithSharing = heapSizeAtStart; costWithSharing = costFunction(heapSizeAtStart, true, true); } // Run the sharing pass if that would give a lower cost. // Subtract the cumulative saving that would have been made if the // sharing had been run before. This is an estimate and depends on the // extent to which a reduction in the heap earlier would be carried through // to later GCs. cumulativeSharingSaving = cumulativeSharingSaving * ((double)currentSpaceUsed / (double)heapSpace); if (debugOptions & DEBUG_HEAPSIZE) Log("Heap: Cumulative sharing saving %0.2f\n", cumulativeSharingSaving); if (costWithSharing - cumulativeSharingSaving < cost) { // Run the sharing pass next time. performSharingPass = true; cumulativeSharingSaving = 0; } else { // Don't run the sharing pass next time performSharingPass = false; // Running a sharing pass reduces the heap for subsequent // runs. Add this into the cost. double freeSharingCost = costFunction(newHeapSizeWithSharing, true, false); if (freeSharingCost < cost && freeSharingCost > userGCRatio) { if (debugOptions & DEBUG_HEAPSIZE) Log("Heap: Previous sharing would have saved %0.2f\n", cost - freeSharingCost); cumulativeSharingSaving += cost - freeSharingCost; } } } if (debugOptions & DEBUG_HEAPSIZE) { if (performSharingPass) Log("Heap: Next full GC will enable the sharing pass\n"); Log("Heap: Resizing from "); LogSize(gMem.SpaceForHeap()); Log(" to "); LogSize(newHeapSize); Log(". Estimated ratio %2.2f\n", cost); } // Set the sizes. gMem.SetSpaceForHeap(newHeapSize); // Set the minor space size. It can potentially use the whole of the // rest of the available heap but there could be a problem if that exceeds // the available memory and causes paging. We need to raise the limit carefully. // Also, if we use the whole of the heap we may not then be able to allocate // new areas in the major heap without going over the limit. Restrict it to // half of the available heap. POLYUNSIGNED nextLimit = highWaterMark + highWaterMark / 32; if (nextLimit > newHeapSize) nextLimit = newHeapSize; // gMem.CurrentHeapSize() is the live space size. if (gMem.CurrentHeapSize() > nextLimit) gMem.SetSpaceBeforeMinorGC(0); // Run out of space else gMem.SetSpaceBeforeMinorGC((nextLimit-gMem.CurrentHeapSize())/2); lastFreeSpace = newHeapSize - currentSpaceUsed; predictedRatio = cost; }
void ComspecDone(int aiRc) { #ifdef _DEBUG xf_dump_chk(); xf_validate(NULL); #endif //WARNING("Послать в GUI CONEMUCMDSTOPPED"); LogSize(NULL, 0, "ComspecDone"); // Это необходимо делать, т.к. при смене буфера (SetConsoleActiveScreenBuffer) приложением, // дескриптор нужно закрыть, иначе conhost может не вернуть предыдущий буфер //ConOutCloseHandle() // Поддержка алиасов if (gpSrv->szComSpecName[0] && gpSrv->szSelfName[0]) { // Скопировать алиасы из cmd.exe в conemuc.exe wchar_t *pszPostAliases = NULL; DWORD nPostAliasSize; BOOL lbChanged = (gpSrv->pszPreAliases == NULL); if (!GetAliases(gpSrv->szComSpecName, &pszPostAliases, &nPostAliasSize)) { if (pszPostAliases) _wprintf(pszPostAliases); } else { if (!lbChanged) { lbChanged = (gpSrv->nPreAliasSize!=nPostAliasSize); } if (!lbChanged && gpSrv->nPreAliasSize && gpSrv->pszPreAliases && pszPostAliases) { lbChanged = memcmp(gpSrv->pszPreAliases,pszPostAliases,gpSrv->nPreAliasSize)!=0; } if (lbChanged) { xf_dump_chk(); if (gnMainServerPID) { MCHKHEAP; CESERVER_REQ* pIn = ExecuteNewCmd(CECMD_SAVEALIASES,sizeof(CESERVER_REQ_HDR)+nPostAliasSize); if (pIn) { MCHKHEAP; memmove(pIn->Data, pszPostAliases, nPostAliasSize); MCHKHEAP; CESERVER_REQ* pOut = ExecuteSrvCmd(gnMainServerPID, pIn, GetConEmuHWND(2), FALSE, 0, TRUE); MCHKHEAP; if (pOut) ExecuteFreeResult(pOut); ExecuteFreeResult(pIn); MCHKHEAP; } } xf_dump_chk(); wchar_t *pszNewName = pszPostAliases, *pszNewTarget, *pszNewLine; while (pszNewName && *pszNewName) { pszNewLine = pszNewName + lstrlen(pszNewName); pszNewTarget = wcschr(pszNewName, L'='); if (pszNewTarget) { *pszNewTarget = 0; pszNewTarget++; } if (*pszNewTarget == 0) pszNewTarget = NULL; AddConsoleAlias(pszNewName, pszNewTarget, gpSrv->szSelfName); pszNewName = pszNewLine+1; } xf_dump_chk(); } } if (pszPostAliases) { free(pszPostAliases); pszPostAliases = NULL; } } xf_dump_chk(); //TODO("Уведомить плагин через пайп (если родитель - FAR) что процесс завершен. Плагин должен считать и запомнить содержимое консоли и только потом вернуть управление в ConEmuC!"); DWORD dwErr1 = 0; //, dwErr2 = 0; HANDLE hOut1 = NULL, hOut2 = NULL; BOOL lbRc1 = FALSE, lbRc2 = FALSE; CONSOLE_SCREEN_BUFFER_INFO sbi1 = {{0,0}}, sbi2 = {{0,0}}; #ifdef _DEBUG HWND hWndCon = GetConEmuHWND(2); #endif // Тут нужна реальная, а не скорректированная информация! if (!gbNonGuiMode) { // Если GUI не сможет через сервер вернуть высоту буфера - это нужно сделать нам! lbRc1 = GetConsoleScreenBufferInfo(hOut1 = GetStdHandle(STD_OUTPUT_HANDLE), &sbi1); if (!lbRc1) dwErr1 = GetLastError(); xf_dump_chk(); } //PRAGMA_ERROR("Размер должен возвращать сам GUI, через серверный ConEmuC!"); #ifdef SHOW_STARTED_MSGBOX MessageBox(GetConEmuHWND(2), L"ConEmuC (comspec mode) is about to TERMINATE", L"ConEmuC.ComSpec", 0); #endif #ifdef _DEBUG xf_dump_chk(); xf_validate(NULL); #endif if (!gbNonGuiMode && (gpSrv->dwParentFarPID != 0)) { //// Вернуть размер буфера (высота И ширина) //if (gpSrv->sbi.dwSize.X && gpSrv->sbi.dwSize.Y) { // SMALL_RECT rc = {0}; // SetConsoleSize(0, gpSrv->sbi.dwSize, rc, "ComspecDone"); //} //ConOutCloseHandle() CONSOLE_SCREEN_BUFFER_INFO l_csbi = {{0}}; lbRc2 = GetConsoleScreenBufferInfo(hOut2 = GetStdHandle(STD_OUTPUT_HANDLE), &l_csbi); CESERVER_REQ *pOut = SendStopped(&l_csbi); if (pOut) { if (!pOut->StartStopRet.bWasBufferHeight) { //gpSrv->sbi.dwSize = pIn->StartStop.sbi.dwSize; lbRc1 = FALSE; // Консольное приложение самостоятельно сбросило буферный режим. Не дергаться... } else { lbRc1 = TRUE; } ExecuteFreeResult(pOut); pOut = NULL; } if (!gbWasBufferHeight) { lbRc2 = GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbi2); #ifdef _DEBUG if (sbi2.dwSize.Y > 200) { wchar_t szTitle[128]; _wsprintf(szTitle, SKIPLEN(countof(szTitle)) L"ConEmuC (PID=%i)", GetCurrentProcessId()); MessageBox(NULL, L"BufferHeight was not turned OFF", szTitle, MB_SETFOREGROUND|MB_SYSTEMMODAL); } #endif if (lbRc1 && lbRc2 && sbi2.dwSize.Y == sbi1.dwSize.Y) { // GUI не смог вернуть высоту буфера... // Это плохо, т.к. фар высоту буфера не меняет и будет сильно глючить на N сотнях строк... int nNeedHeight = gpSrv->sbi.dwSize.Y; if (nNeedHeight < 10) { nNeedHeight = (sbi2.srWindow.Bottom-sbi2.srWindow.Top+1); } if (sbi2.dwSize.Y != nNeedHeight) { _ASSERTE(sbi2.dwSize.Y == nNeedHeight); PRINT_COMSPEC(L"Error: BufferHeight was not changed from %i\n", sbi2.dwSize.Y); SMALL_RECT rc = {0}; sbi2.dwSize.Y = nNeedHeight; if (gpLogSize) LogSize(&sbi2.dwSize, 0, ":ComspecDone.RetSize.before"); SetConsoleSize(0, sbi2.dwSize, rc, "ComspecDone.Force"); if (gpLogSize) LogSize(NULL, 0, ":ComspecDone.RetSize.after"); } } } } if (gpSrv->pszPreAliases) { free(gpSrv->pszPreAliases); gpSrv->pszPreAliases = NULL; } //SafeCloseHandle(ghCtrlCEvent); //SafeCloseHandle(ghCtrlBreakEvent); }
// Set the initial size based on any parameters specified on the command line. // Any of these can be zero indicating they should default. void HeapSizeParameters::SetHeapParameters(POLYUNSIGNED minsize, POLYUNSIGNED maxsize, POLYUNSIGNED initialsize, unsigned percent) { minHeapSize = K_to_words(minsize); // If these overflow assume the result will be zero maxHeapSize = K_to_words(maxsize); POLYUNSIGNED initialSize = K_to_words(initialsize); POLYUNSIGNED memsize = GetPhysicalMemorySize() / sizeof(PolyWord); // If no maximum is given default it to 80% of the physical memory. // This allows some space for the OS and other things. if (maxHeapSize == 0 || maxHeapSize > MAXIMUMADDRESS) { if (memsize != 0) maxHeapSize = memsize - memsize / 5; else maxHeapSize = MAXIMUMADDRESS; // But if this must not be smaller than the minimum size. if (maxHeapSize < minHeapSize) maxHeapSize = minHeapSize; if (maxHeapSize < initialSize) maxHeapSize = initialSize; } // The default minimum is zero; in practice the live data size. // The default initial size is the minimum if that has been provided, // otherwise 8M words. There are applications that only require a small // heap and if we set the heap large to begin with we'll never do a // full GC and reduce it. if (initialSize == 0) { if (minHeapSize != 0) initialSize = minHeapSize; else initialSize = 8 * gMem.DefaultSpaceSize(); // But not more than the maximum if (initialSize > maxHeapSize) initialSize = maxHeapSize; } // Together with the constraints on user settings that ensures this holds. ASSERT(initialSize >= minHeapSize && initialSize <= maxHeapSize); // Initially we divide the space equally between the major and // minor heaps. That means that there will definitely be space // for the first minor GC to copy its data. This division can be // changed later on. gMem.SetSpaceForHeap(initialSize); gMem.SetSpaceBeforeMinorGC(initialSize/2); lastFreeSpace = initialSize; highWaterMark = initialSize; if (percent == 0) userGCRatio = 1.0 / 9.0; // Default to 10% GC to 90% application else userGCRatio = (float)percent / (float)(100 - percent); predictedRatio = lastMajorGCRatio = userGCRatio; if (debugOptions & DEBUG_HEAPSIZE) { Log("Heap: Initial settings: Initial heap "); LogSize(initialSize); Log(" minimum "); LogSize(minHeapSize); Log(" maximum "); LogSize(maxHeapSize); Log(" target ratio %f\n", userGCRatio); } }
size_t SymbianLog::getLogSize() { return (size_t)LogSize(); }