提交 42338688 编写于 作者: 卓昂 提交者: 云矅

[JFR] add support for opto object allocations sampling

Summary: add support for opto object allocations sampling

Test Plan: hotspot/test/jfr/event/objectsprofiling/TestOptoObjectAllocationsSampling.java

Reviewers: zhengxiaolinX, luchsh, sanhong

Issue: https://github.com/alibaba/dragonwell8/issues/64
上级 6292d0bc
/*
* Copyright (c) 2019 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
package jdk.jfr;
/**
* A constant class for JFR Event, contains the names of some events used by jdk.
*/
public class EventNames {
private final static String PREFIX = "com.oracle.jdk.";
public final static String OptoInstanceObjectAllocation = PREFIX + "OptoInstanceObjectAllocation";
public final static String OptoArrayObjectAllocation = PREFIX + "OptoArrayObjectAllocation";
}
...@@ -668,4 +668,7 @@ public final class Recording implements Closeable { ...@@ -668,4 +668,7 @@ public final class Recording implements Closeable {
internal.setSetting(id, value); internal.setSetting(id, value);
} }
public boolean isRecorderEnabled(String eventName) {
return internal.isRecorderEnabled(eventName);
}
} }
...@@ -100,4 +100,27 @@ public final class RecordedClass extends RecordedObject { ...@@ -100,4 +100,27 @@ public final class RecordedClass extends RecordedObject {
public long getId() { public long getId() {
return uniqueId; return uniqueId;
} }
/**
* Returns the object size for the class.
* <p>
* The object size for instance class is accurate. But for the array class, it
* is a magic code 0x1111baba. The array object size can not be determined statically
* from the JVM klass information because array object size is affected by
* actual element length.
*
* @return the object size (instance object), or magic code 0x1111baba (array object)
*/
public int getObjectSize() {
return getTyped("objectSize", Integer.class, -1);
}
/**
* Checks whether the class is for instance or array.
*
* @return true or false
*/
public boolean isArray() {
return getName().startsWith("[");
}
} }
...@@ -287,6 +287,20 @@ public final class JVM { ...@@ -287,6 +287,20 @@ public final class JVM {
*/ */
public native void setSampleThreads(boolean sampleThreads) throws IllegalStateException; public native void setSampleThreads(boolean sampleThreads) throws IllegalStateException;
/**
* Turn on/off objects allocations sampling.
*
* @param sampleAllocations true if object allocations should be sampled, false otherwise.
*/
public native void setSampleObjectAllocations(boolean sampleAllocations);
/**
* Set object allocations sampling interval.
*
* @param interval
*/
public native void setObjectAllocationsSamplingInterval(long interval) throws IllegalArgumentException;
/** /**
* Turn on/off compressed integers. * Turn on/off compressed integers.
* *
......
...@@ -49,6 +49,8 @@ public final class Options { ...@@ -49,6 +49,8 @@ public final class Options {
private static final boolean DEFAULT_SAMPLE_THREADS = true; private static final boolean DEFAULT_SAMPLE_THREADS = true;
private static final long DEFAULT_MAX_CHUNK_SIZE = 12 * 1024 * 1024; private static final long DEFAULT_MAX_CHUNK_SIZE = 12 * 1024 * 1024;
private static final SafePath DEFAULT_DUMP_PATH = SecuritySupport.USER_HOME; private static final SafePath DEFAULT_DUMP_PATH = SecuritySupport.USER_HOME;
private static final boolean DEFAULT_SAMPLE_OBJECT_ALLOCATIONS = false;
private static final long DEFAULT_OBJECT_ALLOCATIONS_SAMPLING_INTERVAL = 1024;
private static long memorySize; private static long memorySize;
private static long globalBufferSize; private static long globalBufferSize;
...@@ -58,6 +60,8 @@ public final class Options { ...@@ -58,6 +60,8 @@ public final class Options {
private static boolean sampleThreads; private static boolean sampleThreads;
private static long maxChunkSize; private static long maxChunkSize;
private static SafePath dumpPath; private static SafePath dumpPath;
private static boolean sampleObjectAllocations;
private static long objectAllocationsSamplingInterval;
static { static {
final long pageSize = Unsafe.getUnsafe().pageSize(); final long pageSize = Unsafe.getUnsafe().pageSize();
...@@ -139,6 +143,31 @@ public final class Options { ...@@ -139,6 +143,31 @@ public final class Options {
return sampleThreads; return sampleThreads;
} }
public static synchronized void setSampleObjectAllocations(Boolean sample) {
jvm.setSampleObjectAllocations(sample);
sampleObjectAllocations = sample;
}
public static synchronized boolean getSampleObjectAllocations() {
return sampleObjectAllocations;
}
/**
* Set interval of sampling object allocation events
* @param interval the number of newly created objects between two sampling
*/
public static synchronized void setObjectAllocationsSamplingInterval(Long interval) {
if (interval <= 0) {
throw new IllegalArgumentException("interval should be greater than 0");
}
jvm.setObjectAllocationsSamplingInterval(interval);
objectAllocationsSamplingInterval = interval;
}
public static synchronized long getObjectAllocationsSamplingInterval() {
return objectAllocationsSamplingInterval;
}
private static synchronized void reset() { private static synchronized void reset() {
setMaxChunkSize(DEFAULT_MAX_CHUNK_SIZE); setMaxChunkSize(DEFAULT_MAX_CHUNK_SIZE);
setMemorySize(DEFAULT_MEMORY_SIZE); setMemorySize(DEFAULT_MEMORY_SIZE);
...@@ -148,6 +177,8 @@ public final class Options { ...@@ -148,6 +177,8 @@ public final class Options {
setSampleThreads(DEFAULT_SAMPLE_THREADS); setSampleThreads(DEFAULT_SAMPLE_THREADS);
setStackDepth(DEFAULT_STACK_DEPTH); setStackDepth(DEFAULT_STACK_DEPTH);
setThreadBufferSize(DEFAULT_THREAD_BUFFER_SIZE); setThreadBufferSize(DEFAULT_THREAD_BUFFER_SIZE);
setSampleObjectAllocations(DEFAULT_SAMPLE_OBJECT_ALLOCATIONS);
setObjectAllocationsSamplingInterval(DEFAULT_OBJECT_ALLOCATIONS_SAMPLING_INTERVAL);
} }
static synchronized long getWaitInterval() { static synchronized long getWaitInterval() {
......
...@@ -47,6 +47,7 @@ import java.util.TimerTask; ...@@ -47,6 +47,7 @@ import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import jdk.jfr.Enabled; import jdk.jfr.Enabled;
import jdk.jfr.EventNames;
import jdk.jfr.EventType; import jdk.jfr.EventType;
import jdk.jfr.FlightRecorder; import jdk.jfr.FlightRecorder;
import jdk.jfr.FlightRecorderListener; import jdk.jfr.FlightRecorderListener;
...@@ -560,4 +561,8 @@ public final class PlatformRecorder { ...@@ -560,4 +561,8 @@ public final class PlatformRecorder {
internal.setInternalDuration(Duration.between(startTime, endTime)); internal.setInternalDuration(Duration.between(startTime, endTime));
return snapshot; return snapshot;
} }
public boolean isEnabled(String eventName) {
return MetadataRepository.getInstance().isEnabled(eventName);
}
} }
...@@ -693,4 +693,8 @@ public final class PlatformRecording implements AutoCloseable { ...@@ -693,4 +693,8 @@ public final class PlatformRecording implements AutoCloseable {
boolean shouldWriteMetadataEvent() { boolean shouldWriteMetadataEvent() {
return shuoldWriteActiveRecordingEvent; return shuoldWriteActiveRecordingEvent;
} }
public boolean isRecorderEnabled(String eventName) {
return recorder.isEnabled(eventName);
}
} }
...@@ -43,6 +43,7 @@ final class DCmdConfigure extends AbstractDCmd { ...@@ -43,6 +43,7 @@ final class DCmdConfigure extends AbstractDCmd {
/** /**
* Execute JFR.configure. * Execute JFR.configure.
* *
* @param onVMStart if cmd is invoked at the moment when vm is started
* @param repositoryPath the path * @param repositoryPath the path
* @param dumpPath path to dump to on fatal error (oom) * @param dumpPath path to dump to on fatal error (oom)
* @param stackDepth depth of stack traces * @param stackDepth depth of stack traces
...@@ -51,6 +52,8 @@ final class DCmdConfigure extends AbstractDCmd { ...@@ -51,6 +52,8 @@ final class DCmdConfigure extends AbstractDCmd {
* @param threadBufferSize size of thread buffer for events * @param threadBufferSize size of thread buffer for events
* @param maxChunkSize threshold at which a new chunk is created in the disk repository * @param maxChunkSize threshold at which a new chunk is created in the disk repository
* @param sampleThreads if thread sampling should be enabled * @param sampleThreads if thread sampling should be enabled
* @param sampleObjectAllocations if object allocations sampling should be enbaled
* @param objectAllocationsSamplingInterval interval of object allocations samplings
* *
* @return result * @return result
...@@ -59,6 +62,7 @@ final class DCmdConfigure extends AbstractDCmd { ...@@ -59,6 +62,7 @@ final class DCmdConfigure extends AbstractDCmd {
*/ */
public String execute public String execute
( (
Boolean onVMStart,
String repositoryPath, String repositoryPath,
String dumpPath, String dumpPath,
Integer stackDepth, Integer stackDepth,
...@@ -67,9 +71,18 @@ final class DCmdConfigure extends AbstractDCmd { ...@@ -67,9 +71,18 @@ final class DCmdConfigure extends AbstractDCmd {
Long threadBufferSize, Long threadBufferSize,
Long memorySize, Long memorySize,
Long maxChunkSize, Long maxChunkSize,
Boolean sampleThreads Boolean sampleThreads,
Boolean sampleObjectAllocations,
Long objectAllocationsSamplingInterval
) throws DCmdException { ) throws DCmdException {
// Check parameters correctness
if (!onVMStart) {
if (sampleObjectAllocations != null || objectAllocationsSamplingInterval != null) {
Logger.log(LogTag.JFR, LogLevel.ERROR, "Could not change sampleObjectAllocations and objectAllocationsSamplingInterval during application's running");
return getResult();
}
}
boolean updated = false; boolean updated = false;
if (repositoryPath != null) { if (repositoryPath != null) {
try { try {
...@@ -139,6 +152,20 @@ final class DCmdConfigure extends AbstractDCmd { ...@@ -139,6 +152,20 @@ final class DCmdConfigure extends AbstractDCmd {
updated = true; updated = true;
} }
if (objectAllocationsSamplingInterval != null) {
Options.setObjectAllocationsSamplingInterval(objectAllocationsSamplingInterval);
Logger.log(LogTag.JFR, LogLevel.INFO, "object allocations sampling interval set to " + objectAllocationsSamplingInterval);
printObjectAllocationsSamplingInterval();
updated = true;
}
if (sampleObjectAllocations != null) {
Options.setSampleObjectAllocations(sampleObjectAllocations);
Logger.log(LogTag.JFR, LogLevel.INFO, "Sample object allocations set to " + sampleObjectAllocations);
printSampleObjectAllocations();
updated = true;
}
if (!updated) { if (!updated) {
println("Current configuration:"); println("Current configuration:");
println(); println();
...@@ -150,6 +177,8 @@ final class DCmdConfigure extends AbstractDCmd { ...@@ -150,6 +177,8 @@ final class DCmdConfigure extends AbstractDCmd {
printMemorySize(); printMemorySize();
printMaxChunkSize(); printMaxChunkSize();
printSampleThreads(); printSampleThreads();
printSampleObjectAllocations();
printObjectAllocationsSamplingInterval();
} }
return getResult(); return getResult();
} }
...@@ -201,4 +230,12 @@ final class DCmdConfigure extends AbstractDCmd { ...@@ -201,4 +230,12 @@ final class DCmdConfigure extends AbstractDCmd {
printBytes(Options.getMaxChunkSize(), " "); printBytes(Options.getMaxChunkSize(), " ");
println(); println();
} }
private void printSampleObjectAllocations() {
println("Sample object allocations: " + Options.getSampleObjectAllocations());
}
private void printObjectAllocationsSamplingInterval() {
println("objects allocations sampling interval: " + Options.getObjectAllocationsSamplingInterval());
}
} }
...@@ -32,9 +32,11 @@ import java.time.Duration; ...@@ -32,9 +32,11 @@ import java.time.Duration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import jdk.jfr.EventNames;
import jdk.jfr.FlightRecorder; import jdk.jfr.FlightRecorder;
import jdk.jfr.Recording; import jdk.jfr.Recording;
import jdk.jfr.internal.JVM; import jdk.jfr.internal.JVM;
import jdk.jfr.internal.Options;
import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.jfr.internal.SecuritySupport.SafePath;
import jdk.jfr.internal.Type; import jdk.jfr.internal.Type;
import jdk.jfr.internal.Utils; import jdk.jfr.internal.Utils;
...@@ -86,6 +88,7 @@ final class DCmdStart extends AbstractDCmd { ...@@ -86,6 +88,7 @@ final class DCmdStart extends AbstractDCmd {
if (duration == null && Boolean.FALSE.equals(dumpOnExit) && path != null) { if (duration == null && Boolean.FALSE.equals(dumpOnExit) && path != null) {
throw new DCmdException("Filename can only be set for a time bound recording or if dumponexit=true. Set duration/dumponexit or omit filename."); throw new DCmdException("Filename can only be set for a time bound recording or if dumponexit=true. Set duration/dumponexit or omit filename.");
} }
if (dumpOnExit == null && path != null) { if (dumpOnExit == null && path != null) {
dumpOnExit = Boolean.TRUE; dumpOnExit = Boolean.TRUE;
} }
...@@ -100,7 +103,7 @@ final class DCmdStart extends AbstractDCmd { ...@@ -100,7 +103,7 @@ final class DCmdStart extends AbstractDCmd {
try { try {
s.putAll(JFC.createKnown(configName).getSettings()); s.putAll(JFC.createKnown(configName).getSettings());
} catch (IOException | ParseException e) { } catch (IOException | ParseException e) {
throw new DCmdException("Could not parse setting " + configurations[0], e); throw new DCmdException("Could not parse setting " + configName, e);
} }
} }
...@@ -136,6 +139,14 @@ final class DCmdStart extends AbstractDCmd { ...@@ -136,6 +139,14 @@ final class DCmdStart extends AbstractDCmd {
} }
recording.setSettings(s); recording.setSettings(s);
if (recording.isRecorderEnabled(EventNames.OptoInstanceObjectAllocation) ||
recording.isRecorderEnabled(EventNames.OptoArrayObjectAllocation)) {
if (!Options.getSampleObjectAllocations()) {
println("Please add -XX:FlightRecorderOptions=sampleobjectallocations=true in JVM options.");
return getResult();
}
}
if (path != null) { if (path != null) {
try { try {
recording.setDestination(Paths.get(path)); recording.setDestination(Paths.get(path));
......
...@@ -173,6 +173,8 @@ public class EventNames { ...@@ -173,6 +173,8 @@ public class EventNames {
public final static String CPUTimeStampCounter = PREFIX + "CPUTimeStampCounter";// "os.processor.cpu_tsc"; public final static String CPUTimeStampCounter = PREFIX + "CPUTimeStampCounter";// "os.processor.cpu_tsc";
public final static String ActiveRecording = PREFIX + "ActiveRecording";//"com.oracle.jdk.ActiveRecording" public final static String ActiveRecording = PREFIX + "ActiveRecording";//"com.oracle.jdk.ActiveRecording"
public final static String ActiveSetting = PREFIX + "ActiveSetting";//"com.oracle.jdk.ActiveSetting" public final static String ActiveSetting = PREFIX + "ActiveSetting";//"com.oracle.jdk.ActiveSetting"
public final static String OptoInstanceObjectAllocation = PREFIX + "OptoInstanceObjectAllocation"; //"com.oracle.jdk.OptoInstanceObjectAllocation"
public final static String OptoArrayObjectAllocation = PREFIX + "OptoArrayObjectAllocation"; //"com.oracle.jdk.OptoArrayObjectAllocation"
public static boolean isGcEvent(EventType et) { public static boolean isGcEvent(EventType et) {
return et.getCategoryNames().contains(GC_CATEGORY); return et.getCategoryNames().contains(GC_CATEGORY);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册