34 // Thread-Local Edens support
35
36 // static member initialization
37 size_t ThreadLocalAllocBuffer::_max_size = 0;
38 unsigned ThreadLocalAllocBuffer::_target_refills = 0;
39 GlobalTLABStats* ThreadLocalAllocBuffer::_global_stats = NULL;
40
41 void ThreadLocalAllocBuffer::clear_before_allocation() {
42 _slow_refill_waste += (unsigned)remaining();
43 make_parsable(true); // also retire the TLAB
44 }
45
46 void ThreadLocalAllocBuffer::accumulate_statistics_before_gc() {
47 global_stats()->initialize();
48
49 for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
50 thread->tlab().accumulate_statistics();
51 thread->tlab().initialize_statistics();
52 }
53
54 // Publish new stats if some allocation occurred.
55 if (global_stats()->allocation() != 0) {
56 global_stats()->publish();
57 if (PrintTLAB) {
58 global_stats()->print();
59 }
60 }
61 }
62
63 void ThreadLocalAllocBuffer::accumulate_statistics() {
64 Thread* thread = myThread();
65 size_t capacity = Universe::heap()->tlab_capacity(thread);
66 size_t used = Universe::heap()->tlab_used(thread);
67
68 _gc_waste += (unsigned)remaining();
69 size_t total_allocated = thread->allocated_bytes();
70 size_t allocated_since_last_gc = total_allocated - _allocated_before_last_gc;
71 _allocated_before_last_gc = total_allocated;
72
73 if (PrintTLAB && (_number_of_refills > 0 || Verbose)) {
74 print_stats("gc");
75 }
76
77 if (_number_of_refills > 0) {
78 // Update allocation history if a reasonable amount of eden was allocated.
79 bool update_allocation_history = used > 0.5 * capacity;
80
81 if (update_allocation_history) {
82 // Average the fraction of eden allocated in a tlab by this
83 // thread for use in the next resize operation.
84 // _gc_waste is not subtracted because it's included in
85 // "used".
86 // The result can be larger than 1.0 due to direct to old allocations.
87 // These allocations should ideally not be counted but since it is not possible
88 // to filter them out here we just cap the fraction to be at most 1.0.
89 double alloc_frac = MIN2(1.0, (double) allocated_since_last_gc / used);
96 global_stats()->update_slow_refill_waste(_slow_refill_waste);
97 global_stats()->update_fast_refill_waste(_fast_refill_waste);
98
99 } else {
100 assert(_number_of_refills == 0 && _fast_refill_waste == 0 &&
101 _slow_refill_waste == 0 && _gc_waste == 0,
102 "tlab stats == 0");
103 }
104 global_stats()->update_slow_allocations(_slow_allocations);
105 }
106
107 // Fills the current tlab with a dummy filler array to create
108 // an illusion of a contiguous Eden and optionally retires the tlab.
109 // Waste accounting should be done in caller as appropriate; see,
110 // for example, clear_before_allocation().
111 void ThreadLocalAllocBuffer::make_parsable(bool retire) {
112 if (end() != NULL) {
113 invariants();
114
115 if (retire) {
116 myThread()->incr_allocated_bytes(used_bytes());
117 }
118
119 CollectedHeap::fill_with_object(top(), hard_end(), retire);
120
121 if (retire || ZeroTLAB) { // "Reset" the TLAB
122 set_start(NULL);
123 set_top(NULL);
124 set_pf_top(NULL);
125 set_end(NULL);
126 }
127 }
128 assert(!(retire || ZeroTLAB) ||
129 (start() == NULL && end() == NULL && top() == NULL),
130 "TLAB must be reset");
131 }
132
133 void ThreadLocalAllocBuffer::resize_all_tlabs() {
134 if (ResizeTLAB) {
135 for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
136 thread->tlab().resize();
137 }
138 }
139 }
174 if (PrintTLAB && Verbose) {
175 print_stats("fill");
176 }
177 assert(top <= start + new_size - alignment_reserve(), "size too small");
178 initialize(start, top, start + new_size - alignment_reserve());
179
180 // Reset amount of internal fragmentation
181 set_refill_waste_limit(initial_refill_waste_limit());
182 }
183
184 void ThreadLocalAllocBuffer::initialize(HeapWord* start,
185 HeapWord* top,
186 HeapWord* end) {
187 set_start(start);
188 set_top(top);
189 set_pf_top(top);
190 set_end(end);
191 invariants();
192 }
193
194 void ThreadLocalAllocBuffer::initialize() {
195 initialize(NULL, // start
196 NULL, // top
197 NULL); // end
198
199 set_desired_size(initial_desired_size());
200
201 // Following check is needed because at startup the main (primordial)
202 // thread is initialized before the heap is. The initialization for
203 // this thread is redone in startup_initialization below.
204 if (Universe::heap() != NULL) {
205 size_t capacity = Universe::heap()->tlab_capacity(myThread()) / HeapWordSize;
206 double alloc_frac = desired_size() * target_refills() / (double) capacity;
207 _allocation_fraction.sample(alloc_frac);
208 }
209
210 set_refill_waste_limit(initial_refill_waste_limit());
211
212 initialize_statistics();
213 }
214
215 void ThreadLocalAllocBuffer::startup_initialization() {
216
217 // Assuming each thread's active tlab is, on average,
218 // 1/2 full at a GC
219 _target_refills = 100 / (2 * TLABWasteTargetPercent);
220 _target_refills = MAX2(_target_refills, (unsigned)1U);
221
222 _global_stats = new GlobalTLABStats();
223
224 // During jvm startup, the main (primordial) thread is initialized
225 // before the heap is initialized. So reinitialize it now.
226 guarantee(Thread::current()->is_Java_thread(), "tlab initialization thread not Java thread");
227 Thread::current()->tlab().initialize();
228
229 if (PrintTLAB && Verbose) {
230 gclog_or_tty->print("TLAB min: " SIZE_FORMAT " initial: " SIZE_FORMAT " max: " SIZE_FORMAT "\n",
231 min_size(), Thread::current()->tlab().initial_desired_size(), max_size());
232 }
233 }
234
235 size_t ThreadLocalAllocBuffer::initial_desired_size() {
236 size_t init_sz = 0;
237
238 if (TLABSize > 0) {
239 init_sz = TLABSize / HeapWordSize;
240 } else if (global_stats() != NULL) {
241 // Initial size is a function of the average number of allocating threads.
242 unsigned nof_threads = global_stats()->allocating_threads_avg();
243
244 init_sz = (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize) /
245 (nof_threads * target_refills());
246 init_sz = align_object_size(init_sz);
247 }
248 init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
249 return init_sz;
250 }
251
252 void ThreadLocalAllocBuffer::print_stats(const char* tag) {
253 Thread* thrd = myThread();
254 size_t waste = _gc_waste + _slow_refill_waste + _fast_refill_waste;
255 size_t alloc = _number_of_refills * _desired_size;
256 double waste_percent = alloc == 0 ? 0.0 :
257 100.0 * waste / alloc;
258 size_t tlab_used = Universe::heap()->tlab_used(thrd);
259 gclog_or_tty->print("TLAB: %s thread: " INTPTR_FORMAT " [id: %2d]"
260 " desired_size: " SIZE_FORMAT "KB"
261 " slow allocs: %d refill waste: " SIZE_FORMAT "B"
262 " alloc:%8.5f %8.0fKB refills: %d waste %4.1f%% gc: %dB"
263 " slow: %dB fast: %dB\n",
264 tag, p2i(thrd), thrd->osthread()->thread_id(),
265 _desired_size / (K / HeapWordSize),
266 _slow_allocations, _refill_waste_limit * HeapWordSize,
267 _allocation_fraction.average(),
268 _allocation_fraction.average() * tlab_used / K,
269 _number_of_refills, waste_percent,
270 _gc_waste * HeapWordSize,
271 _slow_refill_waste * HeapWordSize,
272 _fast_refill_waste * HeapWordSize);
273 }
274
275 void ThreadLocalAllocBuffer::verify() {
276 HeapWord* p = start();
277 HeapWord* t = top();
278 HeapWord* prev_p = NULL;
279 while (p < t) {
280 oop(p)->verify();
281 prev_p = p;
282 p += oop(p)->size();
283 }
284 guarantee(p == top(), "end of last object must match end of space");
285 }
286
287 Thread* ThreadLocalAllocBuffer::myThread() {
288 return (Thread*)(((char *)this) +
289 in_bytes(start_offset()) -
290 in_bytes(Thread::tlab_start_offset()));
291 }
292
293
294 GlobalTLABStats::GlobalTLABStats() :
295 _allocating_threads_avg(TLABAllocationWeight) {
296
297 initialize();
298
299 _allocating_threads_avg.sample(1); // One allocating thread at startup
300
301 if (UsePerfData) {
302
303 EXCEPTION_MARK;
304 ResourceMark rm;
305
306 char* cname = PerfDataManager::counter_name("tlab", "allocThreads");
307 _perf_allocating_threads =
308 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_None, CHECK);
309
310 cname = PerfDataManager::counter_name("tlab", "fills");
|
34 // Thread-Local Edens support
35
36 // static member initialization
37 size_t ThreadLocalAllocBuffer::_max_size = 0;
38 unsigned ThreadLocalAllocBuffer::_target_refills = 0;
39 GlobalTLABStats* ThreadLocalAllocBuffer::_global_stats = NULL;
40
41 void ThreadLocalAllocBuffer::clear_before_allocation() {
42 _slow_refill_waste += (unsigned)remaining();
43 make_parsable(true); // also retire the TLAB
44 }
45
46 void ThreadLocalAllocBuffer::accumulate_statistics_before_gc() {
47 global_stats()->initialize();
48
49 for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
50 thread->tlab().accumulate_statistics();
51 thread->tlab().initialize_statistics();
52 }
53
54 Universe::heap()->accumulate_statistics_all_gclabs();
55
56 // Publish new stats if some allocation occurred.
57 if (global_stats()->allocation() != 0) {
58 global_stats()->publish();
59 if (PrintTLAB) {
60 global_stats()->print();
61 }
62 }
63 }
64
65 void ThreadLocalAllocBuffer::accumulate_statistics() {
66 Thread* thread = myThread();
67 size_t capacity = Universe::heap()->tlab_capacity(thread);
68 size_t used = Universe::heap()->tlab_used(thread);
69
70 _gc_waste += (unsigned)remaining();
71 size_t total_allocated = _gclab ? thread->allocated_bytes_gclab() : thread->allocated_bytes();
72 size_t allocated_since_last_gc = total_allocated - _allocated_before_last_gc;
73 _allocated_before_last_gc = total_allocated;
74
75 if (PrintTLAB && (_number_of_refills > 0 || Verbose)) {
76 print_stats("gc");
77 }
78
79 if (_number_of_refills > 0) {
80 // Update allocation history if a reasonable amount of eden was allocated.
81 bool update_allocation_history = used > 0.5 * capacity;
82
83 if (update_allocation_history) {
84 // Average the fraction of eden allocated in a tlab by this
85 // thread for use in the next resize operation.
86 // _gc_waste is not subtracted because it's included in
87 // "used".
88 // The result can be larger than 1.0 due to direct to old allocations.
89 // These allocations should ideally not be counted but since it is not possible
90 // to filter them out here we just cap the fraction to be at most 1.0.
91 double alloc_frac = MIN2(1.0, (double) allocated_since_last_gc / used);
98 global_stats()->update_slow_refill_waste(_slow_refill_waste);
99 global_stats()->update_fast_refill_waste(_fast_refill_waste);
100
101 } else {
102 assert(_number_of_refills == 0 && _fast_refill_waste == 0 &&
103 _slow_refill_waste == 0 && _gc_waste == 0,
104 "tlab stats == 0");
105 }
106 global_stats()->update_slow_allocations(_slow_allocations);
107 }
108
109 // Fills the current tlab with a dummy filler array to create
110 // an illusion of a contiguous Eden and optionally retires the tlab.
111 // Waste accounting should be done in caller as appropriate; see,
112 // for example, clear_before_allocation().
113 void ThreadLocalAllocBuffer::make_parsable(bool retire) {
114 if (end() != NULL) {
115 invariants();
116
117 if (retire) {
118 if (_gclab) {
119 myThread()->incr_allocated_bytes_gclab(used_bytes());
120 } else {
121 myThread()->incr_allocated_bytes(used_bytes());
122 }
123 }
124
125 HeapWord* obj = Universe::heap()->tlab_post_allocation_setup(top());
126 CollectedHeap::fill_with_object(obj, hard_end(), retire);
127
128 if (retire || ZeroTLAB) { // "Reset" the TLAB
129 set_start(NULL);
130 set_top(NULL);
131 set_pf_top(NULL);
132 set_end(NULL);
133 }
134 }
135 assert(!(retire || ZeroTLAB) ||
136 (start() == NULL && end() == NULL && top() == NULL),
137 "TLAB must be reset");
138 }
139
140 void ThreadLocalAllocBuffer::resize_all_tlabs() {
141 if (ResizeTLAB) {
142 for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
143 thread->tlab().resize();
144 }
145 }
146 }
181 if (PrintTLAB && Verbose) {
182 print_stats("fill");
183 }
184 assert(top <= start + new_size - alignment_reserve(), "size too small");
185 initialize(start, top, start + new_size - alignment_reserve());
186
187 // Reset amount of internal fragmentation
188 set_refill_waste_limit(initial_refill_waste_limit());
189 }
190
191 void ThreadLocalAllocBuffer::initialize(HeapWord* start,
192 HeapWord* top,
193 HeapWord* end) {
194 set_start(start);
195 set_top(top);
196 set_pf_top(top);
197 set_end(end);
198 invariants();
199 }
200
201 void ThreadLocalAllocBuffer::initialize(bool gclab) {
202 _gclab = gclab;
203 initialize(NULL, // start
204 NULL, // top
205 NULL); // end
206
207 set_desired_size(initial_desired_size());
208
209 // Following check is needed because at startup the main (primordial)
210 // thread is initialized before the heap is. The initialization for
211 // this thread is redone in startup_initialization below.
212 if (Universe::heap() != NULL) {
213 size_t capacity = Universe::heap()->tlab_capacity(myThread()) / HeapWordSize;
214 double alloc_frac = desired_size() * target_refills() / (double) capacity;
215 _allocation_fraction.sample(alloc_frac);
216 }
217
218 set_refill_waste_limit(initial_refill_waste_limit());
219
220 initialize_statistics();
221 }
222
223 void ThreadLocalAllocBuffer::startup_initialization() {
224
225 // Assuming each thread's active tlab is, on average,
226 // 1/2 full at a GC
227 _target_refills = 100 / (2 * TLABWasteTargetPercent);
228 _target_refills = MAX2(_target_refills, (unsigned)1U);
229
230 _global_stats = new GlobalTLABStats();
231
232 // During jvm startup, the main (primordial) thread is initialized
233 // before the heap is initialized. So reinitialize it now.
234 guarantee(Thread::current()->is_Java_thread(), "tlab initialization thread not Java thread");
235 Thread::current()->tlab().initialize(false);
236 Thread::current()->gclab().initialize(true);
237
238 if (PrintTLAB && Verbose) {
239 gclog_or_tty->print("TLAB min: " SIZE_FORMAT " initial: " SIZE_FORMAT " max: " SIZE_FORMAT "\n",
240 min_size(), Thread::current()->tlab().initial_desired_size(), max_size());
241 }
242 }
243
244 size_t ThreadLocalAllocBuffer::initial_desired_size() {
245 size_t init_sz = 0;
246
247 if (TLABSize > 0) {
248 init_sz = TLABSize / HeapWordSize;
249 } else if (global_stats() != NULL) {
250 // Initial size is a function of the average number of allocating threads.
251 unsigned nof_threads = global_stats()->allocating_threads_avg();
252
253 init_sz = (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize) /
254 (nof_threads * target_refills());
255 init_sz = align_object_size(init_sz);
256 }
257 init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
258 return init_sz;
259 }
260
261 void ThreadLocalAllocBuffer::print_stats(const char* tag) {
262 Thread* thrd = myThread();
263 size_t waste = _gc_waste + _slow_refill_waste + _fast_refill_waste;
264 size_t alloc = _number_of_refills * _desired_size;
265 double waste_percent = alloc == 0 ? 0.0 :
266 100.0 * waste / alloc;
267 size_t tlab_used = Universe::heap()->tlab_used(thrd);
268 gclog_or_tty->print("TLAB: %s %s thread: " INTPTR_FORMAT " [id: %2d]"
269 " desired_size: " SIZE_FORMAT "KB"
270 " slow allocs: %d refill waste: " SIZE_FORMAT "B"
271 " alloc:%8.5f %8.0fKB refills: %d waste %4.1f%% gc: %dB"
272 " slow: %dB fast: %dB\n",
273 tag, _gclab ? "gclab" : "tlab ", p2i(thrd), thrd->osthread()->thread_id(),
274 _desired_size / (K / HeapWordSize),
275 _slow_allocations, _refill_waste_limit * HeapWordSize,
276 _allocation_fraction.average(),
277 _allocation_fraction.average() * tlab_used / K,
278 _number_of_refills, waste_percent,
279 _gc_waste * HeapWordSize,
280 _slow_refill_waste * HeapWordSize,
281 _fast_refill_waste * HeapWordSize);
282 }
283
284 void ThreadLocalAllocBuffer::verify() {
285 HeapWord* p = start();
286 HeapWord* t = top();
287 HeapWord* prev_p = NULL;
288 while (p < t) {
289 oop(p)->verify();
290 prev_p = p;
291 p += oop(p)->size();
292 }
293 guarantee(p == top(), "end of last object must match end of space");
294 }
295
296 Thread* ThreadLocalAllocBuffer::myThread() {
297 ByteSize gclab_offset = Thread::gclab_start_offset();
298 ByteSize tlab_offset = Thread::tlab_start_offset();
299 ByteSize offs = _gclab ? gclab_offset : tlab_offset;
300 Thread* thread = (Thread*)(((char *)this) +
301 in_bytes(start_offset()) - in_bytes(offs));
302 #ifdef ASSERT
303 assert(this == (_gclab ? &thread->gclab() : &thread->tlab()), "must be");
304 #endif
305 return thread;
306 }
307
308 size_t ThreadLocalAllocBuffer::end_reserve() {
309 int reserve_size = typeArrayOopDesc::header_size(T_INT) + Universe::heap()->oop_extra_words();
310 return MAX2(reserve_size, VM_Version::reserve_for_allocation_prefetch());
311 }
312
313 void ThreadLocalAllocBuffer::rollback(size_t size) {
314 HeapWord* old_top = top();
315 if (old_top != NULL) { // Pathological case: we accept that we can't rollback.
316 set_top(old_top - size);
317 }
318 }
319
320
321 GlobalTLABStats::GlobalTLABStats() :
322 _allocating_threads_avg(TLABAllocationWeight) {
323
324 initialize();
325
326 _allocating_threads_avg.sample(1); // One allocating thread at startup
327
328 if (UsePerfData) {
329
330 EXCEPTION_MARK;
331 ResourceMark rm;
332
333 char* cname = PerfDataManager::counter_name("tlab", "allocThreads");
334 _perf_allocating_threads =
335 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_None, CHECK);
336
337 cname = PerfDataManager::counter_name("tlab", "fills");
|