1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * The contents of this file are subject to the terms of either the Universal Permissive License 7 * v 1.0 as shown at http://oss.oracle.com/licenses/upl 8 * 9 * or the following license: 10 * 11 * Redistribution and use in source and binary forms, with or without modification, are permitted 12 * provided that the following conditions are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 15 * and the following disclaimer. 16 * 17 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 18 * conditions and the following disclaimer in the documentation and/or other materials provided with 19 * the distribution. 20 * 21 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to 22 * endorse or promote products derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 26 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 31 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 package org.openjdk.jmc.flightrecorder.rules.jdk.memory; 34 35 import java.util.Collection; 36 import java.util.Collections; 37 import java.util.Iterator; 38 import java.util.concurrent.Callable; 39 import java.util.concurrent.FutureTask; 40 import java.util.concurrent.RunnableFuture; 41 42 import org.openjdk.jmc.common.item.IItem; 43 import org.openjdk.jmc.common.item.IItemCollection; 44 import org.openjdk.jmc.common.item.IItemFilter; 45 import org.openjdk.jmc.common.item.IItemIterable; 46 import org.openjdk.jmc.common.item.IMemberAccessor; 47 import org.openjdk.jmc.common.item.ItemFilters; 48 import org.openjdk.jmc.common.unit.IQuantity; 49 import org.openjdk.jmc.common.util.IPreferenceValueProvider; 50 import org.openjdk.jmc.common.util.TypedPreference; 51 import org.openjdk.jmc.flightrecorder.JfrAttributes; 52 import org.openjdk.jmc.flightrecorder.jdk.JdkAttributes; 53 import org.openjdk.jmc.flightrecorder.jdk.JdkFilters; 54 import org.openjdk.jmc.flightrecorder.jdk.JdkQueries; 55 import org.openjdk.jmc.flightrecorder.jdk.JdkTypeIDs; 56 import org.openjdk.jmc.flightrecorder.rules.IRule; 57 import org.openjdk.jmc.flightrecorder.rules.Result; 58 import org.openjdk.jmc.flightrecorder.rules.jdk.messages.internal.Messages; 59 import org.openjdk.jmc.flightrecorder.rules.util.JfrRuleTopics; 60 import org.openjdk.jmc.flightrecorder.rules.util.RulesToolkit; 61 import org.openjdk.jmc.flightrecorder.rules.util.RulesToolkit.EventAvailability; 62 63 public class IncreasingMetaspaceLiveSetRule implements IRule { 64 65 private static final String RESULT_ID = "IncreasingMetaSpaceLiveSet"; //$NON-NLS-1$ 66 67 private Result getResult(IItemCollection items, IPreferenceValueProvider valueProvider) { 68 EventAvailability eventAvailability = RulesToolkit.getEventAvailability(items, JdkTypeIDs.METASPACE_SUMMARY); 69 if (eventAvailability == EventAvailability.UNKNOWN || eventAvailability == EventAvailability.DISABLED) { 70 return RulesToolkit.getEventAvailabilityResult(this, items, eventAvailability, 71 JdkTypeIDs.METASPACE_SUMMARY); 72 } 73 74 IItemFilter afterFilter = ItemFilters.and(JdkFilters.METASPACE_SUMMARY_AFTER_GC, JdkFilters.AFTER_GC); 75 Iterator<? extends IItemIterable> allAfterItems = items.apply(afterFilter).iterator(); 76 if (allAfterItems.hasNext()) { 77 IItemIterable afterItems = allAfterItems.next(); 78 // FIXME: Handle multiple IItemIterable 79 IMemberAccessor<IQuantity, IItem> timeAccessor = JfrAttributes.END_TIME.getAccessor(afterItems.getType()); 80 IMemberAccessor<IQuantity, IItem> memAccessor = JdkAttributes.GC_METASPACE_USED 81 .getAccessor(afterItems.getType()); 82 double leastSquare = RulesToolkit.leastSquareMemory(afterItems.iterator(), timeAccessor, memAccessor); 83 // FIXME: Configuration attribute 84 double score = RulesToolkit.mapExp100(leastSquare, 0.75); 85 // FIXME: Should construct a message using leastSquare, not use a hard limit 86 if (score >= 25) { 87 String shortMessage = Messages.getString(Messages.IncreasingMetaspaceLiveSetRuleFactory_TEXT_INFO); 88 String longMessage = shortMessage + " " //$NON-NLS-1$ 89 + Messages.getString(Messages.IncreasingMetaspaceLiveSetRuleFactory_TEXT_INFO_LONG); 90 return new Result(this, score, shortMessage, longMessage, JdkQueries.METASPACE_SUMMARY_AFTER_GC); 91 } 92 return new Result(this, score, Messages.getString(Messages.IncreasingMetaspaceLiveSetRuleFactory_TEXT_OK), 93 null, JdkQueries.METASPACE_SUMMARY_AFTER_GC); 94 } 95 return new Result(this, 0, Messages.getString(Messages.IncreasingMetaspaceLiveSetRuleFactory_TEXT_OK), null, 96 JdkQueries.METASPACE_SUMMARY_AFTER_GC); 97 } 98 99 @Override 100 public RunnableFuture<Result> evaluate(final IItemCollection items, final IPreferenceValueProvider valueProvider) { 101 FutureTask<Result> evaluationTask = new FutureTask<>(new Callable<Result>() { 102 @Override 103 public Result call() throws Exception { 104 return getResult(items, valueProvider); 105 } 106 }); 107 return evaluationTask; 108 } 109 110 @Override 111 public Collection<TypedPreference<?>> getConfigurationAttributes() { 112 return Collections.emptyList(); 113 } 114 115 @Override 116 public String getId() { 117 return RESULT_ID; 118 } 119 120 @Override 121 public String getName() { 122 return Messages.getString(Messages.IncreasingMetaspaceLiveSetRuleFactory_RULE_NAME); 123 } 124 125 @Override 126 public String getTopic() { 127 return JfrRuleTopics.GARBAGE_COLLECTION_TOPIC; 128 } 129 }