Path: blob/master/runtime/gc_trace_vlhgc/TgcDynamicCollectionSet.cpp
5986 views
1/*******************************************************************************2* Copyright (c) 1991, 2017 IBM Corp. and others3*4* This program and the accompanying materials are made available under5* the terms of the Eclipse Public License 2.0 which accompanies this6* distribution and is available at https://www.eclipse.org/legal/epl-2.0/7* or the Apache License, Version 2.0 which accompanies this distribution and8* is available at https://www.apache.org/licenses/LICENSE-2.0.9*10* This Source Code may also be made available under the following11* Secondary Licenses when the conditions for such availability set12* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU13* General Public License, version 2 with the GNU Classpath14* Exception [1] and GNU General Public License, version 2 with the15* OpenJDK Assembly Exception [2].16*17* [1] https://www.gnu.org/software/classpath/license.html18* [2] http://openjdk.java.net/legal/assembly-exception.html19*20* 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-exception21*******************************************************************************/2223#include "j9.h"24#include "j9cfg.h"25#include "j9port.h"26#include "Tgc.hpp"27#include "mmhook.h"2829#include <string.h>3031#include "BaseNonVirtual.hpp"32#include "CollectionSetDelegate.hpp"33#include "CompactGroupManager.hpp"34#include "CompactGroupPersistentStats.hpp"35#include "EnvironmentVLHGC.hpp"36#include "GCExtensions.hpp"37#include "TgcExtensions.hpp"38#include "HeapRegionIteratorVLHGC.hpp"39#include "HeapRegionDescriptorVLHGC.hpp"4041#define MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH 104243class MM_TgcDynamicCollectionSetData : public MM_BaseNonVirtual {44public:45protected:46private:47struct MM_TgcDynamicCollectionSetHistoryElement {48/* Direct measured statistics */49UDATA regionCount; /**< Number of regions that appear in the given group */5051/* Historical average of statistics */52double avgHis_regionCount; /**< Number of regions that appear in the given group */5354/* Local history average of statistics */55double avgLcl_regionCount; /**< Number of regions that appear in the given group */56};57MM_TgcDynamicCollectionSetHistoryElement *_historyTable[MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH];5859bool _historyPrimed; /**< Flag indicating if the decay analysis history has been primed with initial values or not */6061public:62MM_TgcDynamicCollectionSetData();6364static MM_TgcDynamicCollectionSetData *newInstance(J9JavaVM *javaVM);65void kill(J9JavaVM *javaVM);6667void dumpDynamicCollectionSetStatistics(MM_EnvironmentVLHGC *env);6869protected:70private:71bool initialize(J9JavaVM *javaVM);72void tearDown(J9JavaVM *javaVM);7374void decayPrintValue(MM_EnvironmentVLHGC *env, UDATA value);75void decayPrintDelta(MM_EnvironmentVLHGC *env, UDATA before, UDATA after);76};7778MM_TgcDynamicCollectionSetData::MM_TgcDynamicCollectionSetData()79: _historyPrimed(false)80{81_typeId = __FUNCTION__;82memset(_historyTable, 0, sizeof(_historyTable));83}8485MM_TgcDynamicCollectionSetData *86MM_TgcDynamicCollectionSetData::newInstance(J9JavaVM *javaVM)87{88MM_TgcDynamicCollectionSetData *dcsData = NULL;8990dcsData = (MM_TgcDynamicCollectionSetData *)MM_GCExtensions::getExtensions(javaVM)->getForge()->allocate(sizeof(MM_TgcDynamicCollectionSetData), MM_AllocationCategory::FIXED, J9_GET_CALLSITE());91if (NULL != dcsData) {92new(dcsData) MM_TgcDynamicCollectionSetData();93if (!dcsData->initialize(javaVM)) {94dcsData->kill(javaVM);95dcsData = NULL;96}97}9899return dcsData;100101}102103void104MM_TgcDynamicCollectionSetData::kill(J9JavaVM *javaVM)105{106tearDown(javaVM);107MM_GCExtensions::getExtensions(javaVM)->getForge()->free(this);108}109110bool111MM_TgcDynamicCollectionSetData::initialize(J9JavaVM *javaVM)112{113PORT_ACCESS_FROM_JAVAVM(javaVM);114MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);115116for(UDATA index = 0; index < MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH; index++) {117_historyTable[index] = (MM_TgcDynamicCollectionSetHistoryElement *)j9mem_allocate_memory(sizeof(MM_TgcDynamicCollectionSetHistoryElement) * (extensions->tarokRegionMaxAge + 1), OMRMEM_CATEGORY_MM);118if(NULL == _historyTable[index]) {119goto error_no_memory;120}121memset(_historyTable[index], 0, sizeof(MM_TgcDynamicCollectionSetHistoryElement) * (extensions->tarokRegionMaxAge + 1));122}123124return true;125126error_no_memory:127return false;128}129130131void132MM_TgcDynamicCollectionSetData::tearDown(J9JavaVM *javaVM)133{134PORT_ACCESS_FROM_JAVAVM(javaVM);135136for(UDATA index = 0; index < MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH; index++) {137if(NULL != _historyTable[index]) {138j9mem_free_memory(_historyTable[index]);139_historyTable[index] = NULL;140}141}142}143144void145MM_TgcDynamicCollectionSetData::decayPrintValue(MM_EnvironmentVLHGC *env, UDATA value)146{147MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(MM_GCExtensions::getExtensions(env));148149char unitTable[] = { 'b', 'k', 'm', 'g', 't' };150char *units = &(unitTable[0]);151UDATA result = value;152UDATA remainder = 0;153154while(result >= 1024) {155remainder = result % 1024;156result /= 1024;157units += 1;158}159160if(result >= 100) {161tgcExtensions->printf("%4zu%c", result, *units);162} else if (result >= 10) {163UDATA decimal = (remainder * 10) / 1024;164tgcExtensions->printf("%2zu.%1.1zu%c", result, decimal, *units);165} else {166if(0 == result) {167tgcExtensions->printf(" 0");168} else {169UDATA decimal = (remainder * 100) / 1024;170tgcExtensions->printf("%1zu.%2.2zu%c", result, decimal, *units);171}172}173}174175void176MM_TgcDynamicCollectionSetData::decayPrintDelta(MM_EnvironmentVLHGC *env, UDATA before, UDATA after)177{178MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(MM_GCExtensions::getExtensions(env));179180if(before >= after) {181if(0 == before) {182tgcExtensions->printf(" %3zu", 0);183} else {184UDATA percentage = ((before - after) * 100) / before;185tgcExtensions->printf(" %3zu", percentage);186}187} else {188UDATA percentage = ((after - before) * 100) / after;189tgcExtensions->printf("(%3zu)", percentage);190}191}192193void194MM_TgcDynamicCollectionSetData::dumpDynamicCollectionSetStatistics(MM_EnvironmentVLHGC *env)195{196MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);197MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);198199MM_CollectionSetDelegate::SetSelectionData *setSelectionDataTable = (MM_CollectionSetDelegate::SetSelectionData *)extensions->tarokTgcSetSelectionDataTable;200201/* Right now we'll just gather results and dump them out */202203/* Rotate the table depth such that "0" is the most recent */204MM_TgcDynamicCollectionSetHistoryElement *currentHistoryTable = _historyTable[MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH - 1];205for(UDATA index = MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH - 1; index > 0; index--) {206_historyTable[index] = _historyTable[index - 1];207}208_historyTable[0] = currentHistoryTable;209210/* Clear the current table of existing data */211memset(currentHistoryTable, 0, sizeof(MM_TgcDynamicCollectionSetHistoryElement) * (extensions->tarokRegionMaxAge + 1));212213/* Walk all regions building up statistics */214GC_HeapRegionIteratorVLHGC regionIterator(extensions->heapRegionManager, MM_HeapRegionDescriptor::MANAGED);215MM_HeapRegionDescriptorVLHGC *region = NULL;216while (NULL != (region = regionIterator.nextRegion())) {217if (region->containsObjects()) {218UDATA ageIndex = region->getLogicalAge();219220Assert_MM_true(region->getLogicalAge() <= extensions->tarokRegionMaxAge);221currentHistoryTable[ageIndex].regionCount += 1;222}223}224225/* Calculate history */226double weight = 0.1;227if(!_historyPrimed) {228_historyPrimed = true;229weight = 1.0;230}231double preserve = 1.0 - weight;232233for(UDATA ageIndex = 0; ageIndex <= extensions->tarokRegionMaxAge; ageIndex++) {234currentHistoryTable[ageIndex].avgHis_regionCount = _historyTable[1][ageIndex].avgHis_regionCount * preserve;235currentHistoryTable[ageIndex].avgHis_regionCount += ((double)currentHistoryTable[ageIndex].regionCount) * weight;236237currentHistoryTable[ageIndex].avgLcl_regionCount = _historyTable[1][ageIndex].avgLcl_regionCount / (double)2.0;238currentHistoryTable[ageIndex].avgLcl_regionCount += ((double)currentHistoryTable[ageIndex].regionCount) / (double)2.0;239}240241/*242* Dump statistics to the TTY.243*/244tgcExtensions->printf("\n ");245for(UDATA tableIndex = 0; tableIndex <= extensions->tarokRegionMaxAge; tableIndex++) {246tgcExtensions->printf(" %5zu", tableIndex);247}248249tgcExtensions->printf("\n ");250for(UDATA tableIndex = 0; tableIndex <= extensions->tarokRegionMaxAge; tableIndex++) {251tgcExtensions->printf("------");252}253254/* Region count */255tgcExtensions->printf("\nRegCnt ");256for(UDATA tableIndex = 0; tableIndex <= extensions->tarokRegionMaxAge; tableIndex++) {257tgcExtensions->printf(" %5zu", currentHistoryTable[tableIndex].regionCount);258}259260tgcExtensions->printf("\n AvgHis ");261for(UDATA ageIndex = 0; ageIndex <= extensions->tarokRegionMaxAge; ageIndex++) {262tgcExtensions->printf(" %5zu", (UDATA)currentHistoryTable[ageIndex].avgHis_regionCount);263}264265tgcExtensions->printf("\n AvgH%2zu ", MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH);266for(UDATA ageIndex = 0; ageIndex <= extensions->tarokRegionMaxAge; ageIndex++) {267tgcExtensions->printf(" %5zu", (UDATA)currentHistoryTable[ageIndex].avgLcl_regionCount);268}269270UDATA compactGroupCount = MM_CompactGroupManager::getCompactGroupMaxCount(env);271tgcExtensions->printf("\nROR ");272MM_CompactGroupPersistentStats *persistentStats = extensions->compactGroupPersistentStats;273for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {274double rateOfReturn = 1.0 - persistentStats[compactGroupIndex]._historicalSurvivalRate;275tgcExtensions->printf(" %5zu", (UDATA)(rateOfReturn * (double)1000.0));276}277278tgcExtensions->printf("\n RgCtB ");279for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {280tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._regionCountBefore);281}282tgcExtensions->printf("\n RgLfB ");283for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {284tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._regionCountArrayletLeafBefore);285}286tgcExtensions->printf("\n RgCtA ");287for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {288tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._regionCountAfter);289}290tgcExtensions->printf("\n RgLfA ");291for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {292tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._regionCountArrayletLeafAfter);293}294295tgcExtensions->printf("\n RgOv ");296for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {297tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._regionCountOverflow);298}299tgcExtensions->printf("\n RgLfOv");300for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {301tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._regionCountArrayletLeafOverflow);302}303304tgcExtensions->printf("\n RcRgB ");305for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {306tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._reclaimableRegionCountBefore);307}308tgcExtensions->printf("\n RcLfB ");309for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {310tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._reclaimableRegionCountArrayletLeafBefore);311}312tgcExtensions->printf("\n RcRgA ");313for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {314tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._reclaimableRegionCountAfter);315}316tgcExtensions->printf("\n RcLfA ");317for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {318tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._reclaimableRegionCountArrayletLeafAfter);319}320321tgcExtensions->printf("\n RcBcB ");322for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {323tgcExtensions->printf(" ");324decayPrintValue(env, setSelectionDataTable[compactGroupIndex]._reclaimStats._reclaimableBytesConsumedBefore);325}326tgcExtensions->printf("\n RcBcA ");327for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {328tgcExtensions->printf(" ");329decayPrintValue(env, setSelectionDataTable[compactGroupIndex]._reclaimStats._reclaimableBytesConsumedAfter);330}331332tgcExtensions->printf("\n");333}334335/**336* Report dynamic collection set statistics for PGC.337*/338static void339tgcHookReportDynamicCollectionSetStatistics(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)340{341MM_VlhgcGarbageCollectCompletedEvent* event = (MM_VlhgcGarbageCollectCompletedEvent*)eventData;342MM_EnvironmentVLHGC *env = MM_EnvironmentVLHGC::getEnvironment(event->currentThread);343344if(MM_GCExtensions::getExtensions(env)->tarokEnableDynamicCollectionSetSelection) {345MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(MM_GCExtensions::getExtensions(env));346MM_TgcDynamicCollectionSetData *dcsData = (MM_TgcDynamicCollectionSetData *)tgcExtensions->_dynamicCollectionSetData;347dcsData->dumpDynamicCollectionSetStatistics(env);348}349}350351/**352* Dump a legend of terms to the tty.353*/354void355dumpLegend(J9JavaVM *javaVM)356{357MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(javaVM);358359tgcExtensions->printf("\nTGC Dynamic Collection Set Glossary");360tgcExtensions->printf("\n-----------------------------------");361362/* Region count */363tgcExtensions->printf("\nRegCnt - Number of regions found in the age group");364tgcExtensions->printf("\n AvgHis - Historical average number of regions found in the age group");365tgcExtensions->printf("\n AvgHxx - Half-life average number of regions found in the age group for the last %zu iterations", (UDATA)MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH);366367tgcExtensions->printf("\nROR - Rate of return when collecting (trace) the region set (amount of currently consumed data that is rendered reclaimable)");368tgcExtensions->printf("\n RgCtB - Region count before collection");369tgcExtensions->printf("\n RgLfB - Leaf region count before collection");370tgcExtensions->printf("\n RgCtA - Region count after collection");371tgcExtensions->printf("\n RgLfA - Leaf region count after collection");372373tgcExtensions->printf("\n RgOv - Regions in an overflow state (uncollectable through normal means)");374tgcExtensions->printf("\n RgLfOv - Leaf regions in an overflow state as a consequence of their parents being overflowed");375376tgcExtensions->printf("\n RcRgB - Reclaimable region count before collection (those marked as part of the collection set)");377tgcExtensions->printf("\n RcLfB - Reclaimable leaf region count before collection");378tgcExtensions->printf("\n RcRgA - Reclaimable region count after collection");379tgcExtensions->printf("\n RcLfA - Reclaimable leaf region count after collection");380381tgcExtensions->printf("\n RcBcB - Reclaimable region bytes consumed before collection");382tgcExtensions->printf("\n RcBcA - Reclaimable region bytes consumed after collection");383384tgcExtensions->printf("\n");385}386387/**388* Initialize dynamic collection set tgc tracing.389* Attaches hooks to the appropriate functions handling events used by dynamic collection set tgc tracing.390*/391bool392tgcDynamicCollectionSetInitialize(J9JavaVM *javaVM)393{394MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);395MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);396bool result = true;397398tgcExtensions->_dynamicCollectionSetData = MM_TgcDynamicCollectionSetData::newInstance(javaVM);399if(NULL != tgcExtensions->_dynamicCollectionSetData) {400J9HookInterface** privateHooks = J9_HOOK_INTERFACE(extensions->privateHookInterface);401(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_VLHGC_GARBAGE_COLLECT_COMPLETED, tgcHookReportDynamicCollectionSetStatistics, OMR_GET_CALLSITE(), NULL);402dumpLegend(javaVM);403} else {404result = false;405}406return result;407}408409/**410* Tear down dynamic collection set tgc tracing.411* Cleans up any support structures related to the specific tgc facility.412*/413void414tgcDynamicCollectionSetTearDown(J9JavaVM *javaVM)415{416MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);417MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);418419if(NULL != tgcExtensions->_dynamicCollectionSetData) {420((MM_TgcDynamicCollectionSetData *)tgcExtensions->_dynamicCollectionSetData)->kill(javaVM);421tgcExtensions->_dynamicCollectionSetData = NULL;422}423}424425426