30
30
import java .util .regex .Matcher ;
31
31
import java .util .regex .Pattern ;
32
32
33
+ // This class allows us to parse system hugepage config from
34
+ // - a) the Operating System (the truth)
35
+ // - b) the JVM log (-Xlog:pagesize)
36
+ // This is used e.g. in TestHugePageDetection to determine if the JVM detects the correct settings from the OS.
33
37
class HugePageConfiguration {
34
38
35
- Set <Long > _staticHugePageSizes ;
36
- long _staticDefaultHugePageSize ;
39
+ public static class StaticHugePageConfig implements Comparable <StaticHugePageConfig > {
40
+ public long pageSize = -1 ;
41
+ public long nr_hugepages = -1 ;
42
+ public long nr_overcommit_hugepages = -1 ;
37
43
38
- enum THPMode {always , never , madvise , unknown }
44
+ @ Override
45
+ public int hashCode () {
46
+ return Objects .hash (pageSize );
47
+ }
48
+
49
+ @ Override
50
+ public String toString () {
51
+ return "StaticHugePageConfig{" +
52
+ "pageSize=" + pageSize +
53
+ ", nr_hugepages=" + nr_hugepages +
54
+ ", nr_overcommit_hugepages=" + nr_overcommit_hugepages +
55
+ '}' ;
56
+ }
57
+
58
+ @ Override
59
+ public int compareTo (StaticHugePageConfig o ) {
60
+ return (int ) (pageSize - o .pageSize );
61
+ }
62
+ }
63
+
64
+ Set <StaticHugePageConfig > _staticHugePageConfigurations ;
65
+ long _staticDefaultHugePageSize = -1 ;
66
+
67
+ enum THPMode {always , never , madvise }
39
68
THPMode _thpMode ;
40
69
long _thpPageSize ;
41
70
42
- public Set <Long > getStaticHugePageSizes () {
43
- return _staticHugePageSizes ;
71
+ public Set <StaticHugePageConfig > getStaticHugePageConfigurations () {
72
+ return _staticHugePageConfigurations ;
44
73
}
45
74
46
75
public long getStaticDefaultHugePageSize () {
@@ -55,8 +84,18 @@ public long getThpPageSize() {
55
84
return _thpPageSize ;
56
85
}
57
86
58
- public HugePageConfiguration (Set <Long > _staticHugePageSizes , long _staticDefaultHugePageSize , THPMode _thpMode , long _thpPageSize ) {
59
- this ._staticHugePageSizes = _staticHugePageSizes ;
87
+ // Returns true if the THP support is enabled
88
+ public boolean supportsTHP () {
89
+ return _thpMode == THPMode .always || _thpMode == THPMode .madvise ;
90
+ }
91
+
92
+ // Returns true if static huge pages are supported (whether or not we have configured the pools)
93
+ public boolean supportsStaticHugePages () {
94
+ return _staticDefaultHugePageSize > 0 && _staticHugePageConfigurations .size () > 0 ;
95
+ }
96
+
97
+ public HugePageConfiguration (Set <StaticHugePageConfig > _staticHugePageConfigurations , long _staticDefaultHugePageSize , THPMode _thpMode , long _thpPageSize ) {
98
+ this ._staticHugePageConfigurations = _staticHugePageConfigurations ;
60
99
this ._staticDefaultHugePageSize = _staticDefaultHugePageSize ;
61
100
this ._thpMode = _thpMode ;
62
101
this ._thpPageSize = _thpPageSize ;
@@ -65,7 +104,7 @@ public HugePageConfiguration(Set<Long> _staticHugePageSizes, long _staticDefault
65
104
@ Override
66
105
public String toString () {
67
106
return "Configuration{" +
68
- "_staticHugePageSizes =" + _staticHugePageSizes +
107
+ "_staticHugePageConfigurations =" + _staticHugePageConfigurations +
69
108
", _staticDefaultHugePageSize=" + _staticDefaultHugePageSize +
70
109
", _thpMode=" + _thpMode +
71
110
", _thpPageSize=" + _thpPageSize +
@@ -77,12 +116,8 @@ public boolean equals(Object o) {
77
116
if (this == o ) return true ;
78
117
if (o == null || getClass () != o .getClass ()) return false ;
79
118
HugePageConfiguration that = (HugePageConfiguration ) o ;
80
- return _staticDefaultHugePageSize == that ._staticDefaultHugePageSize && _thpPageSize == that ._thpPageSize && Objects .equals (_staticHugePageSizes , that ._staticHugePageSizes ) && _thpMode == that ._thpMode ;
81
- }
82
-
83
- @ Override
84
- public int hashCode () {
85
- return Objects .hash (_staticHugePageSizes , _staticDefaultHugePageSize , _thpMode , _thpPageSize );
119
+ return _staticDefaultHugePageSize == that ._staticDefaultHugePageSize && _thpPageSize == that ._thpPageSize &&
120
+ Objects .equals (_staticHugePageConfigurations , that ._staticHugePageConfigurations ) && _thpMode == that ._thpMode ;
86
121
}
87
122
88
123
private static long readDefaultHugePageSizeFromOS () {
@@ -102,25 +137,36 @@ private static long readDefaultHugePageSizeFromOS() {
102
137
return 0 ;
103
138
}
104
139
105
- private static Set <Long > readSupportedHugePagesFromOS () {
106
- TreeSet <Long > pagesizes = new TreeSet <>();
140
+ private static Set <StaticHugePageConfig > readSupportedHugePagesFromOS () throws IOException {
141
+ TreeSet <StaticHugePageConfig > hugePageConfigs = new TreeSet <>();
107
142
Pattern pat = Pattern .compile ("hugepages-(\\ d+)kB" );
108
143
File [] subdirs = new File ("/sys/kernel/mm/hugepages" ).listFiles ();
109
144
if (subdirs != null ) {
110
- for (File f : subdirs ) {
111
- String name = f .getName ();
145
+ for (File subdir : subdirs ) {
146
+ String name = subdir .getName ();
112
147
Matcher mat = pat .matcher (name );
113
148
if (mat .matches ()) {
114
- long pagesize = Long .parseLong (mat .group (1 )) * 1024 ;
115
- pagesizes .add (pagesize );
149
+ StaticHugePageConfig config = new StaticHugePageConfig ();
150
+ config .pageSize = Long .parseLong (mat .group (1 )) * 1024 ;
151
+ try (FileReader fr = new FileReader (subdir .getAbsolutePath () + "/nr_hugepages" );
152
+ BufferedReader reader = new BufferedReader (fr )) {
153
+ String s = reader .readLine ();
154
+ config .nr_hugepages = Long .parseLong (s );
155
+ }
156
+ try (FileReader fr = new FileReader (subdir .getAbsolutePath () + "/nr_overcommit_hugepages" );
157
+ BufferedReader reader = new BufferedReader (fr )) {
158
+ String s = reader .readLine ();
159
+ config .nr_overcommit_hugepages = Long .parseLong (s );
160
+ }
161
+ hugePageConfigs .add (config );
116
162
}
117
163
}
118
164
}
119
- return pagesizes ;
165
+ return hugePageConfigs ;
120
166
}
121
167
122
168
private static THPMode readTHPModeFromOS () {
123
- THPMode mode = THPMode .unknown ;
169
+ THPMode mode = THPMode .never ;
124
170
String file = "/sys/kernel/mm/transparent_hugepage/enabled" ;
125
171
try (FileReader fr = new FileReader (file );
126
172
BufferedReader reader = new BufferedReader (fr )) {
@@ -136,7 +182,8 @@ private static THPMode readTHPModeFromOS() {
136
182
}
137
183
} catch (IOException e ) {
138
184
System .out .println ("Failed to read " + file );
139
- mode = THPMode .unknown ;
185
+ // Happens when the kernel is not built to support THPs.
186
+ mode = THPMode .never ;
140
187
}
141
188
return mode ;
142
189
}
@@ -148,19 +195,19 @@ private static long readTHPPageSizeFromOS() {
148
195
BufferedReader reader = new BufferedReader (fr )) {
149
196
String s = reader .readLine ();
150
197
pagesize = Long .parseLong (s );
151
- } catch (IOException | NumberFormatException e ) { /* ignored */ }
198
+ } catch (IOException | NumberFormatException e ) { } // ignored
152
199
return pagesize ;
153
200
}
154
201
155
202
// Fill object with info read from proc file system
156
- public static HugePageConfiguration readFromOS () {
203
+ public static HugePageConfiguration readFromOS () throws IOException {
157
204
return new HugePageConfiguration (readSupportedHugePagesFromOS (),
158
205
readDefaultHugePageSizeFromOS (),
159
206
readTHPModeFromOS (),
160
207
readTHPPageSizeFromOS ());
161
208
}
162
209
163
- private static long parseSIUnit (String num , String unit ) {
210
+ public static long parseSIUnit (String num , String unit ) {
164
211
long n = Long .parseLong (num );
165
212
return switch (unit ) {
166
213
case "K" -> n * 1024 ;
@@ -180,7 +227,7 @@ public static HugePageConfiguration readFromJVMLog(OutputAnalyzer output) {
180
227
// [0.001s][info][pagesize] Transparent hugepage (THP) support:
181
228
// [0.001s][info][pagesize] THP mode: madvise
182
229
// [0.001s][info][pagesize] THP pagesize: 2M
183
- TreeSet <Long > hugepages = new TreeSet <>();
230
+ TreeSet <StaticHugePageConfig > staticHugePageConfigs = new TreeSet <>();
184
231
long defaultHugepageSize = 0 ;
185
232
THPMode thpMode = THPMode .never ;
186
233
long thpPageSize = 0 ;
@@ -192,7 +239,9 @@ public static HugePageConfiguration readFromJVMLog(OutputAnalyzer output) {
192
239
for (String s : lines ) {
193
240
Matcher mat = patternHugepageSize .matcher (s );
194
241
if (mat .matches ()) {
195
- hugepages .add (parseSIUnit (mat .group (1 ), mat .group (2 )));
242
+ StaticHugePageConfig config = new StaticHugePageConfig ();
243
+ config .pageSize = parseSIUnit (mat .group (1 ), mat .group (2 ));
244
+ staticHugePageConfigs .add (config );
196
245
continue ;
197
246
}
198
247
if (defaultHugepageSize == 0 ) {
@@ -215,7 +264,7 @@ public static HugePageConfiguration readFromJVMLog(OutputAnalyzer output) {
215
264
}
216
265
}
217
266
218
- return new HugePageConfiguration (hugepages , defaultHugepageSize , thpMode , thpPageSize );
267
+ return new HugePageConfiguration (staticHugePageConfigs , defaultHugepageSize , thpMode , thpPageSize );
219
268
}
220
269
221
270
}
0 commit comments