70
70
* and another thread allocates nothing. Between GC 23 and GC 24 the allocation behaviour of these
71
71
* two threads switches. The allocation average and the TLAB size adapt to the new allocation
72
72
* behavior.
73
- *
73
+ *
74
74
* <pre>
75
75
* +-----+---------------------------------------++---------------------------------------+
76
76
* | #GC | Thread 1 || Thread 2 |
87
87
* | 29 | 0B | 270,44kB | 5,41kB || 3,55MB | 3,28MB | 67,14kB |
88
88
* +-----+--------------+------------+-----------++--------------+------------+-----------+
89
89
* </pre>
90
- *
90
+ * <p>
91
91
* A thread allocating a very large amount of memory will also have a high
92
92
* {@link #allocatedBytesAvg}. If such a thread later changes its allocation behaviour and only
93
93
* allocates a small amount of memory the {@link #allocatedBytesAvg} starts decreasing with the next
@@ -109,25 +109,23 @@ public class TlabSupport {
109
109
@ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-23-ga/src/hotspot/share/gc/shared/tlab_globals.hpp#L82-L85" )//
110
110
private static final long TLAB_WASTE_INCREMENT = 4 ;
111
111
112
- // The desired size of the TLAB, including the reserve for filling the unused memory.
112
+ /* The desired size of the TLAB, including the reserve for filling the unused memory. */
113
113
private static final FastThreadLocalWord <UnsignedWord > desiredSize = FastThreadLocalFactory .createWord ("TlabSupport.desiredSize" );
114
-
115
114
private static final FastThreadLocalWord <UnsignedWord > tlabAllocatedAlignedBytesBeforeLastGC = FastThreadLocalFactory .createWord ("TlabSupport.tlabAllocatedAlignedBytesBeforeLastGC" );
116
-
117
115
private static final FastThreadLocalInt numberOfRefills = FastThreadLocalFactory .createInt ("TlabSupport.numberOfRefills" );
118
116
private static final FastThreadLocalInt refillWaste = FastThreadLocalFactory .createInt ("TlabSupport.refillWaste" );
119
117
private static final FastThreadLocalInt gcWaste = FastThreadLocalFactory .createInt ("TlabSupport.gcWaste" );
120
118
121
- // Average of allocated bytes in TLABs of this thread.
119
+ /* Average of allocated bytes in TLABs of this thread. */
122
120
private static final FastThreadLocalBytes <AdaptiveWeightedAverageStruct .Data > allocatedBytesAvg = FastThreadLocalFactory
123
121
.createBytes (() -> SizeOf .get (AdaptiveWeightedAverageStruct .Data .class ), "TlabSupport.allocatedBytesAvg" );
124
122
125
- // Hold onto the TLAB if availableTlabMemory() is larger than this.
123
+ /* Hold onto the TLAB if availableTlabMemory() is larger than this. */
126
124
private static final FastThreadLocalWord <UnsignedWord > refillWasteLimit = FastThreadLocalFactory .createWord ("TlabSupport.refillWasteLimit" );
127
125
128
126
private static final FastThreadLocalInt slowAllocations = FastThreadLocalFactory .createInt ("TlabSupport.slowAllocations" );
129
127
130
- // Expected number of refills between GCs.
128
+ /* Expected number of refills between GCs. */
131
129
private static UnsignedWord targetRefills = Word .unsigned (1 );
132
130
133
131
private static boolean initialized ;
@@ -160,9 +158,11 @@ public static void initialize(IsolateThread thread) {
160
158
resetStatistics (thread );
161
159
}
162
160
161
+ @ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/runtime/thread.cpp#L168-L174" )
163
162
@ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-23-ga/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp#L183-L195" )
164
163
@ Uninterruptible (reason = "Accesses TLAB" )
165
164
static void fillTlab (Pointer start , Pointer top , WordPointer newSize ) {
165
+ /* Fill the TLAB. */
166
166
numberOfRefills .set (numberOfRefills .get () + 1 );
167
167
168
168
Pointer hardEnd = start .add (newSize .read ());
@@ -172,39 +172,38 @@ static void fillTlab(Pointer start, Pointer top, WordPointer newSize) {
172
172
173
173
initialize (getTlab (), start , top , end );
174
174
175
- // Reset amount of internal fragmentation
175
+ /* Reset amount of internal fragmentation. */
176
176
refillWasteLimit .set (initialRefillWasteLimit ());
177
177
}
178
178
179
179
@ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp#L143-L145" )
180
180
@ Uninterruptible (reason = "Accesses TLAB" )
181
- static void retireTlabBeforeAllocation () {
181
+ static void recordRefillWaste () {
182
182
long availableTlabMemory = availableTlabMemory (getTlab ()).rawValue ();
183
183
refillWaste .set (refillWaste .get () + UninterruptibleUtils .NumUtil .safeToInt (availableTlabMemory ));
184
- retireCurrentTlab (CurrentIsolate .getCurrentThread (), false );
185
184
}
186
185
186
+ @ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/runtime/thread.cpp#L157-L166" )
187
187
@ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp#L131-L141" )
188
188
@ Uninterruptible (reason = "Accesses TLAB" )
189
- private static void retireCurrentTlab (IsolateThread thread , boolean calculateStats ) {
189
+ static void retireTlab (IsolateThread thread , boolean calculateStats ) {
190
+ /* Sampling and serviceability support. */
190
191
ThreadLocalAllocation .Descriptor tlab = getTlab (thread );
191
-
192
192
if (tlab .getAllocationEnd (TLAB_END_IDENTITY ).isNonNull ()) {
193
- assert checkInvariants (tlab );
194
-
195
- UnsignedWord usedTlabSize = getUsedTlabSize (tlab );
196
- allocatedAlignedBytes .set (thread , allocatedAlignedBytes .get (thread ).add (usedTlabSize ));
197
- insertFiller (tlab );
198
- initialize (tlab , Word .nullPointer (), Word .nullPointer (), Word .nullPointer ());
193
+ UnsignedWord usedBytes = getUsedTlabSize (tlab );
194
+ allocatedAlignedBytes .set (thread , allocatedAlignedBytes .get (thread ).add (usedBytes ));
199
195
}
200
196
201
- /*
202
- * Collect statistics after the TLAB has been retired. Otherwise, the current TLAB is
203
- * excluded from the statistics.
204
- */
197
+ /* Retire the TLAB. */
205
198
if (calculateStats ) {
206
199
accumulateAndResetStatistics (thread );
207
200
}
201
+
202
+ if (tlab .getAllocationEnd (TLAB_END_IDENTITY ).isNonNull ()) {
203
+ assert checkInvariants (tlab );
204
+ insertFiller (tlab );
205
+ initialize (tlab , Word .nullPointer (), Word .nullPointer (), Word .nullPointer ());
206
+ }
208
207
}
209
208
210
209
@ Uninterruptible (reason = "Accesses TLAB" )
@@ -238,7 +237,7 @@ private static boolean checkInvariants(Descriptor tlab) {
238
237
@ Uninterruptible (reason = "Accesses TLAB" )
239
238
static void suspendAllocationInCurrentThread () {
240
239
/* The statistics for this thread will be updated later. */
241
- retireCurrentTlab (CurrentIsolate .getCurrentThread (), false );
240
+ retireTlab (CurrentIsolate .getCurrentThread (), false );
242
241
}
243
242
244
243
@ Uninterruptible (reason = CALLED_FROM_UNINTERRUPTIBLE_CODE , mayBeInlined = true )
@@ -268,7 +267,7 @@ static void disableAndFlushForThread(IsolateThread vmThread) {
268
267
private static void retireTlabToEden (IsolateThread thread ) {
269
268
VMThreads .guaranteeOwnsThreadMutex ("Otherwise, we wouldn't be allowed to access the space." , true );
270
269
271
- retireCurrentTlab (thread , true );
270
+ retireTlab (thread , true );
272
271
273
272
Descriptor tlab = getTlab (thread );
274
273
UnalignedHeapChunk .UnalignedHeader unalignedChunk = tlab .getUnalignedChunk ();
@@ -436,15 +435,16 @@ static UnsignedWord maxSize() {
436
435
@ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-23-ga/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp#L76-L117" )
437
436
@ Uninterruptible (reason = CALLED_FROM_UNINTERRUPTIBLE_CODE , mayBeInlined = true )
438
437
private static void accumulateAndResetStatistics (IsolateThread thread ) {
439
- gcWaste .set (thread , gcWaste .get () + UninterruptibleUtils .NumUtil .safeToInt (availableTlabMemory (getTlab (thread )).rawValue ()));
438
+ UnsignedWord remaining = availableTlabMemory (getTlab ());
439
+ gcWaste .set (thread , gcWaste .get () + UnsignedUtils .safeToInt (remaining ));
440
+
440
441
UnsignedWord totalAlignedAllocated = ThreadLocalAllocation .getAlignedAllocatedBytes (thread );
441
442
UnsignedWord allocatedAlignedSinceLastGC = totalAlignedAllocated .subtract (tlabAllocatedAlignedBytesBeforeLastGC .get (thread ));
442
443
tlabAllocatedAlignedBytesBeforeLastGC .set (thread , totalAlignedAllocated );
443
444
444
445
AdaptiveWeightedAverageStruct .sample (allocatedBytesAvg .getAddress (thread ), allocatedAlignedSinceLastGC .rawValue ());
445
446
446
447
printStats (thread , allocatedAlignedSinceLastGC );
447
-
448
448
resetStatistics (thread );
449
449
}
450
450
0 commit comments