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.text.MessageFormat; 36 import java.util.Collection; 37 import java.util.Collections; 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.IDisplayable; 43 import org.openjdk.jmc.common.item.IItemCollection; 44 import org.openjdk.jmc.common.unit.IQuantity; 45 import org.openjdk.jmc.common.unit.UnitLookup; 46 import org.openjdk.jmc.common.util.IPreferenceValueProvider; 47 import org.openjdk.jmc.common.util.TypedPreference; 48 import org.openjdk.jmc.flightrecorder.jdk.JdkAggregators; 49 import org.openjdk.jmc.flightrecorder.jdk.JdkTypeIDs; 50 import org.openjdk.jmc.flightrecorder.rules.IRule; 51 import org.openjdk.jmc.flightrecorder.rules.Result; 52 import org.openjdk.jmc.flightrecorder.rules.jdk.messages.internal.Messages; 53 import org.openjdk.jmc.flightrecorder.rules.util.JfrRuleTopics; 54 import org.openjdk.jmc.flightrecorder.rules.util.RulesToolkit; 55 import org.openjdk.jmc.flightrecorder.rules.util.RulesToolkit.EventAvailability; 56 57 public class TlabAllocationRatioRule implements IRule { 58 59 private static final String RESULT_ID = "TlabAllocationRatio"; //$NON-NLS-1$ 60 61 private Result getResult(IItemCollection items, IPreferenceValueProvider valueProvider) { 62 63 EventAvailability eventAvailability = RulesToolkit.getEventAvailability(items, JdkTypeIDs.ALLOC_INSIDE_TLAB, 64 JdkTypeIDs.ALLOC_OUTSIDE_TLAB); 65 if (eventAvailability == EventAvailability.DISABLED || eventAvailability == EventAvailability.UNKNOWN) { 66 return RulesToolkit.getEventAvailabilityResult(this, items, eventAvailability, JdkTypeIDs.ALLOC_INSIDE_TLAB, 67 JdkTypeIDs.ALLOC_OUTSIDE_TLAB); 68 } 69 70 IQuantity insideSum = items.getAggregate(JdkAggregators.ALLOC_INSIDE_TLAB_SUM); 71 IQuantity outsideSum = items.getAggregate(JdkAggregators.ALLOC_OUTSIDE_TLAB_SUM); 72 73 if (outsideSum == null) { 74 return new Result(this, 0, Messages.getString(Messages.TlabAllocationRatioRuleFactory_TEXT_OK_NO_OUTSIDE)); 75 } else if (insideSum == null) { 76 String shortMessage = Messages.getString(Messages.TlabAllocationRatioRuleFactory_TEXT_INFO_ONLY_OUTSIDE); 77 String longMessage = Messages.getString(Messages.TlabAllocationRatioRuleFactory_TEXT_INFO_ONLY_OUTSIDE_LONG) 78 + "<p>" //$NON-NLS-1$ 79 + Messages.getString(Messages.TlabAllocationRatioRuleFactory_TEXT_RECOMMEND_LESS_ALLOCATION); 80 return new Result(this, 100, shortMessage, longMessage); 81 } 82 83 IQuantity totalSum = insideSum.add(outsideSum); 84 85 double rawRatio = outsideSum.ratioTo(totalSum); 86 // FIXME: Configuration attribute instead of hard coded 0.2 for info limit 87 double score = RulesToolkit.mapExp74(rawRatio, 0.2); 88 String shortMessage = MessageFormat.format( 89 Messages.getString(Messages.TlabAllocationRatioRuleFactory_TEXT_INFO), 90 UnitLookup.PERCENT_UNITY.quantity(rawRatio).displayUsing(IDisplayable.AUTO)); 91 String longMessage = shortMessage; 92 if (score >= 25) { 93 longMessage = longMessage + "<p>" //$NON-NLS-1$ 94 + Messages.getString(Messages.TlabAllocationRatioRuleFactory_TEXT_RECOMMEND_LESS_ALLOCATION); 95 } 96 return new Result(this, score, shortMessage, longMessage); 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.TlabAllocationRatioRuleFactory_RULE_NAME); 123 } 124 125 @Override 126 public String getTopic() { 127 return JfrRuleTopics.TLAB_TOPIC; 128 } 129 130 }