Skip to content

Commit dad28cf

Browse files
author
Zhengyu Gu
committed
Implementation of GarbageCollection event
1 parent 1377605 commit dad28cf

File tree

18 files changed

+455
-35
lines changed

18 files changed

+455
-35
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import com.oracle.svm.core.heap.ReferenceMapIndex;
7676
import com.oracle.svm.core.heap.RuntimeCodeCacheCleaner;
7777
import com.oracle.svm.core.jdk.RuntimeSupport;
78+
import com.oracle.svm.core.jfr.JfrTicks;
7879
import com.oracle.svm.core.log.Log;
7980
import com.oracle.svm.core.os.CommittedMemoryProvider;
8081
import com.oracle.svm.core.snippets.ImplicitExceptions;
@@ -209,7 +210,7 @@ private boolean collectImpl(GCCause cause, long requestingNanoTime, boolean forc
209210

210211
NoAllocationVerifier nav = noAllocationVerifier.open();
211212
try {
212-
long startTicks = JfrGCEventSupport.startGCPhasePause();
213+
long startTicks = JfrTicks.elapsedTicks();
213214
try {
214215
outOfMemory = doCollectImpl(cause, requestingNanoTime, forceFullGC, false);
215216
if (outOfMemory) {
@@ -223,7 +224,7 @@ private boolean collectImpl(GCCause cause, long requestingNanoTime, boolean forc
223224
}
224225
}
225226
} finally {
226-
JfrGCEventSupport.emitGCPhasePauseEvent(getCollectionEpoch(), cause.getName(), startTicks);
227+
JfrGCEventSupport.emitGarbageCollectionEvent(getCollectionEpoch(), GenScavengeGCName.GenScavenge, cause, startTicks);
227228
}
228229
} finally {
229230
nav.close();
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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+
30+
final class GenScavengeGCName extends GCName {
31+
public static final GCName GenScavenge = new GenScavengeGCName("GenScavenge");
32+
33+
private GenScavengeGCName(String name) {
34+
super(name);
35+
}
36+
}

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

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

3232
import com.oracle.svm.core.annotate.Uninterruptible;
33+
import com.oracle.svm.core.heap.GCCause;
34+
import com.oracle.svm.core.heap.GCName;
3335
import com.oracle.svm.core.jfr.JfrBuffer;
3436
import com.oracle.svm.core.jfr.JfrEvent;
3537
import com.oracle.svm.core.jfr.JfrNativeEventWriter;
@@ -52,6 +54,32 @@ public static long startGCPhasePause() {
5254
return JfrTicks.elapsedTicks();
5355
}
5456

57+
@Uninterruptible(reason = "Accesses a JFR buffer.")
58+
public static void emitGarbageCollectionEvent(UnsignedWord gcEpoch, GCName gcName, GCCause cause, long start) {
59+
if (!HasJfrSupport.get()) {
60+
return;
61+
}
62+
63+
long end = JfrTicks.elapsedTicks();
64+
long pauseTime = end - start;
65+
if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(JfrEvent.GarbageCollection)) {
66+
JfrBuffer buffer = ((JfrThreadLocal) SubstrateJVM.getThreadLocal()).getNativeBuffer();
67+
JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class);
68+
JfrNativeEventWriterDataAccess.initialize(data, buffer);
69+
70+
JfrNativeEventWriter.beginEventWrite(data, false);
71+
JfrNativeEventWriter.putLong(data, JfrEvent.GarbageCollection.getId());
72+
JfrNativeEventWriter.putLong(data, start);
73+
JfrNativeEventWriter.putLong(data, pauseTime);
74+
JfrNativeEventWriter.putLong(data, gcEpoch.rawValue());
75+
JfrNativeEventWriter.putLong(data, gcName.getId());
76+
JfrNativeEventWriter.putLong(data, cause.getId());
77+
JfrNativeEventWriter.putLong(data, pauseTime); // sum of pause
78+
JfrNativeEventWriter.putLong(data, pauseTime); // longest pause
79+
JfrNativeEventWriter.endEventWrite(data, false);
80+
}
81+
}
82+
5583
@Uninterruptible(reason = "Accesses a JFR buffer.")
5684
public static void emitGCPhasePauseEvent(UnsignedWord gcEpoch, String name, long startTicks) {
5785
if (!HasJfrSupport.get()) {

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: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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+
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+
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+
GCNames = HostedGCNameList.toArray(new GCName[HostedGCNameList.size()]);
59+
return newId;
60+
}
61+
}
62+
63+
public String getName() {
64+
return name;
65+
}
66+
67+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
68+
public int getId() {
69+
return id;
70+
}
71+
72+
public static GCName[] getGCNames() {
73+
return GCNames;
74+
}
75+
76+
@Platforms(Platform.HOSTED_ONLY.class)
77+
public static void cacheReverseMapping() {
78+
GCNames = HostedGCNameList.toArray(new GCName[HostedGCNameList.size()]);
79+
}
80+
}
81+
82+
@AutomaticFeature
83+
class GCNameFeature implements Feature {
84+
@Override
85+
public void beforeCompilation(BeforeCompilationAccess access) {
86+
GCName.cacheReverseMapping();
87+
access.registerAsImmutable(GCName.GCNames);
88+
}
89+
}

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: 45 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,46 @@ 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+
if (nonNullItems == 0) {
204+
return EMPTY;
205+
}
206+
207+
writer.writeCompressedLong(JfrType.GCCause.getId());
208+
writer.writeCompressedLong(nonNullItems);
209+
for (GCCause cause : causes) {
210+
if (cause != null) {
211+
writer.writeCompressedLong(cause.getId());
212+
writer.writeString(cause.getName());
213+
}
214+
}
215+
return NON_EMPTY;
216+
}
217+
218+
private static int writeGCNames(JfrChunkWriter writer) {
219+
GCName[] gcNames = GCName.getGCNames();
220+
if (gcNames == null) {
221+
return EMPTY;
222+
}
223+
224+
writer.writeCompressedLong(JfrType.GCName.getId());
225+
writer.writeCompressedLong(gcNames.length);
226+
for (GCName name : gcNames) {
227+
writer.writeCompressedLong(name.getId());
228+
writer.writeString(name.getName());
229+
}
230+
return NON_EMPTY;
231+
}
232+
189233
private static void writeClassLoader(JfrChunkWriter writer, ClassLoader cl, long id) {
190234
JfrSymbolRepository symbolRepo = SubstrateJVM.getSymbolRepository();
191235
writer.writeCompressedLong(id);

0 commit comments

Comments
 (0)