Skip to content

Commit d5c6158

Browse files
jaokimMarkus Grönlund
authored andcommitted
8338389: [JFR] Long strings should be added to the string pool
Reviewed-by: mgronlun
1 parent 2edf574 commit d5c6158

File tree

2 files changed

+119
-3
lines changed

2 files changed

+119
-3
lines changed

src/jdk.jfr/share/classes/jdk/jfr/internal/StringPool.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030

3131
public final class StringPool {
3232
public static final int MIN_LIMIT = 16;
33-
public static final int MAX_LIMIT = 128; /* 0 MAX means disabled */
34-
33+
public static final int MAX_LIMIT = 131072; /* 0 MAX means disabled */
34+
private static final int PRECACHE_THRESHOLD = 128;
3535
private static final long DO_NOT_POOL = -1;
3636
/* max size */
3737
private static final int MAX_SIZE = 32 * 1024;
@@ -131,7 +131,7 @@ public static long addString(String s, boolean pinVirtualThread) {
131131
if (lsid != null) {
132132
return ensureCurrentGeneration(s, lsid, pinVirtualThread);
133133
}
134-
if (!preCache(s)) {
134+
if (s.length() <= PRECACHE_THRESHOLD && !preCache(s)) {
135135
/* we should not pool this string */
136136
return DO_NOT_POOL;
137137
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
package jdk.jfr.jvm;
25+
26+
import java.nio.file.Files;
27+
import java.nio.file.Path;
28+
import java.nio.file.Paths;
29+
30+
import jdk.jfr.Event;
31+
import jdk.jfr.Recording;
32+
import jdk.jfr.consumer.RecordingFile;
33+
import jdk.test.lib.Asserts;
34+
import jdk.test.lib.jfr.EventNames;
35+
36+
/**
37+
* @test
38+
* @summary Verify that duplicate longer strings doesn't take up unneccessary space
39+
* @key jfr
40+
* @requires vm.hasJFR
41+
* @library /test/lib
42+
* @run main/othervm jdk.jfr.jvm.TestLongStringsInPool
43+
*/
44+
public class TestLongStringsInPool {
45+
private static class StringEvent extends Event {
46+
String message;
47+
}
48+
49+
public static void main(String[] args) throws Exception {
50+
// Create two recordings; first has only one large
51+
// string, second has several occurences of the same
52+
// string. With long strings (>128 chars) being pooled,
53+
// the two recording should be roughly the same size.
54+
final int numEvents = 10;
55+
final String longString = generateString();
56+
final int strLen = longString.length();
57+
final StringEvent event = new StringEvent();
58+
event.message = longString;
59+
60+
Recording firstRec = new Recording();
61+
firstRec.start();
62+
// commit events with empty message (both recordings
63+
// will have the same number of events)
64+
for (int i = 0; i < numEvents - 1; i++) {
65+
event.message = "";
66+
event.commit();
67+
}
68+
// commit 1 event with a long string
69+
event.message = longString;
70+
event.commit();
71+
72+
firstRec.stop();
73+
Path rec1 = Paths.get(".", "rec1.jfr");
74+
firstRec.dump(rec1);
75+
firstRec.close();
76+
77+
78+
Recording secondRec = new Recording();
79+
secondRec.start();
80+
// commit events with the same long string
81+
for (int i = 0; i < numEvents - 1; i++) {
82+
event.message = longString;
83+
event.commit();
84+
}
85+
// commit 1 event with a long string
86+
event.message = longString;
87+
event.commit();
88+
89+
secondRec.stop();
90+
Path rec2 = Paths.get(".", "rec2.jfr");
91+
secondRec.dump(rec2);
92+
secondRec.close();
93+
94+
// the files aren't exactly the same size, but rec2 should
95+
// not take up space for all strings if they're pooled correctly
96+
long maxAllowedDiff = (numEvents - 1) * strLen;
97+
long diff = Math.abs(Files.size(rec2) - Files.size(rec1));
98+
99+
Asserts.assertTrue(diff <= maxAllowedDiff, "Size difference between recordings is too large: "+ diff +" > " + maxAllowedDiff);
100+
Asserts.assertFalse(RecordingFile.readAllEvents(rec1).isEmpty(), "No events found in recording 1");
101+
Asserts.assertFalse(RecordingFile.readAllEvents(rec2).isEmpty(), "No events found in recording 2");
102+
Asserts.assertEquals(RecordingFile.readAllEvents(rec1).size(), RecordingFile.readAllEvents(rec2).size(), "The recordings don't have the same number of events");
103+
}
104+
105+
/**
106+
* Generate a string of 256 chars length.
107+
* @return
108+
*/
109+
private static String generateString() {
110+
final StringBuilder builder = new StringBuilder();
111+
for (int i = 0; i < 32; i++) {
112+
builder.append("abcdefgh");
113+
}
114+
return builder.toString();
115+
}
116+
}

0 commit comments

Comments
 (0)