Path: blob/master/runtime/gc_trace_vlhgc/TgcInterRegionRememberedSet.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 "GCExtensions.hpp"30#include "TgcExtensions.hpp"3132#include "CycleState.hpp"33#include "EnvironmentVLHGC.hpp"34#include "HeapRegionDescriptorVLHGC.hpp"35#include "HeapRegionManager.hpp"36#include "IncrementalGenerationalGC.hpp"37#include "InterRegionRememberedSet.hpp"38#include "RememberedSetCardListCardIterator.hpp"394041/* Histogram buckets */42#define MAX_BUCKETS 1843struct Bucket {44UDATA regionCount;45UDATA duplicates;46UDATA cardCount;47};4849enum {50DISTINCT_FLAG_ARRAY_SHIFT = 4 /* for duplicate/distinct card list count we used a hash table, this is a factor which tells how hash table is big relative to RSCL */51};5253static UDATA54getUpperBoundDuplicatesCount(MM_EnvironmentVLHGC *env, MM_RememberedSetCardList *rscl)55{56UDATA duplicateCount = 0;5758if (MM_GCExtensions::getExtensions(env)->tarokTgcEnableRememberedSetDuplicateDetection) {59MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(MM_GCExtensions::getExtensions(env));6061/* If lazy initialize of _rsclDistinctFlagArray failed, we'll skip calculating duplicates */62if (NULL != tgcExtensions->_rsclDistinctFlagArray) {63UDATA cardListSize = rscl->getSize(env);64UDATA distinctFlagArraySize = cardListSize << DISTINCT_FLAG_ARRAY_SHIFT;65for (UDATA i = 0; i < distinctFlagArraySize; i++) {66tgcExtensions->_rsclDistinctFlagArray[i] = 0;67}6869GC_RememberedSetCardListCardIterator rsclCardIterator(rscl);70void *cardAddress = NULL;71while(NULL != (cardAddress = rsclCardIterator.nextReferencingCardHeapAddress(env))) {72/* card addresses are CARD_SIZE bytes aligned, thus stripping low bits that are 0s (use the shift value corresponding to the size) */73/* prime 100000007 should be larger than distinctFlagArraySize * 8bits */74UDATA hash = ((UDATA)cardAddress >> CARD_SIZE_SHIFT) % 100000007;75UDATA bit = hash & 0x7;76UDATA index = (hash >> 3) % distinctFlagArraySize;77tgcExtensions->_rsclDistinctFlagArray[index] |= (1 << bit);78}7980UDATA distinctCount = 0;8182for (UDATA i = 0; i < distinctFlagArraySize; i++) {83U_8 flag = tgcExtensions->_rsclDistinctFlagArray[i];84if (0 != flag) {85for (UDATA bitShift = 0; bitShift < 8; bitShift++) {86U_8 bit = 1 << bitShift;87if (bit == (tgcExtensions->_rsclDistinctFlagArray[i] & bit)) {88distinctCount += 1;89}90}91}92}9394duplicateCount = cardListSize - distinctCount;95}96}9798return duplicateCount;99100}101102/**103* Print a histogram of the objects using classList104*/105static void106calculateAndPrintHistogram(J9VMThread *vmThread, MM_HeapRegionManager *regionManager, const char *eventString, UDATA totalReferences, UDATA maxReferences)107{108J9JavaVM *javaVM = vmThread->javaVM;109MM_EnvironmentVLHGC *env = MM_EnvironmentVLHGC::getEnvironment(vmThread);110MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);111MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);112maxReferences = extensions->tarokRememberedSetCardListMaxSize;113UDATA regionCount = regionManager->getTableRegionCount();114double totalPercent = ((double)totalReferences / ((double)regionCount * (double)extensions->tarokRememberedSetCardListSize)) * 100.0;115UDATA totalDuplicates = 0;116117tgcExtensions->printf("{RSCL: %zu (%.2f%%) total reference cards to regions; max %zu per region}\n", totalReferences, totalPercent, maxReferences);118if (maxReferences > 0) {119Bucket buckets[MAX_BUCKETS];120UDATA maxForBucket[MAX_BUCKETS - 1];121UDATA increment = (maxReferences + MAX_BUCKETS - 3) / (MAX_BUCKETS - 2);122UDATA i = 0;123for (i = 0; i < MAX_BUCKETS; i++) {124buckets[i].regionCount = 0;125buckets[i].duplicates = 0;126buckets[i].cardCount = 0;127}128for (i = 0; i < MAX_BUCKETS - 1; i++) {129maxForBucket[i] = i * increment;130}131132tgcExtensions->printf("{RSCL: Histogram of reference cards TO regions after %s. Duplicates percentage in brackets left to the region count. }\n{RSCL: Refs ", eventString);133UDATA minForBucket = 0;134for (i = 0; i < MAX_BUCKETS - 1; i++) {135if (minForBucket < maxForBucket[i]) {136if (100000 <= maxForBucket[i]) {137tgcExtensions->printf(" <=%3zuK", maxForBucket[i]/1024);138} else {139tgcExtensions->printf(" <=%5zu", maxForBucket[i]);140}141} else {142tgcExtensions->printf(" =%5zu", maxForBucket[i]);143}144minForBucket = maxForBucket[i] + 1;145}146tgcExtensions->printf(" OF");147148for (UDATA age = 0; age <= extensions->tarokRegionMaxAge; age++) {149for (i = 0; i < regionCount; i++) {150MM_HeapRegionDescriptorVLHGC *region = (MM_HeapRegionDescriptorVLHGC *)regionManager->physicalTableDescriptorForIndex(i);151if (age == region->getLogicalAge()) {152UDATA cardCount = region->getRememberedSetCardList()->getSize(env);153UDATA duplicates = getUpperBoundDuplicatesCount(env, region->getRememberedSetCardList());154UDATA bucketIndex;155if (region->getRememberedSetCardList()->isOverflowed()) {156bucketIndex = MAX_BUCKETS - 1;157} else {158bucketIndex = (cardCount + increment - 1) / increment;159}160buckets[bucketIndex].regionCount += 1;161buckets[bucketIndex].cardCount += cardCount;162buckets[bucketIndex].duplicates += duplicates;163totalDuplicates += duplicates;164}165}166167tgcExtensions->printf(" }\n{RSCL: age %2zu ", age);168for (i = 0; i < MAX_BUCKETS; i++) {169UDATA duplicatePercentage = 0;170if (0 != buckets[i].cardCount) {171duplicatePercentage = 100 * buckets[i].duplicates / buckets[i].cardCount;172}173if (0 != duplicatePercentage) {174tgcExtensions->printf(" (%2zu)%3zu", duplicatePercentage, buckets[i].regionCount);175} else {176tgcExtensions->printf(" %7zu", buckets[i].regionCount);177}178buckets[i].regionCount = 0;179buckets[i].duplicates = 0;180buckets[i].cardCount = 0;181}182}183184tgcExtensions->printf(" }\n");185tgcExtensions->printf("{RSCL: Total duplicates: %zu%% }\n", totalReferences ? (totalDuplicates * 100 / totalReferences): (UDATA)0);186}187}188189190/**191* Report RSCL histogram prior to a collection192*/193static void194tgcHookReportInterRegionRememberedSetHistogram(J9HookInterface** hookInterface, UDATA eventNum, void* eventData, void* userData)195{196J9VMThread* vmThread = NULL;197const char *eventString = NULL;198J9JavaVM *javaVM = (J9JavaVM *) userData;199MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);200MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);201MM_EnvironmentVLHGC env(javaVM);202J9HookInterface** externalHookInterface = extensions->getHookInterface();203J9HookInterface** privateHookInterface = extensions->getPrivateHookInterface();204205if ((J9HOOK_MM_PRIVATE_MARK_END == eventNum) && ( privateHookInterface == hookInterface)) {206MM_MarkEndEvent* event = (MM_MarkEndEvent*)eventData;207vmThread = static_cast<J9VMThread *>(event->currentThread->_language_vmthread);208eventString = "Mark";209} else if ((J9HOOK_MM_OMR_COMPACT_END == eventNum) && ( externalHookInterface == hookInterface)) {210MM_CompactEndEvent* event = (MM_CompactEndEvent*)eventData;211vmThread = (J9VMThread *)event->omrVMThread->_language_vmthread;212eventString = "Compact";213} else if (J9HOOK_MM_PRIVATE_COPY_FORWARD_END == eventNum && ( privateHookInterface == hookInterface)) {214MM_CopyForwardEndEvent* event = (MM_CopyForwardEndEvent*)eventData;215vmThread = static_cast<J9VMThread *>(event->currentThread->_language_vmthread);216eventString = "CopyForward";217} else {218Assert_MM_unreachable();219}220221/* Lazy allocate for _rsclDistinctFlagArray222* (count not be done in Initialize, since tarokRememberedSetCardListMaxSize might have not be set yet223*/224if (NULL == tgcExtensions->_rsclDistinctFlagArray) {225tgcExtensions->_rsclDistinctFlagArray = (U_8 *)extensions->getForge()->allocate(extensions->tarokRememberedSetCardListMaxSize << DISTINCT_FLAG_ARRAY_SHIFT, MM_AllocationCategory::FIXED, J9_GET_CALLSITE());226}227228MM_HeapRegionManager *regionManager = extensions->heap->getHeapRegionManager();229UDATA regionCount = regionManager->getTableRegionCount();230231UDATA maxCardsToRegion = 0;232UDATA totalCardsToRegions = 0;233234for (UDATA i = 0; i < regionCount; i++) {235MM_HeapRegionDescriptorVLHGC *region = (MM_HeapRegionDescriptorVLHGC *)regionManager->physicalTableDescriptorForIndex(i);236maxCardsToRegion = OMR_MAX(maxCardsToRegion, region->getRememberedSetCardList()->getSize(&env));237totalCardsToRegions += region->getRememberedSetCardList()->getSize(&env);238}239240calculateAndPrintHistogram(vmThread, regionManager, eventString, totalCardsToRegions, maxCardsToRegion);241}242243244/**245* Initialize inter region remembered set tgc tracing.246* Initializes the TgcInterRegionRememberedSetExtensions object associated with irrs tgc tracing. Attaches hooks247* to the appropriate functions handling events used by irrs tgc tracing.248*/249bool250tgcInterRegionRememberedSetInitialize(J9JavaVM *javaVM)251{252MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);253bool result = true;254255J9HookInterface** privateHooks = J9_HOOK_INTERFACE(extensions->privateHookInterface);256J9HookInterface** omrHooks = J9_HOOK_INTERFACE(extensions->omrHookInterface);257(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_MARK_END, tgcHookReportInterRegionRememberedSetHistogram, OMR_GET_CALLSITE(), javaVM);258(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_COMPACT_END, tgcHookReportInterRegionRememberedSetHistogram, OMR_GET_CALLSITE(), javaVM);259(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_COPY_FORWARD_END, tgcHookReportInterRegionRememberedSetHistogram, OMR_GET_CALLSITE(), javaVM);260261return result;262}263264void265tgcInterRegionRememberedSetTearDown(J9JavaVM *javaVM)266{267MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);268MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);269270if (NULL != tgcExtensions->_rsclDistinctFlagArray) {271extensions->getForge()->free(tgcExtensions->_rsclDistinctFlagArray);272}273}274275276