/* Copyright 2012 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.arbeitspferde.groningen.experimentdb.jvmflags;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Range;
import org.arbeitspferde.groningen.proto.GroningenConfigProto;
/**
* An enumeration of the JVM flags that Groningen can manage.
*
* This class does not perform a lot of work itself but delegates much of it to
* a variant of the flyweight design pattern with {@link Formatters} and
* {@link Formatter}. The documentation contained therein notes why these
* facets are not defined as attributes of this class itself.
*/
public enum JvmFlag {
// We are using Integer.MAX_VALUE - 1 as the max value (inclusive). The
// Hypothesizer adds one to
// this value and generates a random value from 0 inclusive to
// Integer.MAX_VALUE exclusive.
// TODO(team): Look at better ways of implementing this.
HEAP_SIZE("<special-never-should-be-exposed>", HotSpotFlagType.NON_STANDARD, 1L, 64 * 1024L, 1L,
DataSize.MEGA, ValueSeparator.NONE),
ADAPTIVE_SIZE_DECREMENT_SCALE_FACTOR("AdaptiveSizeDecrementScaleFactor",
HotSpotFlagType.UNSTABLE, 0L, 100L, 1L, DataSize.NONE, ValueSeparator.EQUAL),
CMS_EXP_AVG_FACTOR("CMSExpAvgFactor", HotSpotFlagType.UNSTABLE, 0L, 100L, 1L, DataSize.NONE,
ValueSeparator.EQUAL),
CMS_INCREMENTAL_DUTY_CYCLE("CMSIncrementalDutyCycle", HotSpotFlagType.UNSTABLE, 0L, 100L, 1L,
DataSize.NONE, ValueSeparator.EQUAL),
CMS_INCREMENTAL_DUTY_CYCLE_MIN("CMSIncrementalDutyCycleMin", HotSpotFlagType.UNSTABLE, 0L, 100L,
1L, DataSize.NONE, ValueSeparator.EQUAL),
CMS_INCREMENTAL_OFFSET("CMSIncrementalOffset", HotSpotFlagType.UNSTABLE, 0L, 100L, 1L,
DataSize.NONE, ValueSeparator.EQUAL),
CMS_INCREMENTAL_SAFETY_FACTOR("CMSIncrementalSafetyFactor", HotSpotFlagType.UNSTABLE, 0L, 100L,
1L, DataSize.NONE, ValueSeparator.EQUAL),
CMS_INITIATING_OCCUPANCY_FRACTION("CMSInitiatingOccupancyFraction", HotSpotFlagType.UNSTABLE, 0L,
100L, 1L, DataSize.NONE, ValueSeparator.EQUAL),
GC_TIME_RATIO("GCTimeRatio", HotSpotFlagType.UNSTABLE, 0L, 1000L, 1L, DataSize.NONE,
ValueSeparator.EQUAL),
MAX_GC_PAUSE_MILLIS("MaxGCPauseMillis", HotSpotFlagType.UNSTABLE, 0L, 1000000L, 1L,
DataSize.NONE, ValueSeparator.EQUAL),
MAX_HEAP_FREE_RATIO("MaxHeapFreeRatio", HotSpotFlagType.UNSTABLE, 0L, 100L, 1L, DataSize.NONE,
ValueSeparator.EQUAL),
MAX_NEW_SIZE("MaxNewSize", HotSpotFlagType.UNSTABLE, 0L, 32 * 1024L, 16L, DataSize.MEGA,
ValueSeparator.EQUAL),
MIN_HEAP_FREE_RATIO("MinHeapFreeRatio", HotSpotFlagType.UNSTABLE, 0L, 100L, 1L, DataSize.NONE,
ValueSeparator.EQUAL),
NEW_RATIO("NewRatio", HotSpotFlagType.UNSTABLE, 0L, 1000L, 1L, DataSize.NONE,
ValueSeparator.EQUAL),
NEW_SIZE("NewSize", HotSpotFlagType.UNSTABLE, 0L, 32 * 1024L, 16L, DataSize.MEGA,
ValueSeparator.EQUAL),
PARALLEL_GC_THREADS("ParallelGCThreads", HotSpotFlagType.UNSTABLE, 0L, 100000L, 10L,
DataSize.NONE, ValueSeparator.EQUAL),
SURVIVOR_RATIO("SurvivorRatio", HotSpotFlagType.UNSTABLE, 0L, 1000L, 1L, DataSize.NONE,
ValueSeparator.EQUAL),
SOFT_REF_LRU_POLICY_MS_PER_MB("SoftRefLRUPolicyMSPerMB", HotSpotFlagType.UNSTABLE, 0L, 1000000L,
1000L, DataSize.NONE, ValueSeparator.EQUAL),
TENURED_GENERATION_SIZE_INCREMENT("TenuredGenerationSizeIncrement", HotSpotFlagType.UNSTABLE, 0L,
100L, 1L, DataSize.NONE, ValueSeparator.EQUAL),
YOUNG_GENERATION_SIZE_INCREMENT("YoungGenerationSizeIncrement", HotSpotFlagType.UNSTABLE, 0L,
100L, 1L, DataSize.NONE, ValueSeparator.EQUAL),
CMS_INCREMENTAL_MODE("CMSIncrementalMode", HotSpotFlagType.UNSTABLE),
CMS_INCREMENTAL_PACING("CMSIncrementalPacing", HotSpotFlagType.UNSTABLE),
USE_CMS_INITIATING_OCCUPANCY_ONLY("UseCMSInitiatingOccupancyOnly", HotSpotFlagType.UNSTABLE),
USE_CONC_MARK_SWEEP_GC("UseConcMarkSweepGC", HotSpotFlagType.UNSTABLE),
USE_PARALLEL_GC("UseParallelGC", HotSpotFlagType.UNSTABLE),
USE_PARALLEL_OLD_GC("UseParallelOldGC", HotSpotFlagType.UNSTABLE),
USE_SERIAL_GC("UseSerialGC", HotSpotFlagType.UNSTABLE);
/**
* The human-readable flag name that excludes the flag-specific argument
* prefix, infix, suffix, and respective assignment value.
*/
private final String name;
/**
* The type of flag that the flag is.
*/
private final HotSpotFlagType hotSpotFlagType;
/**
* The {@link Formatter} flyweight.
*/
private final Formatter formatter;
/**
* The minimum acceptable value for the flag.
*/
private final Long floorValue;
/**
* The maximum acceptable value for the flag.
*/
private final Long ceilingValue;
/**
* The size of the increment.
*/
private final Long stepSize;
/**
* The associated scalar data size associated with this flag.
*/
private final DataSize dataSize;
/**
* The type of infix delimiter between flag name and proposed value.
*/
private final ValueSeparator valueSeparator;
/**
* The range of values allowed.
*/
private final Range<Long> acceptableValueRange;
private static final ImmutableSortedSet<JvmFlag> GC_MODE_FLAGS = ImmutableSortedSet.<JvmFlag>naturalOrder()
.add(USE_CONC_MARK_SWEEP_GC)
.add(USE_PARALLEL_GC)
.add(USE_PARALLEL_OLD_GC)
.add(USE_SERIAL_GC)
.build();
/**
* Construct a new boolean flag.
*
* @param name The name of the flag.
* @param hotSpotFlagType The type of the flag.
*/
private JvmFlag(final String name, final HotSpotFlagType hotSpotFlagType) {
this.name = Preconditions.checkNotNull(name, "name may not be null.");
this.hotSpotFlagType = Preconditions.checkNotNull(hotSpotFlagType, "hotSpotFlagType may not be null.");
formatter = Formatters.BOOLEAN_FORMATTER;
floorValue = 0L;
ceilingValue = 1L;
stepSize = 1L;
dataSize = DataSize.NONE;
valueSeparator = ValueSeparator.NONE;
acceptableValueRange = Range.closed(0L, 1L);
}
/**
* Construct a new integer flag.
*
* @param name The name of the flag.
* @param hotSpotFlagType The type of the flag.
* @param minimum The minimum value.
* @param maximum The maximum value.
* @param stepSize The increment between values.
*/
JvmFlag(final String name, final HotSpotFlagType hotSpotFlagType, final Long minimum,
final Long maximum, final Long stepSize, final DataSize dataSize,
final ValueSeparator valueSeparator) {
this.name = Preconditions.checkNotNull(name, "name may not be null.");
this.hotSpotFlagType = Preconditions.checkNotNull(hotSpotFlagType, "hotSpotFlagType may not be null.");
floorValue = Preconditions.checkNotNull(minimum, "minimum may not be null.");
ceilingValue = Preconditions.checkNotNull(maximum, "maximum may not be null.");
this.stepSize = Preconditions.checkNotNull(stepSize, "stepSize may not be null.");
this.dataSize = Preconditions.checkNotNull(dataSize, "dataSize may not be null.");
this.valueSeparator = Preconditions.checkNotNull(valueSeparator, "valueSeparator may not be null.");
formatter = Formatters.INTEGER_FORMATTER;
acceptableValueRange = Range.closed(minimum, maximum);
}
String getName() {
return name;
}
HotSpotFlagType getHotSpotFlagType() {
return hotSpotFlagType;
}
Formatter getFormatter() {
return formatter;
}
public long getMinimum() {
return floorValue;
}
public long getMaximum() {
return ceilingValue;
}
public long getStepSize() {
return stepSize;
}
ValueSeparator getValueSeparator() {
return valueSeparator;
}
DataSize getDataSize() {
return dataSize;
}
Range<Long> getAcceptableValueRange() {
return acceptableValueRange;
}
/**
* Provide a representation of this flag with value as a String.
*
* @param value The value that should be represented in string form.
* @return The String representation.
*/
public String asArgumentString(final Long value) {
return getFormatter().asArgumentString(this, value);
}
/**
* Provide a representation of along with argument values as String.
*
* @return The String representation.
*/
public String asRegularExpressionString() {
return getFormatter().asRegularExpressionString(this);
}
/**
* Provide a representation of the allowed values as String.
*
* @return The String representation.
*/
public String asAcceptableValuesString() {
return getFormatter().asAcceptableValuesString(this);
}
/**
* Validate this flag with the proposed value.
*
* @param proposedValue The proposed value to be checked.
* @throws IllegalArgumentException In case of a bad argument.
*/
public void validate(final Long proposedValue) throws IllegalArgumentException {
getFormatter().validate(this, proposedValue);
}
/**
* Returns the GC mode {@link JvmFlag} instances.
*
* @return List of GC modes.
*/
public static ImmutableSortedSet<JvmFlag> getGcModeArguments() {
return GC_MODE_FLAGS;
}
/**
* Returns the GC mode command-line argument for the given GC mode.
*/
public static JvmFlag getGcModeArgument(final GcMode gcMode) {
Preconditions.checkNotNull(gcMode, "gcMode should not be null.");
switch (gcMode) {
case CMS:
return USE_CONC_MARK_SWEEP_GC;
case PARALLEL:
return USE_PARALLEL_GC;
case PARALLEL_OLD:
return USE_PARALLEL_OLD_GC;
case SERIAL:
return USE_SERIAL_GC;
default:
throw new IllegalArgumentException("Invalid GC mode: " + gcMode);
}
}
public static JvmFlag getGcModeArgument(final GroningenConfigProto.ProgramConfiguration.JvmSearchSpace.GcMode mode) {
Preconditions.checkNotNull(mode, "mode should not be null.");
// initialize the enum mappings
switch (mode) {
case USE_CONC_MARK_SWEEP:
return USE_CONC_MARK_SWEEP_GC;
case USE_PARALLEL:
return USE_PARALLEL_GC;
case USE_PARALLEL_OLD:
return USE_PARALLEL_OLD_GC;
case USE_SERIAL:
return USE_SERIAL_GC;
default:
throw new IllegalArgumentException("Invalid GC mode: " + mode);
}
}
}