Path: blob/master/runtime/gc_trace_standard/TgcLargeAllocation.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 "j9port.h"25#include "modronopt.h"26#include "mmhook.h"2728#include "ConcurrentGCStats.hpp"29#include "EnvironmentBase.hpp"30#include "GCExtensions.hpp"31#include "Heap.hpp"32#include "HeapMemoryPoolIterator.hpp"33#include "HeapMemorySubSpaceIterator.hpp"34#include "LargeObjectAllocateStats.hpp"35#include "MemoryPool.hpp"36#include "MemorySpace.hpp"37#include "MemorySubSpace.hpp"38#include "ScanClassesMode.hpp"39#include "TgcExtensions.hpp"40#include "TgcLargeAllocation.hpp"4142static void43tgcFreeMemoryPrintStatsForMemoryPool(OMR_VMThread* omrVMThread, MM_MemoryPool *memoryPool)44{45MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);46MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);4748MM_LargeObjectAllocateStats *stats = memoryPool->getLargeObjectAllocateStats();4950if (NULL != stats) {5152tgcExtensions->printf(" -------------------------------------\n");53tgcExtensions->printf(" %llx (%s) pool: \n", memoryPool, memoryPool->getPoolName());54tgcExtensions->printf(" Index SizeClass Count FreqAlloc MBytes ( Pct) Cumulative ( Pct)\n");5556UDATA totalCount = 0;57UDATA approxTotalFreeMemory = 0;58for (IDATA sizeClassIndex = (IDATA)stats->getMaxSizeClasses() - 1; sizeClassIndex >=0 ; sizeClassIndex--) {59UDATA count = stats->getFreeEntrySizeClassStats()->getCount(sizeClassIndex);60UDATA frequentAllocCount = stats->getFreeEntrySizeClassStats()->getFrequentAllocCount(sizeClassIndex);61count += frequentAllocCount;62if (0 != count) {63totalCount += count;64UDATA approxFreeMemory = (count - frequentAllocCount) * stats->getSizeClassSizes(sizeClassIndex);6566MM_FreeEntrySizeClassStats::FrequentAllocation *curr = stats->getFreeEntrySizeClassStats()->getFrequentAllocationHead(sizeClassIndex);67UDATA veryLargeEntrySizeClass = stats->getFreeEntrySizeClassStats()->getVeryLargeEntrySizeClass();68while (NULL != curr) {69if (sizeClassIndex >= (IDATA)veryLargeEntrySizeClass) {70tgcExtensions->printf(" VeryLarge size %8zu count %8zu\n", curr->_size, curr->_count);71} else {72tgcExtensions->printf(" Frequent size %8zu count %8zu\n", curr->_size, curr->_count);73}74approxFreeMemory += (curr->_size * curr->_count);75curr = curr->_nextInSizeClass;76}77approxTotalFreeMemory += approxFreeMemory;7879Assert_MM_true(frequentAllocCount <= count);8081tgcExtensions->printf(" %4zu %11zu %8zu %9zu %9zuM (%5.2f%%) %9zuM (%5.2f%%)\n",82sizeClassIndex, stats->getSizeClassSizes(sizeClassIndex), count, frequentAllocCount,83approxFreeMemory >> 20, 100 * (float)approxFreeMemory/(float)memoryPool->getActualFreeMemorySize(),84approxTotalFreeMemory >> 20, 100 * (float)approxTotalFreeMemory/(float)memoryPool->getActualFreeMemorySize());85}86}87tgcExtensions->printf(" Total Count: %zu (%zu). Approx total free memory: %zuMB (%zuMB)\n",88totalCount, memoryPool->getActualFreeEntryCount(), approxTotalFreeMemory >> 20, memoryPool->getActualFreeMemorySize() >> 20);89Assert_MM_true(totalCount == memoryPool->getActualFreeEntryCount());90}91}9293static void94tgcTlhAllocPrintStatsForMemoryPool(OMR_VMThread* omrVMThread, MM_MemoryPool *memoryPool)95{96MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);97MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);9899MM_LargeObjectAllocateStats *stats = memoryPool->getLargeObjectAllocateStats();100101if (NULL != stats) {102103tgcExtensions->printf(" -------------------------------------\n");104tgcExtensions->printf(" %llx (%s) pool - TLH alloc: \n", memoryPool, memoryPool->getPoolName());105tgcExtensions->printf(" Index SizeClass tlhCount tlhKBytes\n");106107for (IDATA sizeClassIndex = (IDATA)stats->getMaxTLHSizeClasses() - 1; sizeClassIndex >=0 ; sizeClassIndex--) {108UDATA countTlhAlloc = stats->getTlhAllocSizeClassCount(sizeClassIndex);109if (0 != countTlhAlloc) {110UDATA approxTlhAllocMemory = countTlhAlloc * stats->getSizeClassSizes(sizeClassIndex);111tgcExtensions->printf(" %4zu %11zu %8zu %9zuK\n",112sizeClassIndex, stats->getSizeClassSizes(sizeClassIndex), countTlhAlloc, approxTlhAllocMemory >> 10);113}114}115}116117}118119static void120tgcFreeMemoryPrintStatsForMemorySubSpace(OMR_VMThread* omrVMThread, MM_MemorySubSpace *memorySubSpace, bool globalGC)121{122MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);123MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);124125MM_LargeObjectAllocateStats *stats = memorySubSpace->getLargeObjectAllocateStats();126127if (NULL != stats) {128MM_MemoryPool *memoryPool = memorySubSpace->getMemoryPool();129130tgcExtensions->printf("-------------------------------------\n");131tgcExtensions->printf("Index SizeClass Count FreqAlloc MBytes ( Pct) Cumulative ( Pct)\n");132133UDATA totalCount = 0;134UDATA approxTotalFreeMemory = 0;135for (IDATA sizeClassIndex = (IDATA)stats->getMaxSizeClasses() - 1; sizeClassIndex >=0 ; sizeClassIndex--) {136UDATA count = stats->getFreeEntrySizeClassStats()->getCount(sizeClassIndex);137UDATA frequentAllocCount = stats->getFreeEntrySizeClassStats()->getFrequentAllocCount(sizeClassIndex);138count += frequentAllocCount;139if (0 != count) {140totalCount += count;141UDATA approxFreeMemory = (count - frequentAllocCount) * stats->getSizeClassSizes(sizeClassIndex);142143Assert_MM_true(frequentAllocCount <= count);144145MM_FreeEntrySizeClassStats::FrequentAllocation *curr = stats->getFreeEntrySizeClassStats()->getFrequentAllocationHead(sizeClassIndex);146UDATA veryLargeEntrySizeClass = stats->getFreeEntrySizeClassStats()->getVeryLargeEntrySizeClass();147while (NULL != curr) {148if (sizeClassIndex >= (IDATA)veryLargeEntrySizeClass) {149tgcExtensions->printf(" VeryLarge size %8zu count %8zu\n", curr->_size, curr->_count);150} else {151tgcExtensions->printf(" Frequent size %8zu count %8zu\n", curr->_size, curr->_count);152}153approxFreeMemory += (curr->_size * curr->_count);154curr = curr->_nextInSizeClass;155}156approxTotalFreeMemory += approxFreeMemory;157158tgcExtensions->printf("%4zu %11zu %8zu %9zu %9zuM (%5.2f%%) %9zuM (%5.2f%%)\n",159sizeClassIndex, stats->getSizeClassSizes(sizeClassIndex), count, frequentAllocCount,160approxFreeMemory >> 20, 100 * (float)approxFreeMemory/(float)memoryPool->getActualFreeMemorySize(),161approxTotalFreeMemory >> 20, 100 * (float)approxTotalFreeMemory/(float)memoryPool->getActualFreeMemorySize());162}163}164tgcExtensions->printf("Total Count: %zu (%zu). Approx total free memory: %zuMB (%zuMB)\n",165totalCount, memoryPool->getActualFreeEntryCount(), approxTotalFreeMemory >> 20, memoryPool->getActualFreeMemorySize() >> 20);166Assert_MM_true(totalCount == memoryPool->getActualFreeEntryCount());167168if ((globalGC && (GLOBALGC_ESTIMATE_FRAGMENTATION == (extensions->estimateFragmentation & GLOBALGC_ESTIMATE_FRAGMENTATION))) ||169(!globalGC && (LOCALGC_ESTIMATE_FRAGMENTATION == (extensions->estimateFragmentation & LOCALGC_ESTIMATE_FRAGMENTATION)))) {170tgcExtensions->printf("------------- Fragmented Remainder ------------------------\n");171tgcExtensions->printf("Index SizeClass Count FreqAlloc MBytes ( Pct) Cumulative ( Pct)\n");172173totalCount = 0;174approxTotalFreeMemory = 0;175for (IDATA sizeClassIndex = (IDATA)stats->getMaxSizeClasses() - 1; sizeClassIndex >=0 ; sizeClassIndex--) {176UDATA count = extensions->freeEntrySizeClassStatsSimulated.getCount(sizeClassIndex);177UDATA frequentAllocCount = extensions->freeEntrySizeClassStatsSimulated.getFrequentAllocCount(sizeClassIndex);178count += frequentAllocCount;179if (0 != count) {180totalCount += count;181UDATA approxFreeMemory = (count - frequentAllocCount) * stats->getSizeClassSizes(sizeClassIndex);182183MM_FreeEntrySizeClassStats::FrequentAllocation *curr = extensions->freeEntrySizeClassStatsSimulated.getFrequentAllocationHead(sizeClassIndex);184UDATA veryLargeEntrySizeClass = stats->getFreeEntrySizeClassStats()->getVeryLargeEntrySizeClass();185while (NULL != curr) {186if (sizeClassIndex >= (IDATA)veryLargeEntrySizeClass) {187tgcExtensions->printf(" VeryLarge size %8zu count %8zu\n", curr->_size, curr->_count);188} else {189tgcExtensions->printf(" Frequent size %8zu count %8zu\n", curr->_size, curr->_count);190}191approxFreeMemory += (curr->_size * curr->_count);192Assert_MM_true(stats->getSizeClassIndex(curr->_size) == (UDATA)sizeClassIndex);193curr = curr->_nextInSizeClass;194}195approxTotalFreeMemory += approxFreeMemory;196197tgcExtensions->printf("%4zu %11zu %8zu %9zu %9zuM (%5.2f%%) %9zuM (%5.2f%%)\n",198sizeClassIndex, stats->getSizeClassSizes(sizeClassIndex), count, frequentAllocCount,199approxFreeMemory >> 20, 100 * (float)approxFreeMemory/(float)memoryPool->getActualFreeMemorySize(),200approxTotalFreeMemory >> 20, 100 * (float)approxTotalFreeMemory/(float)memoryPool->getActualFreeMemorySize());201202Assert_MM_true(frequentAllocCount <= count);203}204}205tgcExtensions->printf("Total Count: %zu (%zu). Approx total free memory: %zuMB (%zuMB)\n",206totalCount, memoryPool->getActualFreeEntryCount(), approxTotalFreeMemory >> 20, memoryPool->getActualFreeMemorySize() >> 20);207}208}209}210211static void212tgcLargeAllocationPrintCurrentStatsForMemoryPool(OMR_VMThread* omrVMThread, MM_MemoryPool *memoryPool)213{214MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);215MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);216217MM_LargeObjectAllocateStats *stats = memoryPool->getLargeObjectAllocateStats();218219if (NULL != stats) {220tgcExtensions->printf(" --------------------------------------\n");221tgcExtensions->printf(" %llx (%s) pool - CURRENT:\n", memoryPool, memoryPool->getPoolName());222tgcExtensions->printf(" Rank | Size KBytes Count | SizeClass KBytes Count\n");223224for(U_16 i = 0; i < spaceSavingGetCurSize(stats->getSpaceSavingSizes()) && i < stats->getMaxAllocateSizes(); i++) {225UDATA size = 0;226UDATA sizeCount = 0;227size = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizes(), i + 1);228if (0 != size) {229sizeCount = spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizes(), i + 1) / size;230}231232UDATA sizeClass = 0;233UDATA sizeClassCount = 0;234if (i < spaceSavingGetCurSize(stats->getSpaceSavingSizeClasses())) {235sizeClass = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizeClasses(), i + 1);236if (0 != sizeClass) {237sizeClassCount = spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizeClasses(), i + 1) / sizeClass;238}239}240241tgcExtensions->printf(" %4zu | %9zu %10zuK %6zu | %9zu %10zuK %6zu\n",242i, size, sizeCount * size >> 10, sizeCount, sizeClass, sizeClass * sizeClassCount >> 10, sizeClassCount);243}244}245}246247static void248tgcLargeAllocationPrintAverageStatsForMemoryPool(OMR_VMThread* omrVMThread, MM_MemoryPool *memoryPool)249{250MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);251MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);252253MM_LargeObjectAllocateStats *stats = memoryPool->getLargeObjectAllocateStats();254255if (NULL != stats) {256tgcExtensions->printf(" -------------------------------------\n");257tgcExtensions->printf(" %llx (%s) pool - AVERAGE:\n", memoryPool, memoryPool->getPoolName());258tgcExtensions->printf(" Rank | Size BytesPct | SizeClass BytesPct\n");259260for(U_16 i = 0; i < spaceSavingGetCurSize(stats->getSpaceSavingSizesAveragePercent()) && i < stats->getMaxAllocateSizes(); i++) {261262UDATA sizeForAveragePercent = 0;263float averagePercent = 0;264if (i < spaceSavingGetCurSize(stats->getSpaceSavingSizesAveragePercent())) {265sizeForAveragePercent = (UDATA)spaceSavingGetKthMostFreq(stats->getSpaceSavingSizesAveragePercent(), i + 1);266averagePercent = stats->convertPercentUDATAToFloat(spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizesAveragePercent(), i + 1));267}268269UDATA sizeClassForAveragePercent = 0;270float sizeClassAveragePercent = 0;271if (i < spaceSavingGetCurSize(stats->getSpaceSavingSizeClassesAveragePercent())) {272sizeClassForAveragePercent = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizeClassesAveragePercent(), i + 1);273sizeClassAveragePercent = stats->convertPercentUDATAToFloat(spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizeClassesAveragePercent(), i + 1));274}275276tgcExtensions->printf(" %4zu | %9zu %7.4f%% | %9zu %7.4f%%\n",277i, sizeForAveragePercent, averagePercent, sizeClassForAveragePercent, sizeClassAveragePercent);278}279280281}282}283284static void285tgcLargeAllocationPrintCurrentStatsForMemorySubSpace(OMR_VMThread* omrVMThread, MM_MemorySubSpace *memorySubSpace)286{287MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);288MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);289290/* we fetch directly the stats from the SubSpace. It will know if it needs to merge stats from child SubSpaces/Pools, or fetch directly from child Pool */291MM_LargeObjectAllocateStats *stats = memorySubSpace->getLargeObjectAllocateStats();292293if (NULL != stats) {294295tgcExtensions->printf("---------------- CURRENT ----------------\n");296tgcExtensions->printf("Rank | Size KBytes Count | SizeClass KBytes Count\n");297298for(U_16 i = 0; i < spaceSavingGetCurSize(stats->getSpaceSavingSizes()) && i < stats->getMaxAllocateSizes(); i++){299UDATA size = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizes(), i + 1);300UDATA sizeCount = 0;301if (0 != size) {302sizeCount = spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizes() ,i + 1) / size;303}304UDATA sizeClass = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizeClasses(), i + 1);305UDATA sizeClassCount = 0;306if (0 != sizeClass) {307sizeClassCount = spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizeClasses(), i + 1) / sizeClass;308}309310tgcExtensions->printf("%4zu | %9zu %10zuK %6zu | %9zu %10zuK %6zu\n",311i, size, sizeCount * size >> 10, sizeCount, sizeClass, sizeClass * sizeClassCount >> 10, sizeClassCount);312}313}314}315316static void317tgcLargeAllocationPrintAverageStatsForMemorySubSpace(OMR_VMThread* omrVMThread, MM_MemorySubSpace *memorySubSpace)318{319MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);320MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);321322/* we fetch directly the stats from the SubSpace. It will know if it needs to merge stats from child SubSpaces/Pools, or fetch directly from child Pool */323MM_LargeObjectAllocateStats *stats = memorySubSpace->getLargeObjectAllocateStats();324325if (NULL != stats) {326tgcExtensions->printf("---------------- AVERAGE ----------------\n");327tgcExtensions->printf("Rank | Size BytesPct | SizeClass BytesPct\n");328329for(U_16 i = 0; i < spaceSavingGetCurSize(stats->getSpaceSavingSizesAveragePercent()) && i < stats->getMaxAllocateSizes(); i++){330UDATA sizeForAveragePercent = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizesAveragePercent(), i + 1);331float averagePercent = stats->convertPercentUDATAToFloat(spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizesAveragePercent(), i + 1));332333UDATA sizeClassForAveragePercent = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizeClassesAveragePercent(), i + 1);334float sizeClassAveragePercent = stats->convertPercentUDATAToFloat(spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizeClassesAveragePercent(), i + 1));335336tgcExtensions->printf("%4zu | %9zu %7.4f%% | %9zu %7.4f%%\n",337i, sizeForAveragePercent, averagePercent, sizeClassForAveragePercent, sizeClassAveragePercent);338}339}340}341342static void343tgcLargeAllocationPrintStatsForAllocateMemory(OMR_VMThread* omrVMThread)344{345MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);346MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);347348MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();349MM_MemorySubSpace *defaultMemorySubspace = defaultMemorySpace->getDefaultMemorySubSpace();350351if (defaultMemorySubspace->isPartOfSemiSpace()) {352tgcExtensions->printf("======== Large Allocation Statistics ========\n");353354/* We are in generational configuration. defaultMemorySubspace points to one of two allocate Subspaces, but we want both. Thus we access the parent (SemiSpace subspace) */355/* SemiSpace stats include only Mutator stats (no Collector stats during flipping) */356MM_MemorySubSpace *topLevelMemorySubSpaceNew = defaultMemorySubspace->getTopLevelMemorySubSpace(MEMORY_TYPE_NEW);357tgcExtensions->printf("Allocate subspace: %llx (%s)\n", topLevelMemorySubSpaceNew, topLevelMemorySubSpaceNew->getName());358tgcLargeAllocationPrintCurrentStatsForMemorySubSpace(omrVMThread, topLevelMemorySubSpaceNew);359tgcExtensions->printf("=============================================\n");360}361}362363static void364tgcLargeAllocationPrintCurrentStatsForTenureMemory(OMR_VMThread* omrVMThread)365{366MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);367MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);368MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(omrVMThread);369370tgcExtensions->printf("==== Large Allocation Current Statistics ====\n");371372MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();373MM_MemorySubSpace *tenureMemorySubspace = defaultMemorySpace->getTenureMemorySubSpace();374375/* Note that tenure stats:376* for Generational: will include stats both Collector and Mutator allocates377* for Flat: will include stats only Mutator allocates378*/379tgcExtensions->printf("Tenure subspace: %llx (%s) - CURRENT \n", tenureMemorySubspace, tenureMemorySubspace->getName());380tgcLargeAllocationPrintCurrentStatsForMemorySubSpace(omrVMThread, tenureMemorySubspace);381382MM_MemoryPool *memoryPool = NULL;383MM_HeapMemoryPoolIterator poolIterator(env, extensions->heap, tenureMemorySubspace);384385while (NULL != (memoryPool = poolIterator.nextPoolInSubSpace())) {386tgcTlhAllocPrintStatsForMemoryPool(omrVMThread, memoryPool);387tgcLargeAllocationPrintCurrentStatsForMemoryPool(omrVMThread, memoryPool);388}389390tgcExtensions->printf("=============================================\n");391}392393static void394tgcLargeAllocationPrintAverageStatsForTenureMemory(OMR_VMThread* omrVMThread, UDATA eventNum)395{396MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);397MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);398MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(omrVMThread);399400tgcExtensions->printf("==== Large Allocation Average Statistics ====\n");401402MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();403MM_MemorySubSpace *tenureMemorySubspace = defaultMemorySpace->getTenureMemorySubSpace();404405/* Note that tenure stats:406* for Generational: will include stats both Collector and Mutator allocates407* for Flat: will include stats only Mutator allocates408*/409MM_MemoryPool *memoryPool = NULL;410MM_HeapMemoryPoolIterator poolIterator(env, extensions->heap, tenureMemorySubspace);411412while (NULL != (memoryPool = poolIterator.nextPoolInSubSpace())) {413414tgcLargeAllocationPrintAverageStatsForMemoryPool(omrVMThread, memoryPool);415}416417tgcExtensions->printf("Tenure subspace: %llx (%s) - AVERAGE\n", tenureMemorySubspace, tenureMemorySubspace->getName());418tgcLargeAllocationPrintAverageStatsForMemorySubSpace(omrVMThread, tenureMemorySubspace);419420tgcExtensions->printf("=============================================\n");421}422423static void424tgcFreeMemoryPrintStats(OMR_VMThread* omrVMThread, bool globalGC)425{426MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);427MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);428MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(omrVMThread);429430tgcExtensions->printf("=========== Free Memory Statistics ==========\n");431tgcExtensions->printf("=========== Size Class Distribution =========\n");432433MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();434MM_MemorySubSpace *tenureMemorySubspace = defaultMemorySpace->getTenureMemorySubSpace();435436MM_MemoryPool *memoryPool = NULL;437MM_HeapMemoryPoolIterator poolIterator(env, extensions->heap, tenureMemorySubspace);438439while (NULL != (memoryPool = poolIterator.nextPoolInSubSpace())) {440tgcFreeMemoryPrintStatsForMemoryPool(omrVMThread, memoryPool);441}442443tgcExtensions->printf("Tenure subspace: %llx (%s)\n", tenureMemorySubspace, tenureMemorySubspace->getName());444tgcFreeMemoryPrintStatsForMemorySubSpace(omrVMThread, tenureMemorySubspace, globalGC);445446tgcExtensions->printf("=============================================\n");447}448449static void450tgcEstimateFragmentationPrintStats(OMR_VMThread* omrVMThread)451{452MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);453MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);454455MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();456MM_MemorySubSpace *tenureMemorySubspace = defaultMemorySpace->getTenureMemorySubSpace();457MM_LargeObjectAllocateStats* stats = tenureMemorySubspace->getLargeObjectAllocateStats();458459OMRPORT_ACCESS_FROM_OMRVMTHREAD(omrVMThread);460U_64 time = omrtime_hires_delta(0, stats->getTimeEstimateFragmentation(), J9PORT_TIME_DELTA_IN_MICROSECONDS);461U_64 cpuTime = stats->getCPUTimeEstimateFragmentation();462if (cpuTime > time) {463cpuTime = 0;464}465char timestamp[32];466omrstr_ftime(timestamp, sizeof(timestamp), "%b %d %H:%M:%S %Y", omrtime_current_time_millis());467tgcExtensions->printf("<tgcLargeAllocation op=\"estimateFragmentation\" timems=\"%llu.%03.3llu\" cputimes=\"%llu.%03.3llu\" remainingFreeMemory=\"%zu\" initialFreeMemory=\"%zu\" timestamp=\"%s\" />\n",468time/1000, time%1000, cpuTime/1000, cpuTime%1000, stats->getRemainingFreeMemoryAfterEstimate(), stats->getFreeMemoryBeforeEstimate(), timestamp);469470}471472/**473* print time for mergeLargeAllocateStats, mergeTLH, mergeFreeEntry and averageLargeAllocateStats474*/475static void476tgcMergeAveragePrintStats(OMR_VMThread* omrVMThread)477{478MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);479MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);480MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();481MM_MemorySubSpace *tenureMemorySubspace = defaultMemorySpace->getTenureMemorySubSpace();482MM_LargeObjectAllocateStats* stats = tenureMemorySubspace->getLargeObjectAllocateStats();483484OMRPORT_ACCESS_FROM_OMRVMTHREAD(omrVMThread);485U_64 time = omrtime_hires_delta(0, stats->getTimeMergeAverage(), J9PORT_TIME_DELTA_IN_MICROSECONDS);486char timestamp[32];487omrstr_ftime(timestamp, sizeof(timestamp), "%b %d %H:%M:%S %Y", omrtime_current_time_millis());488tgcExtensions->printf("<tgcLargeAllocation op=\"mergeAndAverage\" timems=\"%llu.%03.3llu\" timestamp=\"%s\" />\n",489time/1000, time%1000, timestamp);490491}492493static void494tgcVerifyBackoutInScavenger(J9VMThread* vmThread)495{496MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vmThread);497MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);498499MM_ScavengerStats *scavengerStats = (MM_ScavengerStats *)&extensions->scavengerStats;500if(scavengerStats->_backout) {501tgcExtensions->printf("<tgcLargeAllocation op=\"gc\" type=\"scavenge\" details=\"aborted collection due to insufficient free space\" />\n");502}503}504505static void506tgcHookLargeAllocationGlobalPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)507{508MM_GlobalGCEndEvent* event = (MM_GlobalGCEndEvent*)eventData;509tgcLargeAllocationPrintCurrentStatsForTenureMemory(event->currentThread);510tgcLargeAllocationPrintAverageStatsForTenureMemory(event->currentThread, eventNum);511tgcLargeAllocationPrintStatsForAllocateMemory(event->currentThread);512}513514static void515tgcHookLargeAllocationLocalPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)516{517if (J9HOOK_MM_OMR_LOCAL_GC_START == eventNum) {518MM_LocalGCStartEvent* event = (MM_LocalGCStartEvent*)eventData;519tgcLargeAllocationPrintStatsForAllocateMemory(event->currentThread);520} else if (J9HOOK_MM_OMR_LOCAL_GC_END == eventNum) {521MM_LocalGCEndEvent* event = (MM_LocalGCEndEvent*)eventData;522tgcLargeAllocationPrintCurrentStatsForTenureMemory(event->currentThread);523tgcLargeAllocationPrintAverageStatsForTenureMemory(event->currentThread, eventNum);524} else {525Assert_MM_unreachable();526}527528}529530static void531tgcHookFreeMemoryGlobalPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)532{533MM_GlobalGCEndEvent* event = (MM_GlobalGCEndEvent*)eventData;534MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(event->currentThread);535MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);536537if (tgcExtensions->_largeAllocationVerboseRequested) {538tgcFreeMemoryPrintStats(event->currentThread, true);539}540tgcMergeAveragePrintStats(event->currentThread);541if (GLOBALGC_ESTIMATE_FRAGMENTATION == (extensions->estimateFragmentation & GLOBALGC_ESTIMATE_FRAGMENTATION)) {542tgcEstimateFragmentationPrintStats(event->currentThread);543}544}545546static void547tgcHookFreeMemoryLocalPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)548{549MM_LocalGCEndEvent* event = (MM_LocalGCEndEvent*)eventData;550MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(event->currentThread);551MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);552553if (tgcExtensions->_largeAllocationVerboseRequested) {554tgcFreeMemoryPrintStats(event->currentThread, false);555}556557tgcVerifyBackoutInScavenger((J9VMThread *) event->currentThread->_language_vmthread);558tgcMergeAveragePrintStats(event->currentThread);559if (LOCALGC_ESTIMATE_FRAGMENTATION == (extensions->estimateFragmentation & LOCALGC_ESTIMATE_FRAGMENTATION)) {560tgcEstimateFragmentationPrintStats(event->currentThread);561}562}563564static void565tgcVerifyHaltedInConcurrentGC(J9VMThread* vmThread, const char* state, const char* status)566{567MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vmThread);568MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);569tgcExtensions->printf("<tgcLargeAllocation op=\"gc\" type=\"concurrent\" details=\"concurrent-halted\" state=\"%s\" status=\"%s\" />\n", state, status);570}571572static void573tgcHookVerifyHaltedInConcurrentGC(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)574{575MM_ConcurrentHaltedEvent* event = (MM_ConcurrentHaltedEvent*)eventData;576#define CONCURRENT_STATUS_BUFFER_LENGTH 32577char statusBuffer[CONCURRENT_STATUS_BUFFER_LENGTH];578MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(event->currentThread);579const char* statusString = MM_ConcurrentGCStats::getConcurrentStatusString(env, event->executionMode, statusBuffer, CONCURRENT_STATUS_BUFFER_LENGTH);580#undef CONCURRENT_STATUS_BUFFER_LENGTH581582const char* stateString = "Complete";583if (0 == event->isTracingExhausted) {584stateString = "Tracing incomplete";585}586#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)587switch (event->scanClassesMode) {588case MM_ScanClassesMode::SCAN_CLASSES_NEED_TO_BE_EXECUTED:589case MM_ScanClassesMode::SCAN_CLASSES_CURRENTLY_ACTIVE:590stateString = "Class scanning incomplete";591break;592case MM_ScanClassesMode::SCAN_CLASSES_COMPLETE:593case MM_ScanClassesMode::SCAN_CLASSES_DISABLED:594break;595default:596stateString = "Class scanning bad state";597break;598}599#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */600if (0 == event->isCardCleaningComplete) {601stateString = "Card cleaning incomplete";602}603604tgcVerifyHaltedInConcurrentGC(static_cast<J9VMThread*>(event->currentThread->_language_vmthread), stateString, statusString);605}606607bool608tgcLargeAllocationInitialize(J9JavaVM *javaVM)609{610bool result = true;611MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);612MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);613614/*TODO: remove condition check for concurrentSweep, currently tgc:largeAllocation can not be enabled in concurrentSweep case */615if (extensions->processLargeAllocateStats && extensions->isStandardGC()) {616if (!extensions->isConcurrentSweepEnabled()) {617J9HookInterface** omrHooks = J9_HOOK_INTERFACE(extensions->omrHookInterface);618if (tgcExtensions->_largeAllocationVerboseRequested) {619(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_GLOBAL_GC_START, tgcHookLargeAllocationGlobalPrintStats, OMR_GET_CALLSITE(), NULL);620(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_LOCAL_GC_START, tgcHookLargeAllocationLocalPrintStats, OMR_GET_CALLSITE(), NULL);621(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_LOCAL_GC_END, tgcHookLargeAllocationLocalPrintStats, OMR_GET_CALLSITE(), NULL);622}623624(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_GLOBAL_GC_END, tgcHookFreeMemoryGlobalPrintStats, OMR_GET_CALLSITE(), NULL);625(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_LOCAL_GC_END, tgcHookFreeMemoryLocalPrintStats, OMR_GET_CALLSITE(), NULL);626627J9HookInterface** privateHooks = J9_HOOK_INTERFACE(extensions->privateHookInterface);628(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_CONCURRENT_HALTED, tgcHookVerifyHaltedInConcurrentGC, OMR_GET_CALLSITE(), NULL);629(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_COMPACT_START, tgcHookFreeMemoryGlobalPrintStats, OMR_GET_CALLSITE(), NULL);630}631}632return result;633}634635636