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