Skip to content

Commit c8f0450

Browse files
author
Zhengyu Gu
committed
Implementation of GarbageCollection event
1 parent d2b0513 commit c8f0450

File tree

18 files changed

+462
-38
lines changed

18 files changed

+462
-38
lines changed

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ private boolean collectImpl(GCCause cause, long requestingNanoTime, boolean forc
209209

210210
NoAllocationVerifier nav = noAllocationVerifier.open();
211211
try {
212-
long startTicks = JfrGCEventSupport.startGCPhasePause();
212+
long startTicks = JfrGCEventSupport.getTicks();
213213
try {
214214
outOfMemory = doCollectImpl(cause, requestingNanoTime, forceFullGC, false);
215215
if (outOfMemory) {
@@ -223,7 +223,7 @@ private boolean collectImpl(GCCause cause, long requestingNanoTime, boolean forc
223223
}
224224
}
225225
} finally {
226-
JfrGCEventSupport.emitGCPhasePauseEvent(getCollectionEpoch(), cause.getName(), startTicks);
226+
JfrGCEventSupport.emitGarbageCollectionEvent(getCollectionEpoch(), cause, startTicks);
227227
}
228228
} finally {
229229
nav.close();
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
package com.oracle.svm.core.genscavenge;
27+
28+
import com.oracle.svm.core.heap.GCName;
29+
import com.oracle.svm.core.SubstrateOptions;
30+
31+
final class GenScavengeGCName extends GCName {
32+
public static final GCName GenScavenge;
33+
34+
static {
35+
if (SubstrateOptions.UseEpsilonGC.getValue()) {
36+
GenScavenge = new GenScavengeGCName("epsilon");
37+
} else {
38+
assert SubstrateOptions.UseSerialGC.getValue();
39+
GenScavenge = new GenScavengeGCName("serial");
40+
}
41+
}
42+
43+
private GenScavengeGCName(String name) {
44+
super(name);
45+
}
46+
}

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/JfrGCEventSupport.java

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.graalvm.word.UnsignedWord;
3131

3232
import com.oracle.svm.core.annotate.Uninterruptible;
33+
import com.oracle.svm.core.heap.GCCause;
3334
import com.oracle.svm.core.jfr.JfrBuffer;
3435
import com.oracle.svm.core.jfr.JfrEvent;
3536
import com.oracle.svm.core.jfr.JfrNativeEventWriter;
@@ -44,6 +45,13 @@ class JfrGCEventSupport {
4445
private static final int MAX_PHASE_LEVEL = 4;
4546
private static int currentPhase;
4647

48+
public static long getTicks() {
49+
if (!HasJfrSupport.get()) {
50+
return 0;
51+
}
52+
return JfrTicks.elapsedTicks();
53+
}
54+
4755
public static long startGCPhasePause() {
4856
if (!HasJfrSupport.get()) {
4957
return 0;
@@ -52,6 +60,31 @@ public static long startGCPhasePause() {
5260
return JfrTicks.elapsedTicks();
5361
}
5462

63+
@Uninterruptible(reason = "Accesses a JFR buffer.")
64+
public static void emitGarbageCollectionEvent(UnsignedWord gcEpoch, GCCause cause, long start) {
65+
if (!HasJfrSupport.get()) {
66+
return;
67+
}
68+
69+
long end = JfrTicks.elapsedTicks();
70+
long pauseTime = end - start;
71+
if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(JfrEvent.GarbageCollection)) {
72+
JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class);
73+
JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data);
74+
75+
JfrNativeEventWriter.beginEventWrite(data, false);
76+
JfrNativeEventWriter.putLong(data, JfrEvent.GarbageCollection.getId());
77+
JfrNativeEventWriter.putLong(data, start);
78+
JfrNativeEventWriter.putLong(data, pauseTime);
79+
JfrNativeEventWriter.putLong(data, gcEpoch.rawValue());
80+
JfrNativeEventWriter.putLong(data, GenScavengeGCName.GenScavenge.getId());
81+
JfrNativeEventWriter.putLong(data, cause.getId());
82+
JfrNativeEventWriter.putLong(data, pauseTime); // sum of pause
83+
JfrNativeEventWriter.putLong(data, pauseTime); // longest pause
84+
JfrNativeEventWriter.endEventWrite(data, false);
85+
}
86+
}
87+
5588
@Uninterruptible(reason = "Accesses a JFR buffer.")
5689
public static void emitGCPhasePauseEvent(UnsignedWord gcEpoch, String name, long startTicks) {
5790
if (!HasJfrSupport.get()) {
@@ -62,9 +95,8 @@ public static void emitGCPhasePauseEvent(UnsignedWord gcEpoch, String name, long
6295
JfrEvent event = getGCPhasePauseEvent(level);
6396
if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(event)) {
6497
long end = JfrTicks.elapsedTicks();
65-
JfrBuffer buffer = ((JfrThreadLocal) SubstrateJVM.getThreadLocal()).getNativeBuffer();
6698
JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class);
67-
JfrNativeEventWriterDataAccess.initialize(data, buffer);
99+
JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data);
68100

69101
JfrNativeEventWriter.beginEventWrite(data, false);
70102
JfrNativeEventWriter.putLong(data, event.getId());

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCCause.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -82,6 +82,10 @@ public static GCCause fromId(int causeId) {
8282
return GCCauses[causeId];
8383
}
8484

85+
public static GCCause[] getGCCauses() {
86+
return GCCauses;
87+
}
88+
8589
@Platforms(Platform.HOSTED_ONLY.class)
8690
public static void cacheReverseMapping() {
8791
GCCauses = HostedGCCauseList.toArray(new GCCause[HostedGCCauseList.size()]);
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
package com.oracle.svm.core.heap;
27+
28+
import java.util.ArrayList;
29+
import org.graalvm.nativeimage.Platform;
30+
import org.graalvm.nativeimage.Platforms;
31+
import org.graalvm.nativeimage.hosted.Feature;
32+
33+
import com.oracle.svm.core.annotate.AutomaticFeature;
34+
import com.oracle.svm.core.annotate.Uninterruptible;
35+
import com.oracle.svm.core.annotate.UnknownObjectField;
36+
/**
37+
* This class holds supported garbage collector names.
38+
*/
39+
public class GCName {
40+
@Platforms(Platform.HOSTED_ONLY.class) private static final ArrayList<GCName> HostedGCNameList = new ArrayList<>();
41+
42+
@UnknownObjectField(types = {GCName[].class}) protected static GCName[] GCNames;
43+
44+
private final int id;
45+
private final String name;
46+
47+
@Platforms(Platform.HOSTED_ONLY.class)
48+
protected GCName(String name) {
49+
this.name = name;
50+
this.id = addGCNameMapping();
51+
}
52+
53+
@Platforms(Platform.HOSTED_ONLY.class)
54+
private int addGCNameMapping() {
55+
synchronized (HostedGCNameList) {
56+
int newId = HostedGCNameList.size();
57+
HostedGCNameList.add(newId, this);
58+
return newId;
59+
}
60+
}
61+
62+
public String getName() {
63+
return name;
64+
}
65+
66+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
67+
public int getId() {
68+
return id;
69+
}
70+
71+
public static GCName[] getGCNames() {
72+
return GCNames;
73+
}
74+
75+
@Platforms(Platform.HOSTED_ONLY.class)
76+
public static void cacheReverseMapping() {
77+
GCNames = HostedGCNameList.toArray(new GCName[HostedGCNameList.size()]);
78+
}
79+
}
80+
81+
@AutomaticFeature
82+
class GCNameFeature implements Feature {
83+
@Override
84+
public void beforeCompilation(BeforeCompilationAccess access) {
85+
GCName.cacheReverseMapping();
86+
access.registerAsImmutable(GCName.GCNames);
87+
}
88+
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public enum JfrEvent {
4545
PhysicalMemory("jdk.PhysicalMemory"),
4646
ExecutionSample("jdk.ExecutionSample"),
4747
NativeMethodSample("jdk.NativeMethodSample"),
48+
GarbageCollection("jdk.GarbageCollection"),
4849
GCPhasePauseEvent("jdk.GCPhasePause"),
4950
GCPhasePauseLevel1Event("jdk.GCPhasePauseLevel1"),
5051
GCPhasePauseLevel2Event("jdk.GCPhasePauseLevel2"),

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrType.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,9 @@ public enum JfrType {
3939
Symbol("jdk.types.Symbol"),
4040
Module("jdk.types.Module"),
4141
Package("jdk.types.Package"),
42-
FrameType("jdk.types.FrameType");
42+
FrameType("jdk.types.FrameType"),
43+
GCCause("jdk.types.GCCause"),
44+
GCName("jdk.types.GCName");
4345

4446
private final long id;
4547

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrTypeRepository.java

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,8 @@
3535

3636
import com.oracle.svm.core.SubstrateUtil;
3737
import com.oracle.svm.core.annotate.Uninterruptible;
38+
import com.oracle.svm.core.heap.GCCause;
39+
import com.oracle.svm.core.heap.GCName;
3840
import com.oracle.svm.core.heap.Heap;
3941
import com.oracle.svm.core.jfr.traceid.JfrTraceId;
4042

@@ -62,6 +64,8 @@ public int write(JfrChunkWriter writer) {
6264
count += writePackages(writer, typeInfo);
6365
count += writeModules(writer, typeInfo);
6466
count += writeClassLoaders(writer, typeInfo);
67+
count += writeGCCauses(writer);
68+
count += writeGCNames(writer);
6569
return count;
6670
}
6771

@@ -186,6 +190,42 @@ private static int writeClassLoaders(JfrChunkWriter writer, TypeInfo typeInfo) {
186190
return NON_EMPTY;
187191
}
188192

193+
private static int writeGCCauses(JfrChunkWriter writer) {
194+
// GCCauses has null entries
195+
GCCause[] causes = GCCause.getGCCauses();
196+
int nonNullItems = 0;
197+
for (int index = 0; index < causes.length; index++) {
198+
if (causes[index] != null) {
199+
nonNullItems++;
200+
}
201+
}
202+
203+
assert nonNullItems > 0;
204+
205+
writer.writeCompressedLong(JfrType.GCCause.getId());
206+
writer.writeCompressedLong(nonNullItems);
207+
for (GCCause cause : causes) {
208+
if (cause != null) {
209+
writer.writeCompressedLong(cause.getId());
210+
writer.writeString(cause.getName());
211+
}
212+
}
213+
return NON_EMPTY;
214+
}
215+
216+
private static int writeGCNames(JfrChunkWriter writer) {
217+
GCName[] gcNames = GCName.getGCNames();
218+
assert gcNames != null && gcNames.length > 0;
219+
220+
writer.writeCompressedLong(JfrType.GCName.getId());
221+
writer.writeCompressedLong(gcNames.length);
222+
for (GCName name : gcNames) {
223+
writer.writeCompressedLong(name.getId());
224+
writer.writeString(name.getName());
225+
}
226+
return NON_EMPTY;
227+
}
228+
189229
private static void writeClassLoader(JfrChunkWriter writer, ClassLoader cl, long id) {
190230
JfrSymbolRepository symbolRepo = SubstrateJVM.getSymbolRepository();
191231
writer.writeCompressedLong(id);

0 commit comments

Comments
 (0)