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.general; 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.BinaryPrefix; 45 import org.openjdk.jmc.common.unit.IQuantity; 46 import org.openjdk.jmc.common.unit.UnitLookup; 47 import org.openjdk.jmc.common.util.IPreferenceValueProvider; 48 import org.openjdk.jmc.common.util.TypedPreference; 49 import org.openjdk.jmc.flightrecorder.jdk.JdkAggregators; 50 import org.openjdk.jmc.flightrecorder.jdk.JdkTypeIDs; 51 import org.openjdk.jmc.flightrecorder.rules.IRule; 52 import org.openjdk.jmc.flightrecorder.rules.Result; 53 import org.openjdk.jmc.flightrecorder.rules.jdk.memory.CollectorType; 54 import org.openjdk.jmc.flightrecorder.rules.jdk.messages.internal.Messages; 55 import org.openjdk.jmc.flightrecorder.rules.util.JfrRuleTopics; 56 import org.openjdk.jmc.flightrecorder.rules.util.RulesToolkit; 57 import org.openjdk.jmc.flightrecorder.rules.util.RulesToolkit.EventAvailability; 58 59 public class DiscouragedGcOptionsRule implements IRule { 60 private static final IQuantity LARGE_HEAP = UnitLookup.MEMORY.getUnit(BinaryPrefix.GIBI).quantity(4); 61 private static final IQuantity HW_THREADS_FOR_MULTI_CPU = UnitLookup.NUMBER_UNITY.quantity(4); 62 private static final IQuantity ONE = UnitLookup.NUMBER_UNITY.quantity(1); 63 64 private static final String GC_OPTIONS_RESULT_ID = "GcOptions"; //$NON-NLS-1$ 65 66 private Result getResult(IItemCollection items, IPreferenceValueProvider valueProvider) { 67 EventAvailability eventAvailability = RulesToolkit.getEventAvailability(items, JdkTypeIDs.CPU_INFORMATION); 68 if (eventAvailability == EventAvailability.UNKNOWN || eventAvailability == EventAvailability.DISABLED) { 69 return RulesToolkit.getEventAvailabilityResult(this, items, eventAvailability, JdkTypeIDs.CPU_INFORMATION); 70 } 71 72 IQuantity parallelGCThreads = items.getAggregate(JdkAggregators.PARALLEL_GC_THREAD_COUNT_MAX); 73 IQuantity minHwThreads = items.getAggregate(JdkAggregators.MIN_HW_THREADS); 74 CollectorType oc = CollectorType.getOldCollectorType(items); 75 if (parallelGCThreads != null && minHwThreads != null && oc != null) { 76 if (oc == CollectorType.SERIAL_OLD) { 77 IQuantity maxHeapSize = items.getAggregate(JdkAggregators.HEAP_CONF_MAX_SIZE); 78 if (minHwThreads.compareTo(HW_THREADS_FOR_MULTI_CPU) >= 0 && maxHeapSize != null 79 && maxHeapSize.compareTo(LARGE_HEAP) > 0) { 80 return new Result(this, 50, Messages.getString(Messages.SerialGcOnMultiCpuRuleFactory_TEXT_INFO), 81 Messages.getString(Messages.SerialGcOnMultiCpuRuleFactory_TEXT_INFO_LONG)); 82 } 83 } else if (minHwThreads.compareTo(ONE) == 0 && oc == CollectorType.PARALLEL_OLD) { 84 return new Result(this, 50, Messages.getString(Messages.ParallelOnSingleCpuRuleFactory_TEXT_INFO), 85 Messages.getString(Messages.ParallelOnSingleCpuRuleFactory_TEXT_INFO_LONG)); 86 } else if (parallelGCThreads.compareTo(minHwThreads) > 0) { 87 String message = MessageFormat.format( 88 Messages.getString(Messages.NumberOfGcThreadsRuleFactory_TEXT_INFO), parallelGCThreads, 89 minHwThreads.displayUsing(IDisplayable.AUTO)); 90 String longMessage = message + " " //$NON-NLS-1$ 91 + Messages.getString(Messages.NumberOfGcThreadsRuleFactory_TEXT_INFO_LONG); 92 return new Result(this, 50, message, longMessage); 93 } else if (parallelGCThreads.compareTo(ONE) == 0 94 && (oc == CollectorType.PARALLEL_OLD || oc == CollectorType.G1_OLD)) { 95 return new Result(this, 50, Messages.getString(Messages.ParGcFewThreadsRuleFactory_TEXT_INFO), 96 Messages.getString(Messages.ParGcFewThreadsRuleFactory_TEXT_INFO_LONG)); 97 } 98 return new Result(this, 0, Messages.getString(Messages.DiscouragedGcOptionsRule_TEXT_OK)); 99 } 100 return RulesToolkit.getTooFewEventsResult(this); 101 } 102 103 @Override 104 public RunnableFuture<Result> evaluate(final IItemCollection items, final IPreferenceValueProvider valueProvider) { 105 FutureTask<Result> evaluationTask = new FutureTask<>(new Callable<Result>() { 106 @Override 107 public Result call() throws Exception { 108 return getResult(items, valueProvider); 109 } 110 }); 111 return evaluationTask; 112 } 113 114 @Override 115 public Collection<TypedPreference<?>> getConfigurationAttributes() { 116 return Collections.emptyList(); 117 } 118 119 @Override 120 public String getId() { 121 return GC_OPTIONS_RESULT_ID; 122 } 123 124 @Override 125 public String getName() { 126 return Messages.getString(Messages.DiscouragedGcOptionsRule_RULE_NAME); 127 } 128 129 @Override 130 public String getTopic() { 131 return JfrRuleTopics.JVM_INFORMATION_TOPIC; 132 } 133 }