Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/runtime/Metaspace/elastic/MetaspaceTestContext.java
41155 views
1
2
import sun.hotspot.WhiteBox;
3
4
import java.util.ArrayList;
5
import java.util.HashSet;
6
import java.util.List;
7
8
public class MetaspaceTestContext {
9
10
long context;
11
12
final long commitLimit;
13
final long reserveLimit;
14
15
int numArenasCreated;
16
int numArenasDestroyed;
17
18
HashSet<MetaspaceTestArena> arenaList = new HashSet<>();
19
20
long allocatedWords;
21
long numAllocated;
22
long deallocatedWords;
23
long numDeallocated;
24
long allocationFailures;
25
26
public MetaspaceTestContext(long commitLimit, long reserveLimit) {
27
this.commitLimit = commitLimit;
28
this.reserveLimit = reserveLimit;
29
WhiteBox wb = WhiteBox.getWhiteBox();
30
context = wb.createMetaspaceTestContext(commitLimit, reserveLimit);
31
if (context == 0) {
32
throw new RuntimeException("Failed to create context");
33
}
34
}
35
36
// no limits
37
public MetaspaceTestContext() {
38
this(0, 0);
39
}
40
41
public void destroy() {
42
if (context != 0) {
43
WhiteBox wb = WhiteBox.getWhiteBox();
44
wb.destroyMetaspaceTestContext(context);
45
context = 0;
46
}
47
}
48
49
public void purge() {
50
if (context != 0) {
51
WhiteBox wb = WhiteBox.getWhiteBox();
52
wb.purgeMetaspaceTestContext(context);
53
}
54
}
55
56
public MetaspaceTestArena createArena(boolean is_micro, long ceiling) {
57
MetaspaceTestArena arena = null;
58
if (context != 0) {
59
WhiteBox wb = WhiteBox.getWhiteBox();
60
long arena0 = wb.createArenaInTestContext(context, is_micro);
61
if (arena0 == 0) {
62
throw new RuntimeException("Failed to create arena");
63
}
64
numArenasCreated++;
65
arena = new MetaspaceTestArena(arena0, ceiling);
66
arenaList.add(arena);
67
}
68
return arena;
69
}
70
71
public void destroyArena(MetaspaceTestArena a) {
72
if (context != 0) {
73
if (a.isLive()) {
74
WhiteBox wb = WhiteBox.getWhiteBox();
75
wb.destroyMetaspaceTestArena(a.arena);
76
numArenasDestroyed++;
77
}
78
arenaList.remove(a);
79
}
80
}
81
82
public long committedWords() {
83
long l = 0;
84
if (context != 0) {
85
WhiteBox wb = WhiteBox.getWhiteBox();
86
l = wb.getTotalCommittedWordsInMetaspaceTestContext(context);
87
}
88
return l;
89
}
90
91
public long usedWords() {
92
long l = 0;
93
if (context != 0) {
94
WhiteBox wb = WhiteBox.getWhiteBox();
95
l = wb.getTotalUsedWordsInMetaspaceTestContext(context);
96
}
97
return l;
98
}
99
100
public int numLiveArenas() {
101
return arenaList.size();
102
}
103
104
public void updateTotals() {
105
allocatedWords = deallocatedWords = numAllocated = numDeallocated = 0;
106
for (MetaspaceTestArena a : arenaList) {
107
allocatedWords += a.allocatedWords;
108
deallocatedWords += a.deallocatedWords;
109
numAllocated += a.numAllocated;
110
numDeallocated += a.numDeallocated;
111
allocationFailures += a.numAllocationFailures;
112
}
113
}
114
115
public void printToTTY() {
116
if (context != 0) {
117
WhiteBox wb = WhiteBox.getWhiteBox();
118
wb.printMetaspaceTestContext(context);
119
}
120
}
121
122
/**
123
* Given usage and some context information for current live arenas, do a heuristic about whether the
124
* Usage seems right for this case.
125
*/
126
public void checkStatistics() {
127
128
// Note:
129
// Estimating Used and Committed is fuzzy, and we only have limited information here
130
// (we know the current state, but not the history, which determines fragmentation and
131
// freelist occupancy).
132
//
133
// We do not want test which constantly generate false positives, so these checks are
134
// somewhat loose and only meant to check for clear outliers, e.g. leaks.
135
136
///// used /////
137
138
updateTotals();
139
140
long usageMeasured = usedWords();
141
long committedMeasured = committedWords();
142
143
if (usageMeasured > committedMeasured) {
144
throw new RuntimeException("Weirdness.");
145
}
146
147
if (deallocatedWords > allocatedWords) {
148
throw new RuntimeException("Weirdness.");
149
}
150
151
// If no arenas are alive, usage should be zero and committed too (in reclaiming mode)
152
if (numLiveArenas() == 0) {
153
if (usageMeasured > 0) {
154
throw new RuntimeException("Usage > 0, expected 0");
155
}
156
if (Settings.settings().doesReclaim()) {
157
if (committedMeasured > 0) {
158
throw new RuntimeException("Committed > 0, expected 0");
159
}
160
}
161
}
162
163
long expectedMinUsage = allocatedWords - deallocatedWords;
164
165
if (usageMeasured < expectedMinUsage) {
166
throw new RuntimeException("Usage too low: " + usageMeasured + " expected at least " + expectedMinUsage);
167
}
168
169
long expectedMaxUsage = allocatedWords;
170
171
// This is necessary a bit fuzzy, since Metaspace usage consists of:
172
// - whatever we allocated
173
// - deallocated blocks in fbl
174
// - remains of retired chunks in fbl
175
// - overhead per allocation (padding for alignment, possibly allocation guards)
176
177
// Overhead per allocation (see metaspaceArena.cpp, get_raw_allocation_word_size() )
178
// Any allocation is 3 words least
179
expectedMaxUsage += (numAllocated * 3);
180
if (Settings.settings().usesAllocationGuards) {
181
// Guards need space.
182
expectedMaxUsage += (numAllocated * 2);
183
// Also, they disable the fbl, so deallocated still counts as used.
184
expectedMaxUsage += deallocatedWords;
185
}
186
187
// Lets add a overhead per arena. Each arena carries a free block list containing
188
// deallocated/retired blocks. We do not know how much. In general, the free block list should not
189
// accumulate a lot of memory but be drained in the course of allocating memory from the arena.
190
long overheadPerArena = 1024 * 1024 * numLiveArenas();
191
expectedMaxUsage += overheadPerArena;
192
193
if (expectedMaxUsage < usageMeasured) {
194
throw new RuntimeException("Usage seems high: " + usageMeasured + " expected at most " + expectedMaxUsage);
195
}
196
197
///// Committed //////
198
199
if (committedMeasured < expectedMinUsage) {
200
throw new RuntimeException("Usage too low: " + usageMeasured + " expected at least " + expectedMinUsage);
201
}
202
203
// Max committed:
204
// This is difficult to estimate, so just a rough guess.
205
//
206
// Committed space depends on:
207
// 1) Usage (how much we allocated + overhead per allocation + free block list content)
208
// 2) free space in used chunks
209
// 3) committed chunks in freelist.
210
//
211
// Having only live usage numbers without history, (2) and (3) can only be roughly estimated. Since these
212
// are stress tests,
213
//
214
long expectedMaxCommitted = usageMeasured;
215
expectedMaxCommitted += Settings.rootChunkWordSize;
216
if (Settings.settings().doesReclaim()) {
217
expectedMaxCommitted *= 10.0;
218
} else {
219
expectedMaxCommitted *= 100.0;
220
}
221
222
if (committedMeasured > expectedMaxCommitted) {
223
throw new RuntimeException("Committed seems high: " + committedMeasured + " expected at most " + expectedMaxCommitted);
224
}
225
226
}
227
228
@java.lang.Override
229
public java.lang.String toString() {
230
return "MetaspaceTestContext{" +
231
"context=" + context +
232
", commitLimit=" + commitLimit +
233
", reserveLimit=" + reserveLimit +
234
", numArenasCreated=" + numArenasCreated +
235
", numArenasDestroyed=" + numArenasDestroyed +
236
", numLiveArenas=" + numLiveArenas() +
237
", allocatedWords=" + allocatedWords +
238
", numAllocated=" + numAllocated +
239
", deallocatedWords=" + deallocatedWords +
240
", numDeallocated=" + numDeallocated +
241
", allocationFailures=" + allocationFailures +
242
'}';
243
}
244
}
245
246