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
25 #include "precompiled.hpp"
26 #include "gc/shared/genCollectedHeap.hpp"
27 #include "gc/shared/threadLocalAllocBuffer.inline.hpp"
28 #include "logging/log.hpp"
29 #include "memory/resourceArea.hpp"
30 #include "memory/universe.inline.hpp"
31 #include "oops/oop.inline.hpp"
32 #include "runtime/thread.inline.hpp"
33 #include "utilities/copy.hpp"
34
35 // Thread-Local Edens support
36
37 // static member initialization
38 size_t ThreadLocalAllocBuffer::_max_size = 0;
39 int ThreadLocalAllocBuffer::_reserve_for_allocation_prefetch = 0;
40 unsigned ThreadLocalAllocBuffer::_target_refills = 0;
41 GlobalTLABStats* ThreadLocalAllocBuffer::_global_stats = NULL;
42
43 void ThreadLocalAllocBuffer::clear_before_allocation() {
44 _slow_refill_waste += (unsigned)remaining();
45 make_parsable(true); // also retire the TLAB
46 }
47
48 void ThreadLocalAllocBuffer::accumulate_statistics_before_gc() {
49 global_stats()->initialize();
50
51 for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
104
105 // Fills the current tlab with a dummy filler array to create
106 // an illusion of a contiguous Eden and optionally retires the tlab.
107 // Waste accounting should be done in caller as appropriate; see,
108 // for example, clear_before_allocation().
109 void ThreadLocalAllocBuffer::make_parsable(bool retire, bool zap) {
110 if (end() != NULL) {
111 invariants();
112
113 if (retire) {
114 myThread()->incr_allocated_bytes(used_bytes());
115 }
116
117 CollectedHeap::fill_with_object(top(), hard_end(), retire && zap);
118
119 if (retire || ZeroTLAB) { // "Reset" the TLAB
120 set_start(NULL);
121 set_top(NULL);
122 set_pf_top(NULL);
123 set_end(NULL);
124 }
125 }
126 assert(!(retire || ZeroTLAB) ||
127 (start() == NULL && end() == NULL && top() == NULL),
128 "TLAB must be reset");
129 }
130
131 void ThreadLocalAllocBuffer::resize_all_tlabs() {
132 if (ResizeTLAB) {
133 for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
134 thread->tlab().resize();
135 }
136 }
137 }
138
139 void ThreadLocalAllocBuffer::resize() {
140 // Compute the next tlab size using expected allocation amount
141 assert(ResizeTLAB, "Should not call this otherwise");
142 size_t alloc = (size_t)(_allocation_fraction.average() *
143 (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize));
166
167 void ThreadLocalAllocBuffer::fill(HeapWord* start,
168 HeapWord* top,
169 size_t new_size) {
170 _number_of_refills++;
171 print_stats("fill");
172 assert(top <= start + new_size - alignment_reserve(), "size too small");
173 initialize(start, top, start + new_size - alignment_reserve());
174
175 // Reset amount of internal fragmentation
176 set_refill_waste_limit(initial_refill_waste_limit());
177 }
178
179 void ThreadLocalAllocBuffer::initialize(HeapWord* start,
180 HeapWord* top,
181 HeapWord* end) {
182 set_start(start);
183 set_top(top);
184 set_pf_top(top);
185 set_end(end);
186 invariants();
187 }
188
189 void ThreadLocalAllocBuffer::initialize() {
190 initialize(NULL, // start
191 NULL, // top
192 NULL); // end
193
194 set_desired_size(initial_desired_size());
195
196 // Following check is needed because at startup the main (primordial)
197 // thread is initialized before the heap is. The initialization for
198 // this thread is redone in startup_initialization below.
199 if (Universe::heap() != NULL) {
200 size_t capacity = Universe::heap()->tlab_capacity(myThread()) / HeapWordSize;
201 double alloc_frac = desired_size() * target_refills() / (double) capacity;
202 _allocation_fraction.sample(alloc_frac);
203 }
204
205 set_refill_waste_limit(initial_refill_waste_limit());
206
289 _allocation_fraction.average(),
290 _allocation_fraction.average() * tlab_used / K,
291 _number_of_refills, waste_percent,
292 _gc_waste * HeapWordSize,
293 _slow_refill_waste * HeapWordSize,
294 _fast_refill_waste * HeapWordSize);
295 }
296
297 void ThreadLocalAllocBuffer::verify() {
298 HeapWord* p = start();
299 HeapWord* t = top();
300 HeapWord* prev_p = NULL;
301 while (p < t) {
302 oop(p)->verify();
303 prev_p = p;
304 p += oop(p)->size();
305 }
306 guarantee(p == top(), "end of last object must match end of space");
307 }
308
309 Thread* ThreadLocalAllocBuffer::myThread() {
310 return (Thread*)(((char *)this) +
311 in_bytes(start_offset()) -
312 in_bytes(Thread::tlab_start_offset()));
313 }
314
315
316 GlobalTLABStats::GlobalTLABStats() :
317 _allocating_threads_avg(TLABAllocationWeight) {
318
319 initialize();
320
321 _allocating_threads_avg.sample(1); // One allocating thread at startup
322
323 if (UsePerfData) {
324
325 EXCEPTION_MARK;
326 ResourceMark rm;
327
328 char* cname = PerfDataManager::counter_name("tlab", "allocThreads");
329 _perf_allocating_threads =
330 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_None, CHECK);
331
332 cname = PerfDataManager::counter_name("tlab", "fills");
333 _perf_total_refills =
334 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_None, CHECK);
|
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
25 #include "precompiled.hpp"
26 #include "gc/shared/genCollectedHeap.hpp"
27 #include "gc/shared/threadLocalAllocBuffer.inline.hpp"
28 #include "logging/log.hpp"
29 #include "memory/resourceArea.hpp"
30 #include "memory/universe.inline.hpp"
31 #include "oops/oop.inline.hpp"
32 #include "runtime/heapMonitoring.hpp"
33 #include "runtime/thread.inline.hpp"
34 #include "utilities/copy.hpp"
35
36 // Thread-Local Edens support
37
38 // static member initialization
39 size_t ThreadLocalAllocBuffer::_max_size = 0;
40 int ThreadLocalAllocBuffer::_reserve_for_allocation_prefetch = 0;
41 unsigned ThreadLocalAllocBuffer::_target_refills = 0;
42 GlobalTLABStats* ThreadLocalAllocBuffer::_global_stats = NULL;
43
44 void ThreadLocalAllocBuffer::clear_before_allocation() {
45 _slow_refill_waste += (unsigned)remaining();
46 make_parsable(true); // also retire the TLAB
47 }
48
49 void ThreadLocalAllocBuffer::accumulate_statistics_before_gc() {
50 global_stats()->initialize();
51
52 for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
105
106 // Fills the current tlab with a dummy filler array to create
107 // an illusion of a contiguous Eden and optionally retires the tlab.
108 // Waste accounting should be done in caller as appropriate; see,
109 // for example, clear_before_allocation().
110 void ThreadLocalAllocBuffer::make_parsable(bool retire, bool zap) {
111 if (end() != NULL) {
112 invariants();
113
114 if (retire) {
115 myThread()->incr_allocated_bytes(used_bytes());
116 }
117
118 CollectedHeap::fill_with_object(top(), hard_end(), retire && zap);
119
120 if (retire || ZeroTLAB) { // "Reset" the TLAB
121 set_start(NULL);
122 set_top(NULL);
123 set_pf_top(NULL);
124 set_end(NULL);
125 set_actual_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 }
140
141 void ThreadLocalAllocBuffer::resize() {
142 // Compute the next tlab size using expected allocation amount
143 assert(ResizeTLAB, "Should not call this otherwise");
144 size_t alloc = (size_t)(_allocation_fraction.average() *
145 (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize));
168
169 void ThreadLocalAllocBuffer::fill(HeapWord* start,
170 HeapWord* top,
171 size_t new_size) {
172 _number_of_refills++;
173 print_stats("fill");
174 assert(top <= start + new_size - alignment_reserve(), "size too small");
175 initialize(start, top, start + new_size - alignment_reserve());
176
177 // Reset amount of internal fragmentation
178 set_refill_waste_limit(initial_refill_waste_limit());
179 }
180
181 void ThreadLocalAllocBuffer::initialize(HeapWord* start,
182 HeapWord* top,
183 HeapWord* end) {
184 set_start(start);
185 set_top(top);
186 set_pf_top(top);
187 set_end(end);
188 set_actual_end(end);
189 invariants();
190 _bytes_until_sample = 0;
191 }
192
193 void ThreadLocalAllocBuffer::initialize() {
194 initialize(NULL, // start
195 NULL, // top
196 NULL); // end
197
198 set_desired_size(initial_desired_size());
199
200 // Following check is needed because at startup the main (primordial)
201 // thread is initialized before the heap is. The initialization for
202 // this thread is redone in startup_initialization below.
203 if (Universe::heap() != NULL) {
204 size_t capacity = Universe::heap()->tlab_capacity(myThread()) / HeapWordSize;
205 double alloc_frac = desired_size() * target_refills() / (double) capacity;
206 _allocation_fraction.sample(alloc_frac);
207 }
208
209 set_refill_waste_limit(initial_refill_waste_limit());
210
293 _allocation_fraction.average(),
294 _allocation_fraction.average() * tlab_used / K,
295 _number_of_refills, waste_percent,
296 _gc_waste * HeapWordSize,
297 _slow_refill_waste * HeapWordSize,
298 _fast_refill_waste * HeapWordSize);
299 }
300
301 void ThreadLocalAllocBuffer::verify() {
302 HeapWord* p = start();
303 HeapWord* t = top();
304 HeapWord* prev_p = NULL;
305 while (p < t) {
306 oop(p)->verify();
307 prev_p = p;
308 p += oop(p)->size();
309 }
310 guarantee(p == top(), "end of last object must match end of space");
311 }
312
313 void ThreadLocalAllocBuffer::pick_next_sample() {
314 if (bytes_until_sample() == 0) {
315 HeapMonitoring::pick_next_sample(bytes_until_sample_addr());
316 }
317
318 // Finally, fix up the sampling bytes left and _end.
319 size_t heap_words_remaining = _end - _top;
320 size_t bytes_left = bytes_until_sample();
321 size_t words_until_sample = bytes_left / HeapWordSize;
322
323 if (heap_words_remaining > words_until_sample) {
324 set_end(_top + words_until_sample);
325 set_bytes_until_sample(0);
326 } else {
327 // TODO(jcbeyler): this is not exact actually since there can be left over
328 // space, this will need to get fixed...
329 bytes_left -= heap_words_remaining * HeapWordSize;
330 set_bytes_until_sample(bytes_left);
331 }
332 }
333
334 Thread* ThreadLocalAllocBuffer::myThread() {
335 return (Thread*)(((char *)this) +
336 in_bytes(start_offset()) -
337 in_bytes(Thread::tlab_start_offset()));
338 }
339
340 void ThreadLocalAllocBuffer::handle_sample(Thread* thread, HeapWord* result,
341 size_t size) {
342 set_bytes_until_sample(bytes_until_sample() - size);
343
344 // Should we sample now?
345 if (should_sample()) {
346 set_back_actual_end();
347 HeapMonitoring::object_alloc_do_sample(thread,
348 reinterpret_cast<oopDesc*>(result),
349 size);
350 pick_next_sample();
351 } else {
352 // Update the size and end fields.
353 set_back_actual_end();
354 pick_next_sample();
355 }
356 }
357
358 GlobalTLABStats::GlobalTLABStats() :
359 _allocating_threads_avg(TLABAllocationWeight) {
360
361 initialize();
362
363 _allocating_threads_avg.sample(1); // One allocating thread at startup
364
365 if (UsePerfData) {
366
367 EXCEPTION_MARK;
368 ResourceMark rm;
369
370 char* cname = PerfDataManager::counter_name("tlab", "allocThreads");
371 _perf_allocating_threads =
372 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_None, CHECK);
373
374 cname = PerfDataManager::counter_name("tlab", "fills");
375 _perf_total_refills =
376 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_None, CHECK);
|