< prev index next >

core/org.openjdk.jmc.flightrecorder.rules.jdk/src/main/java/org/openjdk/jmc/flightrecorder/rules/jdk/memory/IncreasingLiveSetRule.java

Print this page




  82          * Defines the relative amount of live set increase per second that corresponds to a rule score
  83          * of 75.
  84          */
  85         private static final double PERCENT_OF_HEAP_INCREASE_PER_SECOND = 0.01;
  86 
  87         private static final String RESULT_ID = "IncreasingLiveSet"; //$NON-NLS-1$
  88 
  89         public static final TypedPreference<IQuantity> CLASSES_LOADED_PERCENT = new TypedPreference<>(
  90                         "memleak.classload.percent", Messages.getString(Messages.IncreasingLiveSetRule_LOADED_CLASSES_PERCENT), //$NON-NLS-1$
  91                         Messages.getString(Messages.IncreasingLiveSetRule_LOADED_CLASSES_PERCENT_DESC), PERCENTAGE,
  92                         PERCENT.quantity(90));
  93         public static final TypedPreference<IQuantity> RELEVANCE_THRESHOLD = new TypedPreference<>(
  94                         "memleak.reference.tree.depth", Messages.getString(Messages.IncreasingLiveSetRule_RELEVANCE_THRESHOLD), //$NON-NLS-1$
  95                         Messages.getString(Messages.IncreasingLiveSetRule_RELEVANCE_THRESHOLD_DESC), NUMBER,
  96                         NUMBER_UNITY.quantity(0.5d));
  97         private static final List<TypedPreference<?>> CONFIG_ATTRIBUTES = Arrays
  98                         .<TypedPreference<?>> asList(CLASSES_LOADED_PERCENT, RELEVANCE_THRESHOLD);
  99 
 100         private Result getResult(IItemCollection items, IPreferenceValueProvider valueProvider) {
 101                 EventAvailability eventAvailability = RulesToolkit.getEventAvailability(items, JdkTypeIDs.HEAP_SUMMARY);
 102                 if (eventAvailability == EventAvailability.UNAVAILABLE || eventAvailability == EventAvailability.DISABLED) {
 103                         return RulesToolkit.getEventAvailabilityResult(this, items, eventAvailability, JdkTypeIDs.HEAP_SUMMARY);
 104                 }
 105 
 106                 IQuantity postWarmupTime = getPostWarmupTime(items, valueProvider.getPreferenceValue(CLASSES_LOADED_PERCENT));
 107                 Iterator<? extends IItemIterable> allAfterItems = items.apply(JdkFilters.HEAP_SUMMARY_AFTER_GC).iterator();
 108                 double score = 0;
 109                 IQuantity liveSetIncreasePerSecond = UnitLookup.MEMORY.getUnit(BinaryPrefix.MEBI).quantity(0);
 110                 if (allAfterItems.hasNext()) {
 111                         // FIXME: Handle multiple IItemIterable
 112                         IItemIterable afterItems = allAfterItems.next();
 113                         IMemberAccessor<IQuantity, IItem> timeAccessor = JfrAttributes.END_TIME.getAccessor(afterItems.getType());
 114                         IMemberAccessor<IQuantity, IItem> memAccessor = JdkAttributes.HEAP_USED.getAccessor(afterItems.getType());
 115 
 116                         liveSetIncreasePerSecond = UnitLookup.MEMORY.getUnit(BinaryPrefix.MEBI)
 117                                         .quantity(RulesToolkit.leastSquareMemory(afterItems.iterator(), timeAccessor, memAccessor));
 118 
 119                         if (postWarmupTime == null) {
 120                                 return RulesToolkit.getTooFewEventsResult(this);
 121                         }
 122                         IQuantity postWarmupHeapSize = items
 123                                         .apply(ItemFilters.and(JdkFilters.HEAP_SUMMARY_AFTER_GC,
 124                                                         ItemFilters.moreOrEqual(JfrAttributes.START_TIME, postWarmupTime)))
 125                                         .getAggregate(JdkAggregators.first(JdkAttributes.HEAP_USED));
 126                         if (postWarmupHeapSize == null) {
 127                                 return RulesToolkit.getTooFewEventsResult(this);
 128                         }
 129                         double relativeIncreasePerSecond = liveSetIncreasePerSecond.ratioTo(postWarmupHeapSize);
 130                         score = RulesToolkit.mapExp100(relativeIncreasePerSecond, PERCENT_OF_HEAP_INCREASE_PER_SECOND);
 131                 }
 132                 // If we have Old Object Sample events we can attempt to find suitable memory leak class candidates
 133                 // otherwise we just return the basic increasing live set score
 134                 EventAvailability ea = RulesToolkit.getEventAvailability(items, JdkTypeIDs.OLD_OBJECT_SAMPLE);
 135                 // FIXME: Should construct an message using memoryIncrease, not use a hard limit
 136                 if (score >= 25 && (ea == EventAvailability.DISABLED || ea == EventAvailability.UNAVAILABLE)) {
 137                         String shortMessage = MessageFormat.format(
 138                                         Messages.getString(Messages.IncreasingLiveSetRuleFactory_TEXT_INFO),
 139                                         liveSetIncreasePerSecond.displayUsing(IDisplayable.AUTO));
 140                         String longMessage = shortMessage + "<p>" //$NON-NLS-1$
 141                                         + Messages.getString(Messages.IncreasingLiveSetRuleFactory_TEXT_INFO_LONG);
 142                         return new Result(this, score, shortMessage, longMessage, JdkQueries.HEAP_SUMMARY_AFTER_GC);
 143                 } else if (score < 25) {
 144                         return new Result(this, score, Messages.getString(Messages.IncreasingLiveSetRule_TEXT_OK));
 145                 }
 146 
 147                 // step 1. extract events from after the estimated warmup period
 148                 IItemCollection oldObjectItems = items.apply(ItemFilters.and(ItemFilters.type(JdkTypeIDs.OLD_OBJECT_SAMPLE),
 149                                 ItemFilters.more(JfrAttributes.START_TIME, postWarmupTime)));
 150 
 151                 ReferenceTreeModel tree = ReferenceTreeModel.buildReferenceTree(oldObjectItems);
 152 
 153                 // step 2. perform a balance calculation on the old object sample events aggregated by class count
 154                 boolean anyReferrerChains = false;
 155                 for (ReferenceTreeObject referenceTreeObject : tree.getLeakObjects()) {
 156                         if (referenceTreeObject.getParent() != null) {




  82          * Defines the relative amount of live set increase per second that corresponds to a rule score
  83          * of 75.
  84          */
  85         private static final double PERCENT_OF_HEAP_INCREASE_PER_SECOND = 0.01;
  86 
  87         private static final String RESULT_ID = "IncreasingLiveSet"; //$NON-NLS-1$
  88 
  89         public static final TypedPreference<IQuantity> CLASSES_LOADED_PERCENT = new TypedPreference<>(
  90                         "memleak.classload.percent", Messages.getString(Messages.IncreasingLiveSetRule_LOADED_CLASSES_PERCENT), //$NON-NLS-1$
  91                         Messages.getString(Messages.IncreasingLiveSetRule_LOADED_CLASSES_PERCENT_DESC), PERCENTAGE,
  92                         PERCENT.quantity(90));
  93         public static final TypedPreference<IQuantity> RELEVANCE_THRESHOLD = new TypedPreference<>(
  94                         "memleak.reference.tree.depth", Messages.getString(Messages.IncreasingLiveSetRule_RELEVANCE_THRESHOLD), //$NON-NLS-1$
  95                         Messages.getString(Messages.IncreasingLiveSetRule_RELEVANCE_THRESHOLD_DESC), NUMBER,
  96                         NUMBER_UNITY.quantity(0.5d));
  97         private static final List<TypedPreference<?>> CONFIG_ATTRIBUTES = Arrays
  98                         .<TypedPreference<?>> asList(CLASSES_LOADED_PERCENT, RELEVANCE_THRESHOLD);
  99 
 100         private Result getResult(IItemCollection items, IPreferenceValueProvider valueProvider) {
 101                 EventAvailability eventAvailability = RulesToolkit.getEventAvailability(items, JdkTypeIDs.HEAP_SUMMARY);
 102                 if (eventAvailability == EventAvailability.UNKNOWN || eventAvailability == EventAvailability.DISABLED) {
 103                         return RulesToolkit.getEventAvailabilityResult(this, items, eventAvailability, JdkTypeIDs.HEAP_SUMMARY);
 104                 }
 105 
 106                 IQuantity postWarmupTime = getPostWarmupTime(items, valueProvider.getPreferenceValue(CLASSES_LOADED_PERCENT));
 107                 Iterator<? extends IItemIterable> allAfterItems = items.apply(JdkFilters.HEAP_SUMMARY_AFTER_GC).iterator();
 108                 double score = 0;
 109                 IQuantity liveSetIncreasePerSecond = UnitLookup.MEMORY.getUnit(BinaryPrefix.MEBI).quantity(0);
 110                 if (allAfterItems.hasNext()) {
 111                         // FIXME: Handle multiple IItemIterable
 112                         IItemIterable afterItems = allAfterItems.next();
 113                         IMemberAccessor<IQuantity, IItem> timeAccessor = JfrAttributes.END_TIME.getAccessor(afterItems.getType());
 114                         IMemberAccessor<IQuantity, IItem> memAccessor = JdkAttributes.HEAP_USED.getAccessor(afterItems.getType());
 115 
 116                         liveSetIncreasePerSecond = UnitLookup.MEMORY.getUnit(BinaryPrefix.MEBI)
 117                                         .quantity(RulesToolkit.leastSquareMemory(afterItems.iterator(), timeAccessor, memAccessor));
 118 
 119                         if (postWarmupTime == null) {
 120                                 return RulesToolkit.getTooFewEventsResult(this);
 121                         }
 122                         IQuantity postWarmupHeapSize = items
 123                                         .apply(ItemFilters.and(JdkFilters.HEAP_SUMMARY_AFTER_GC,
 124                                                         ItemFilters.moreOrEqual(JfrAttributes.START_TIME, postWarmupTime)))
 125                                         .getAggregate(JdkAggregators.first(JdkAttributes.HEAP_USED));
 126                         if (postWarmupHeapSize == null) {
 127                                 return RulesToolkit.getTooFewEventsResult(this);
 128                         }
 129                         double relativeIncreasePerSecond = liveSetIncreasePerSecond.ratioTo(postWarmupHeapSize);
 130                         score = RulesToolkit.mapExp100(relativeIncreasePerSecond, PERCENT_OF_HEAP_INCREASE_PER_SECOND);
 131                 }
 132                 // If we have Old Object Sample events we can attempt to find suitable memory leak class candidates
 133                 // otherwise we just return the basic increasing live set score
 134                 EventAvailability ea = RulesToolkit.getEventAvailability(items, JdkTypeIDs.OLD_OBJECT_SAMPLE);
 135                 // FIXME: Should construct an message using memoryIncrease, not use a hard limit
 136                 if (score >= 25 && (ea == EventAvailability.DISABLED || ea == EventAvailability.UNKNOWN)) {
 137                         String shortMessage = MessageFormat.format(
 138                                         Messages.getString(Messages.IncreasingLiveSetRuleFactory_TEXT_INFO),
 139                                         liveSetIncreasePerSecond.displayUsing(IDisplayable.AUTO));
 140                         String longMessage = shortMessage + "<p>" //$NON-NLS-1$
 141                                         + Messages.getString(Messages.IncreasingLiveSetRuleFactory_TEXT_INFO_LONG);
 142                         return new Result(this, score, shortMessage, longMessage, JdkQueries.HEAP_SUMMARY_AFTER_GC);
 143                 } else if (score < 25) {
 144                         return new Result(this, score, Messages.getString(Messages.IncreasingLiveSetRule_TEXT_OK));
 145                 }
 146 
 147                 // step 1. extract events from after the estimated warmup period
 148                 IItemCollection oldObjectItems = items.apply(ItemFilters.and(ItemFilters.type(JdkTypeIDs.OLD_OBJECT_SAMPLE),
 149                                 ItemFilters.more(JfrAttributes.START_TIME, postWarmupTime)));
 150 
 151                 ReferenceTreeModel tree = ReferenceTreeModel.buildReferenceTree(oldObjectItems);
 152 
 153                 // step 2. perform a balance calculation on the old object sample events aggregated by class count
 154                 boolean anyReferrerChains = false;
 155                 for (ReferenceTreeObject referenceTreeObject : tree.getLeakObjects()) {
 156                         if (referenceTreeObject.getParent() != null) {


< prev index next >