comparison src/share/vm/memory/threadLocalAllocBuffer.cpp @ 14310:1e1c8d358b52

8030177: G1: Enable TLAB resizing Reviewed-by: tschatzl, stefank, jmasa
author brutisso
date Mon, 27 Jan 2014 13:14:53 +0100
parents f34d701e952e
children d8041d695d19 78bbf4d43a14
comparison
equal deleted inserted replaced
14309:63a4eb8bcd23 14310:1e1c8d358b52
32 #include "utilities/copy.hpp" 32 #include "utilities/copy.hpp"
33 33
34 // Thread-Local Edens support 34 // Thread-Local Edens support
35 35
36 // static member initialization 36 // static member initialization
37 size_t ThreadLocalAllocBuffer::_max_size = 0;
37 unsigned ThreadLocalAllocBuffer::_target_refills = 0; 38 unsigned ThreadLocalAllocBuffer::_target_refills = 0;
38 GlobalTLABStats* ThreadLocalAllocBuffer::_global_stats = NULL; 39 GlobalTLABStats* ThreadLocalAllocBuffer::_global_stats = NULL;
39 40
40 void ThreadLocalAllocBuffer::clear_before_allocation() { 41 void ThreadLocalAllocBuffer::clear_before_allocation() {
41 _slow_refill_waste += (unsigned)remaining(); 42 _slow_refill_waste += (unsigned)remaining();
43 } 44 }
44 45
45 void ThreadLocalAllocBuffer::accumulate_statistics_before_gc() { 46 void ThreadLocalAllocBuffer::accumulate_statistics_before_gc() {
46 global_stats()->initialize(); 47 global_stats()->initialize();
47 48
48 for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) { 49 for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
49 thread->tlab().accumulate_statistics(); 50 thread->tlab().accumulate_statistics();
50 thread->tlab().initialize_statistics(); 51 thread->tlab().initialize_statistics();
51 } 52 }
52 53
53 // Publish new stats if some allocation occurred. 54 // Publish new stats if some allocation occurred.
58 } 59 }
59 } 60 }
60 } 61 }
61 62
62 void ThreadLocalAllocBuffer::accumulate_statistics() { 63 void ThreadLocalAllocBuffer::accumulate_statistics() {
63 size_t capacity = Universe::heap()->tlab_capacity(myThread()) / HeapWordSize; 64 Thread* thread = myThread();
64 size_t unused = Universe::heap()->unsafe_max_tlab_alloc(myThread()) / HeapWordSize; 65 size_t capacity = Universe::heap()->tlab_capacity(thread);
65 size_t used = capacity - unused; 66 size_t used = Universe::heap()->tlab_used(thread);
66
67 // Update allocation history if a reasonable amount of eden was allocated.
68 bool update_allocation_history = used > 0.5 * capacity;
69 67
70 _gc_waste += (unsigned)remaining(); 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;
71 72
72 if (PrintTLAB && (_number_of_refills > 0 || Verbose)) { 73 if (PrintTLAB && (_number_of_refills > 0 || Verbose)) {
73 print_stats("gc"); 74 print_stats("gc");
74 } 75 }
75 76
76 if (_number_of_refills > 0) { 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;
77 80
78 if (update_allocation_history) { 81 if (update_allocation_history) {
79 // Average the fraction of eden allocated in a tlab by this 82 // Average the fraction of eden allocated in a tlab by this
80 // thread for use in the next resize operation. 83 // thread for use in the next resize operation.
81 // _gc_waste is not subtracted because it's included in 84 // _gc_waste is not subtracted because it's included in
82 // "used". 85 // "used".
83 size_t allocation = _number_of_refills * desired_size(); 86 // The result can be larger than 1.0 due to direct to old allocations.
84 double alloc_frac = allocation / (double) used; 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);
85 _allocation_fraction.sample(alloc_frac); 90 _allocation_fraction.sample(alloc_frac);
86 } 91 }
87 global_stats()->update_allocating_threads(); 92 global_stats()->update_allocating_threads();
88 global_stats()->update_number_of_refills(_number_of_refills); 93 global_stats()->update_number_of_refills(_number_of_refills);
89 global_stats()->update_allocation(_number_of_refills * desired_size()); 94 global_stats()->update_allocation(_number_of_refills * desired_size());
124 (start() == NULL && end() == NULL && top() == NULL), 129 (start() == NULL && end() == NULL && top() == NULL),
125 "TLAB must be reset"); 130 "TLAB must be reset");
126 } 131 }
127 132
128 void ThreadLocalAllocBuffer::resize_all_tlabs() { 133 void ThreadLocalAllocBuffer::resize_all_tlabs() {
129 for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) { 134 if (ResizeTLAB) {
130 thread->tlab().resize(); 135 for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
136 thread->tlab().resize();
137 }
131 } 138 }
132 } 139 }
133 140
134 void ThreadLocalAllocBuffer::resize() { 141 void ThreadLocalAllocBuffer::resize() {
135 142 // Compute the next tlab size using expected allocation amount
136 if (ResizeTLAB) { 143 assert(ResizeTLAB, "Should not call this otherwise");
137 // Compute the next tlab size using expected allocation amount 144 size_t alloc = (size_t)(_allocation_fraction.average() *
138 size_t alloc = (size_t)(_allocation_fraction.average() * 145 (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize));
139 (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize)); 146 size_t new_size = alloc / _target_refills;
140 size_t new_size = alloc / _target_refills; 147
141 148 new_size = MIN2(MAX2(new_size, min_size()), max_size());
142 new_size = MIN2(MAX2(new_size, min_size()), max_size()); 149
143 150 size_t aligned_new_size = align_object_size(new_size);
144 size_t aligned_new_size = align_object_size(new_size); 151
145 152 if (PrintTLAB && Verbose) {
146 if (PrintTLAB && Verbose) { 153 gclog_or_tty->print("TLAB new size: thread: " INTPTR_FORMAT " [id: %2d]"
147 gclog_or_tty->print("TLAB new size: thread: " INTPTR_FORMAT " [id: %2d]" 154 " refills %d alloc: %8.6f desired_size: " SIZE_FORMAT " -> " SIZE_FORMAT "\n",
148 " refills %d alloc: %8.6f desired_size: " SIZE_FORMAT " -> " SIZE_FORMAT "\n", 155 myThread(), myThread()->osthread()->thread_id(),
149 myThread(), myThread()->osthread()->thread_id(), 156 _target_refills, _allocation_fraction.average(), desired_size(), aligned_new_size);
150 _target_refills, _allocation_fraction.average(), desired_size(), aligned_new_size); 157 }
151 } 158 set_desired_size(aligned_new_size);
152 set_desired_size(aligned_new_size); 159 set_refill_waste_limit(initial_refill_waste_limit());
153
154 set_refill_waste_limit(initial_refill_waste_limit());
155 }
156 } 160 }
157 161
158 void ThreadLocalAllocBuffer::initialize_statistics() { 162 void ThreadLocalAllocBuffer::initialize_statistics() {
159 _number_of_refills = 0; 163 _number_of_refills = 0;
160 _fast_refill_waste = 0; 164 _fast_refill_waste = 0;
246 init_sz = MIN2(MAX2(init_sz, min_size()), max_size()); 250 init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
247 } 251 }
248 return init_sz; 252 return init_sz;
249 } 253 }
250 254
251 const size_t ThreadLocalAllocBuffer::max_size() {
252
253 // TLABs can't be bigger than we can fill with a int[Integer.MAX_VALUE].
254 // This restriction could be removed by enabling filling with multiple arrays.
255 // If we compute that the reasonable way as
256 // header_size + ((sizeof(jint) * max_jint) / HeapWordSize)
257 // we'll overflow on the multiply, so we do the divide first.
258 // We actually lose a little by dividing first,
259 // but that just makes the TLAB somewhat smaller than the biggest array,
260 // which is fine, since we'll be able to fill that.
261
262 size_t unaligned_max_size = typeArrayOopDesc::header_size(T_INT) +
263 sizeof(jint) *
264 ((juint) max_jint / (size_t) HeapWordSize);
265 return align_size_down(unaligned_max_size, MinObjAlignment);
266 }
267
268 void ThreadLocalAllocBuffer::print_stats(const char* tag) { 255 void ThreadLocalAllocBuffer::print_stats(const char* tag) {
269 Thread* thrd = myThread(); 256 Thread* thrd = myThread();
270 size_t waste = _gc_waste + _slow_refill_waste + _fast_refill_waste; 257 size_t waste = _gc_waste + _slow_refill_waste + _fast_refill_waste;
271 size_t alloc = _number_of_refills * _desired_size; 258 size_t alloc = _number_of_refills * _desired_size;
272 double waste_percent = alloc == 0 ? 0.0 : 259 double waste_percent = alloc == 0 ? 0.0 :
273 100.0 * waste / alloc; 260 100.0 * waste / alloc;
274 size_t tlab_used = Universe::heap()->tlab_capacity(thrd) - 261 size_t tlab_used = Universe::heap()->tlab_used(thrd);
275 Universe::heap()->unsafe_max_tlab_alloc(thrd);
276 gclog_or_tty->print("TLAB: %s thread: " INTPTR_FORMAT " [id: %2d]" 262 gclog_or_tty->print("TLAB: %s thread: " INTPTR_FORMAT " [id: %2d]"
277 " desired_size: " SIZE_FORMAT "KB" 263 " desired_size: " SIZE_FORMAT "KB"
278 " slow allocs: %d refill waste: " SIZE_FORMAT "B" 264 " slow allocs: %d refill waste: " SIZE_FORMAT "B"
279 " alloc:%8.5f %8.0fKB refills: %d waste %4.1f%% gc: %dB" 265 " alloc:%8.5f %8.0fKB refills: %d waste %4.1f%% gc: %dB"
280 " slow: %dB fast: %dB\n", 266 " slow: %dB fast: %dB\n",