Path: blob/master/runtime/gc_trace/TgcHeap.cpp
5985 views
/*******************************************************************************1* Copyright (c) 1991, 2019 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#include "j9.h"23#include "j9cfg.h"24#include "mmhook.h"25#include "j9port.h"26#include "modronopt.h"27#include "j9comp.h"2829#include "GCExtensions.hpp"30#include "Heap.hpp"31#include "HeapStats.hpp"32#include "TgcExtensions.hpp"33#include "TgcHeap.hpp"34#include "Heap.hpp"35#include "MemorySpace.hpp"36#include "MemorySubSpace.hpp"37#include "MemoryPool.hpp"38#include "ParallelSweepChunk.hpp"39#include "SweepHeapSectioning.hpp"40#include "ModronAssertions.h"4142#include "SweepStats.hpp"43#include "GlobalGCStats.hpp"444546#include "j9.h"47#include "j9cfg.h"48#include "mmhook.h"49#include "j9port.h"50#include "modronopt.h"51#include "j9comp.h"5253#include "FreeHeapRegionList.hpp"54#include "GCExtensions.hpp"55#include "GlobalAllocationManagerSegregated.hpp"56#include "GlobalGCStats.hpp"57#include "Heap.hpp"58#include "HeapRegionQueue.hpp"59#include "LockingHeapRegionQueue.hpp"60#include "MemoryPool.hpp"61#include "MemorySpace.hpp"62#include "MemorySubSpace.hpp"63#include "ParallelSweepChunk.hpp"64#include "RegionPoolSegregated.hpp"65#include "SegregatedAllocationInterface.hpp"66#include "SweepHeapSectioning.hpp"67#include "SweepStats.hpp"68#include "TgcExtensions.hpp"69#include "TgcHeap.hpp"7071#include "MemoryPool.hpp"7273static void74tgcHeapPrintStats(OMR_VMThread* omrVMThread)75{76MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(omrVMThread);7778MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);79MM_HeapStats stats;80MM_Heap *heap = extensions->heap;81/* Gather statistics on all allocations since last collection from memory pools */82heap->mergeHeapStats(&stats); /* Assume active */8384tgcExtensions->printf("------------- Heap Statistics -------------\n");85tgcExtensions->printf("Heap Allocated Count: %12zu\n", stats._allocCount);86tgcExtensions->printf("Heap Allocated Bytes: %12zu\n", stats._allocBytes);87tgcExtensions->printf("Heap Discarded Bytes: %12zu\n", stats._allocDiscardedBytes);88tgcExtensions->printf("Heap Search Count: %12zu\n", stats._allocSearchCount);89tgcExtensions->printf("Heap Free After Last GC: %12zu\n", stats._lastFreeBytes);90tgcExtensions->printf("Freelist Size: %12zu\n", stats._activeFreeEntryCount);91tgcExtensions->printf("Deferred Size: %12zu\n", stats._inactiveFreeEntryCount);92}9394static void95tgcHeapMicroFragmentPrintStats(OMR_VMThread* omrVMThread)96{97void *tgcRegionDarkmatter_address_start = NULL;98void *tgcRegionDarkmatter_address_end = NULL;99UDATA tgcRegionDarkmatter_bytes = 0;100UDATA tgcRegionFree_bytes = 0;101UDATA tgcRegionDarkmatter_count = 0;102const UDATA tgcRegionMaxcount = 20;103104MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(omrVMThread);105106MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);107MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();108MM_MemorySubSpace *tenureMemorySubspace = defaultMemorySpace->getTenureMemorySubSpace();109110UDATA totalChunkCount = extensions->splitFreeListNumberChunksPrepared;111UDATA tgcRegionDarkmatter_size = totalChunkCount/tgcRegionMaxcount; /**> number of chunks */112113if (0 == tgcRegionDarkmatter_size) {114tgcRegionDarkmatter_size = 1;115}116117MM_ParallelSweepChunk* sweepChunk = NULL;118MM_ParallelSweepChunk* lastSweepChunk = NULL;119MM_SweepHeapSectioningIterator sectioningIterator(extensions->sweepHeapSectioning);120UDATA regionSize = 0;121122OMRPORT_ACCESS_FROM_OMRVMTHREAD(omrVMThread);123char timestamp[32];124omrstr_ftime(timestamp, sizeof(timestamp), "%b %d %H:%M:%S %Y", omrtime_current_time_millis());125tgcExtensions->printf("------- Micro Fragment Statistics timestamp=\"%s\" ---------\n", timestamp);126tgcExtensions->printf(" address start - address end ( size) free KBytes( Pct) fragment KBytes( Pct)\n");127128for (uintptr_t chunkNum = 0; chunkNum < totalChunkCount; chunkNum++) {129sweepChunk = sectioningIterator.nextChunk();130if (MEMORY_TYPE_OLD == sweepChunk->memoryPool->getSubSpace()->getTypeFlags()) {131132if (0 == sweepChunk->chunkTop) {133continue;134}135tgcRegionDarkmatter_count += 1;136tgcRegionDarkmatter_bytes += sweepChunk->_darkMatterBytes;137tgcRegionFree_bytes += sweepChunk->freeBytes;138lastSweepChunk = sweepChunk;139if (1 == tgcRegionDarkmatter_count) {140tgcRegionDarkmatter_address_start = sweepChunk->chunkBase;141}142if (tgcRegionDarkmatter_size == tgcRegionDarkmatter_count) {143tgcRegionDarkmatter_address_end = sweepChunk->chunkTop;144if (tgcRegionDarkmatter_address_end == tgcRegionDarkmatter_address_start) {145break;146}147regionSize = (UDATA)tgcRegionDarkmatter_address_end-(UDATA)tgcRegionDarkmatter_address_start;148149tgcExtensions->printf("%p - %p(%3zuMB)%14zuKB(%5.2f%%)%14zuKB(%5.2f%%)\n",150tgcRegionDarkmatter_address_start, tgcRegionDarkmatter_address_end, regionSize>>20,151tgcRegionFree_bytes >> 10, 100 * (float)tgcRegionFree_bytes/(float)regionSize,152tgcRegionDarkmatter_bytes >> 10, 100 * (float)tgcRegionDarkmatter_bytes/(float)regionSize);153154tgcRegionDarkmatter_count = 0;155tgcRegionDarkmatter_bytes = 0;156tgcRegionFree_bytes = 0;157}158}159}160161if (0 != tgcRegionDarkmatter_count) {162tgcRegionDarkmatter_address_end = lastSweepChunk->chunkTop;163regionSize = (UDATA)tgcRegionDarkmatter_address_end-(UDATA)tgcRegionDarkmatter_address_start;164165tgcExtensions->printf("%p - %p(%3zuMB)%14zuKB(%5.2f%%)%14zuKB(%5.2f%%)\n",166tgcRegionDarkmatter_address_start, tgcRegionDarkmatter_address_end, regionSize>>20,167tgcRegionFree_bytes >> 10, 100 * (float)tgcRegionFree_bytes/(float)regionSize,168tgcRegionDarkmatter_bytes >> 10, 100 * (float)tgcRegionDarkmatter_bytes/(float)regionSize);169170tgcRegionDarkmatter_count = 0;171tgcRegionDarkmatter_bytes = 0;172tgcRegionFree_bytes = 0;173}174UDATA tenureDarkMatterBytes = tenureMemorySubspace->getMemoryPool()->getDarkMatterBytes();175UDATA tenureFreeBytes = tenureMemorySubspace->getMemoryPool()->getApproximateFreeMemorySize();176177tgcExtensions->printf("Tenure(%zuMB) Free Size: %12zu(%zuMB, %5.2f%%), Micro Fragment Size: %12zu(%zuMB, %5.2f%%)\n",178extensions->heap->getActiveMemorySize(MEMORY_TYPE_OLD)>>20, tenureFreeBytes, tenureFreeBytes>>20, 100 * (float)tenureFreeBytes / (float)extensions->heap->getActiveMemorySize(MEMORY_TYPE_OLD),179tenureDarkMatterBytes, tenureDarkMatterBytes>>20, 100 * (float)tenureDarkMatterBytes / (float)extensions->heap->getActiveMemorySize(MEMORY_TYPE_OLD));180181MM_SweepStats *sweepStats = &extensions->globalGCStats.sweepStats;182183U_64 duration = omrtime_hires_delta(sweepStats->_startTime, sweepStats->_endTime, J9PORT_TIME_DELTA_IN_MICROSECONDS);184tgcExtensions->printf("Sweep Time(ms): total=\"%llu.%03.3llu\", DarkMatter Samples: %zu\n",185duration / 1000, duration % 1000, tenureMemorySubspace->getMemoryPool()->getDarkMatterSamples());186187}188189static void190tgcHookHeapGlobalPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)191{192MM_GlobalGCStartEvent* event = (MM_GlobalGCStartEvent*)eventData;193tgcHeapPrintStats(event->currentThread);194}195196static void197tgcHookHeapLocalPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)198{199MM_LocalGCStartEvent* event = (MM_LocalGCStartEvent*)eventData;200tgcHeapPrintStats(event->currentThread);201}202203static void204tgcHookGlobalGcSweepEndPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)205{206MM_SweepEndEvent* event = (MM_SweepEndEvent*)eventData;207tgcHeapMicroFragmentPrintStats(event->currentThread);208}209210#if defined(J9VM_GC_SEGREGATED_HEAP)211static void212tgcShowRegions(OMR_VMThread *omrVMThread, const char *comment)213{214MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(omrVMThread);215MM_GCExtensionsBase *extensions = MM_GCExtensions::getExtensions(omrVMThread);216MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(omrVMThread);217218MM_GlobalAllocationManagerSegregated *globalAllocationManager = (MM_GlobalAllocationManagerSegregated *) extensions->globalAllocationManager;219MM_RegionPoolSegregated *regionPool = globalAllocationManager->getRegionPool();220221globalAllocationManager->flushCachedFullRegions(env);222223uintptr_t countSmall, countLarge, countArraylet, countFree, countCoalesce, countMultiFree;224uintptr_t countTotal = 0;225uintptr_t countFullSmallTotal = 0;226uintptr_t countAvailableSmallTotal = 0;227uintptr_t darkMatterBytesTotal = 0;228uintptr_t allocCacheBytesTotal = 0;229230tgcExtensions->printf(">>> %32s \n", comment);231tgcExtensions->printf(">>> sizeClass | full | available | total | dark | cache\n");232tgcExtensions->printf(">>> ====================================================================\n");233uintptr_t regionSize = extensions->heap->getHeapRegionManager()->getRegionSize();234235for (int32_t sizeClass = OMR_SIZECLASSES_MIN_SMALL; sizeClass <= OMR_SIZECLASSES_MAX_SMALL; sizeClass++) {236uintptr_t cellSize = env->getExtensions()->defaultSizeClasses->getCellSize(sizeClass);237countSmall= regionPool->getSmallFullRegions(sizeClass)->getTotalRegions();238countFullSmallTotal += countSmall;239tgcExtensions->printf(">>> %2d: %5d | %4d | ", sizeClass, cellSize, countSmall);240241for (int32_t i = 0; i < NUM_DEFRAG_BUCKETS; i++) {242uintptr_t count = 0;243for (uintptr_t j = 0; j < regionPool->getSplitAvailableListSplitCount(); j++) {244count += regionPool->getSmallAvailableRegions(sizeClass, i, j)->getTotalRegions();245}246countSmall += count;247countAvailableSmallTotal += count;248tgcExtensions->printf(" %4d ", count);249}250countTotal += countSmall;251tgcExtensions->printf("| %5d | ", countSmall);252253uintptr_t darkMatterBytes = regionPool->getDarkMatterCellCount(sizeClass) * cellSize;254darkMatterBytesTotal += darkMatterBytes;255tgcExtensions->printf("%6.2f%% | ", (countSmall == 0)? 0: (darkMatterBytes / (countSmall * regionSize)));256257uintptr_t allocCacheSize = 0;258GC_OMRVMThreadListIterator vmThreadListIterator(env->getOmrVM());259while(OMR_VMThread* thread = vmThreadListIterator.nextOMRVMThread()) {260MM_EnvironmentBase *envThread = MM_EnvironmentBase::getEnvironment(thread);261allocCacheSize += MM_SegregatedAllocationInterface::getObjectAllocationInterface(envThread)->getAllocatableSize(sizeClass);262}263264allocCacheBytesTotal += allocCacheSize;265tgcExtensions->printf("%5d\n", allocCacheSize);266}267268tgcExtensions->printf(">>> region size %d\n", regionSize);269270uintptr_t arrayletLeafSize = extensions->getOmrVM()->_arrayletLeafSize;271tgcExtensions->printf(">>> arraylet leaf size %d\n", arrayletLeafSize);272273tgcExtensions->printf(">>> small total (full, available) region count %d (%d, %d)\n", countTotal, countFullSmallTotal, countAvailableSmallTotal);274275countTotal += countLarge = regionPool->getLargeFullRegions()->getTotalRegions();276tgcExtensions->printf(">>> large full region count %d\n", countLarge);277278countTotal += countArraylet = regionPool->getArrayletFullRegions()->getTotalRegions();279tgcExtensions->printf(">>> arraylet full region count %d\n", countArraylet);280281countTotal += (countArraylet = regionPool->getArrayletAvailableRegions()->getTotalRegions());282tgcExtensions->printf(">>> arraylet available region count %d\n", countArraylet);283284countTotal += countFree = regionPool->getSingleFreeList()->getTotalRegions();285tgcExtensions->printf(">>> free region count %d\n", countFree);286287countTotal += countMultiFree = regionPool->getMultiFreeList()->getTotalRegions();288tgcExtensions->printf(">>> mutliFree region count %d\n", countMultiFree);289290countTotal += countCoalesce = regionPool->getCoalesceFreeList()->getTotalRegions();291tgcExtensions->printf(">>> coalesce region count %d\n", countCoalesce);292293uintptr_t heapSize = countTotal * env->getExtensions()->getHeap()->getHeapRegionManager()->getRegionSize();294295tgcExtensions->printf(">>> total region count %d\n", countTotal);296tgcExtensions->printf(">>> dark matter total bytes %d (%2.2f%% of heap)\n", darkMatterBytesTotal, 100.0 * darkMatterBytesTotal / heapSize);297tgcExtensions->printf(">>> allocation cache total bytes %d (%2.2f%% of heap)\n", allocCacheBytesTotal, 100.0 * allocCacheBytesTotal / heapSize);298tgcExtensions->printf(">>> -------------------------------------------------------\n");299}300301static void302tgcShowHeapStatistics(OMR_VMThread *omrVMThread)303{304MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(omrVMThread);305MM_GCExtensionsBase *extensions = MM_GCExtensions::getExtensions(omrVMThread);306MM_MemoryPool *memoryPool = extensions->getHeap()->getDefaultMemorySpace()->getDefaultMemorySubSpace()->getMemoryPool();307308tgcExtensions->printf(">>> minimum free entry size: %d\n", memoryPool->getMinimumFreeEntrySize());309}310311static void312tgcHookSegregatedGlobalGcSweepStartPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)313{314MM_SweepStartEvent* event = (MM_SweepStartEvent *) eventData;315tgcShowRegions(event->currentThread, "Before Sweep");316}317318static void319tgcHookSegregatedGlobalGcSweepEndPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)320{321MM_SweepEndEvent* event = (MM_SweepEndEvent *) eventData;322tgcShowRegions(event->currentThread, "After Sweep");323tgcShowHeapStatistics(event->currentThread);324}325326static void327tgcHookSegregatedGlobalGcSynchronousGCStart(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)328{329MM_MetronomeSynchronousGCStartEvent *event = (MM_MetronomeSynchronousGCStartEvent *) eventData;330331if (OUT_OF_MEMORY_TRIGGER == event->reason) {332tgcShowRegions(event->currentThread, "Out of Memory");333tgcShowHeapStatistics(event->currentThread);334}335}336337#endif /* defined(J9VM_GC_SEGREGATED_HEAP) */338339340bool341tgcHeapInitialize(J9JavaVM *javaVM)342{343MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);344J9HookInterface** privateHooks = J9_HOOK_INTERFACE(extensions->privateHookInterface);345J9HookInterface** omrHooks = J9_HOOK_INTERFACE(extensions->omrHookInterface);346347bool result = true;348349if (extensions->isStandardGC() || extensions->isVLHGC()) {350(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_GLOBAL_GC_START, tgcHookHeapGlobalPrintStats, OMR_GET_CALLSITE(), NULL);351(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_LOCAL_GC_START, tgcHookHeapLocalPrintStats, OMR_GET_CALLSITE(), NULL);352(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_SWEEP_END, tgcHookGlobalGcSweepEndPrintStats, OMR_GET_CALLSITE(), NULL);353} else if (extensions->isSegregatedHeap()) {354#if defined(J9VM_GC_SEGREGATED_HEAP)355(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_SWEEP_START, tgcHookSegregatedGlobalGcSweepStartPrintStats, OMR_GET_CALLSITE(), NULL);356(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_SWEEP_END, tgcHookSegregatedGlobalGcSweepEndPrintStats, OMR_GET_CALLSITE(), NULL);357(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_METRONOME_SYNCHRONOUS_GC_START, tgcHookSegregatedGlobalGcSynchronousGCStart, OMR_GET_CALLSITE(), NULL);358#endif /* defined(J9VM_GC_SEGREGATED_HEAP) */359}360return result;361}362363364