Mercurial > hg > graal-jvmci-8
annotate src/share/vm/memory/threadLocalAllocBuffer.cpp @ 2368:dde920245681
6896099: Integrate CMS heap ergo with default heap sizing ergo
6627787: CMS: JVM refuses to start up with -Xms16m -Xmx16m
7000125: CMS: Anti-monotone young gen sizing with respect to maximum whole heap size specification
7027529: CMS: retire CMSUseOldDefaults flag
Summary: Simplify CMS heap sizing code, relying on ergonomic initial sizing consistent with other collectors for the most part, controlling only young gen sizing to rein in pause times. Make CMS young gen sizing default statically cpu-dependant. Remove inconsistencies wrt generation sizing and policy code, allowing for the fixing for 6627787 and 7000125. For 7027529, retire the flag CMSUseOldDefaults which had been introduced as a bridge from JDK 5 to JDK 6 a number of years ago.
Reviewed-by: brutisso, poonam
author | ysr |
---|---|
date | Wed, 16 Mar 2011 10:37:08 -0700 |
parents | b1a2afa37ec4 |
children | f08d439fab8c |
rev | line source |
---|---|
0 | 1 /* |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1165
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1165
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1165
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "memory/genCollectedHeap.hpp" | |
27 #include "memory/resourceArea.hpp" | |
28 #include "memory/threadLocalAllocBuffer.inline.hpp" | |
29 #include "memory/universe.inline.hpp" | |
30 #include "oops/oop.inline.hpp" | |
31 #include "utilities/copy.hpp" | |
32 #ifdef TARGET_OS_FAMILY_linux | |
33 # include "thread_linux.inline.hpp" | |
34 #endif | |
35 #ifdef TARGET_OS_FAMILY_solaris | |
36 # include "thread_solaris.inline.hpp" | |
37 #endif | |
38 #ifdef TARGET_OS_FAMILY_windows | |
39 # include "thread_windows.inline.hpp" | |
40 #endif | |
0 | 41 |
1972 | 42 // Thread-Local Edens support |
0 | 43 |
44 // static member initialization | |
45 unsigned ThreadLocalAllocBuffer::_target_refills = 0; | |
46 GlobalTLABStats* ThreadLocalAllocBuffer::_global_stats = NULL; | |
47 | |
48 void ThreadLocalAllocBuffer::clear_before_allocation() { | |
49 _slow_refill_waste += (unsigned)remaining(); | |
50 make_parsable(true); // also retire the TLAB | |
51 } | |
52 | |
53 void ThreadLocalAllocBuffer::accumulate_statistics_before_gc() { | |
54 global_stats()->initialize(); | |
55 | |
56 for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) { | |
57 thread->tlab().accumulate_statistics(); | |
58 thread->tlab().initialize_statistics(); | |
59 } | |
60 | |
61 // Publish new stats if some allocation occurred. | |
62 if (global_stats()->allocation() != 0) { | |
63 global_stats()->publish(); | |
64 if (PrintTLAB) { | |
65 global_stats()->print(); | |
66 } | |
67 } | |
68 } | |
69 | |
70 void ThreadLocalAllocBuffer::accumulate_statistics() { | |
71 size_t capacity = Universe::heap()->tlab_capacity(myThread()) / HeapWordSize; | |
72 size_t unused = Universe::heap()->unsafe_max_tlab_alloc(myThread()) / HeapWordSize; | |
73 size_t used = capacity - unused; | |
74 | |
75 // Update allocation history if a reasonable amount of eden was allocated. | |
76 bool update_allocation_history = used > 0.5 * capacity; | |
77 | |
78 _gc_waste += (unsigned)remaining(); | |
79 | |
80 if (PrintTLAB && (_number_of_refills > 0 || Verbose)) { | |
81 print_stats("gc"); | |
82 } | |
83 | |
84 if (_number_of_refills > 0) { | |
85 | |
86 if (update_allocation_history) { | |
87 // Average the fraction of eden allocated in a tlab by this | |
88 // thread for use in the next resize operation. | |
89 // _gc_waste is not subtracted because it's included in | |
90 // "used". | |
91 size_t allocation = _number_of_refills * desired_size(); | |
92 double alloc_frac = allocation / (double) used; | |
93 _allocation_fraction.sample(alloc_frac); | |
94 } | |
95 global_stats()->update_allocating_threads(); | |
96 global_stats()->update_number_of_refills(_number_of_refills); | |
97 global_stats()->update_allocation(_number_of_refills * desired_size()); | |
98 global_stats()->update_gc_waste(_gc_waste); | |
99 global_stats()->update_slow_refill_waste(_slow_refill_waste); | |
100 global_stats()->update_fast_refill_waste(_fast_refill_waste); | |
101 | |
102 } else { | |
103 assert(_number_of_refills == 0 && _fast_refill_waste == 0 && | |
104 _slow_refill_waste == 0 && _gc_waste == 0, | |
105 "tlab stats == 0"); | |
106 } | |
107 global_stats()->update_slow_allocations(_slow_allocations); | |
108 } | |
109 | |
110 // Fills the current tlab with a dummy filler array to create | |
111 // an illusion of a contiguous Eden and optionally retires the tlab. | |
112 // Waste accounting should be done in caller as appropriate; see, | |
113 // for example, clear_before_allocation(). | |
114 void ThreadLocalAllocBuffer::make_parsable(bool retire) { | |
115 if (end() != NULL) { | |
116 invariants(); | |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
117 |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
118 if (retire) { |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
119 myThread()->incr_allocated_bytes(used_bytes()); |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
120 } |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
121 |
1165
2dd52dea6d28
6902115: G1:assert(ignore_max_completed||thread->is_Java_thread()||SafepointSynchronize::is_at_safepoint())
johnc
parents:
579
diff
changeset
|
122 CollectedHeap::fill_with_object(top(), hard_end(), retire); |
0 | 123 |
124 if (retire || ZeroTLAB) { // "Reset" the TLAB | |
125 set_start(NULL); | |
126 set_top(NULL); | |
127 set_pf_top(NULL); | |
128 set_end(NULL); | |
129 } | |
130 } | |
131 assert(!(retire || ZeroTLAB) || | |
132 (start() == NULL && end() == NULL && top() == NULL), | |
133 "TLAB must be reset"); | |
134 } | |
135 | |
136 void ThreadLocalAllocBuffer::resize_all_tlabs() { | |
137 for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) { | |
138 thread->tlab().resize(); | |
139 } | |
140 } | |
141 | |
142 void ThreadLocalAllocBuffer::resize() { | |
143 | |
144 if (ResizeTLAB) { | |
145 // Compute the next tlab size using expected allocation amount | |
146 size_t alloc = (size_t)(_allocation_fraction.average() * | |
147 (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize)); | |
148 size_t new_size = alloc / _target_refills; | |
149 | |
150 new_size = MIN2(MAX2(new_size, min_size()), max_size()); | |
151 | |
152 size_t aligned_new_size = align_object_size(new_size); | |
153 | |
154 if (PrintTLAB && Verbose) { | |
155 gclog_or_tty->print("TLAB new size: thread: " INTPTR_FORMAT " [id: %2d]" | |
156 " refills %d alloc: %8.6f desired_size: " SIZE_FORMAT " -> " SIZE_FORMAT "\n", | |
157 myThread(), myThread()->osthread()->thread_id(), | |
158 _target_refills, _allocation_fraction.average(), desired_size(), aligned_new_size); | |
159 } | |
160 set_desired_size(aligned_new_size); | |
161 | |
162 set_refill_waste_limit(initial_refill_waste_limit()); | |
163 } | |
164 } | |
165 | |
166 void ThreadLocalAllocBuffer::initialize_statistics() { | |
167 _number_of_refills = 0; | |
168 _fast_refill_waste = 0; | |
169 _slow_refill_waste = 0; | |
170 _gc_waste = 0; | |
171 _slow_allocations = 0; | |
172 } | |
173 | |
174 void ThreadLocalAllocBuffer::fill(HeapWord* start, | |
175 HeapWord* top, | |
176 size_t new_size) { | |
177 _number_of_refills++; | |
178 if (PrintTLAB && Verbose) { | |
179 print_stats("fill"); | |
180 } | |
181 assert(top <= start + new_size - alignment_reserve(), "size too small"); | |
182 initialize(start, top, start + new_size - alignment_reserve()); | |
183 | |
184 // Reset amount of internal fragmentation | |
185 set_refill_waste_limit(initial_refill_waste_limit()); | |
186 } | |
187 | |
188 void ThreadLocalAllocBuffer::initialize(HeapWord* start, | |
189 HeapWord* top, | |
190 HeapWord* end) { | |
191 set_start(start); | |
192 set_top(top); | |
193 set_pf_top(top); | |
194 set_end(end); | |
195 invariants(); | |
196 } | |
197 | |
198 void ThreadLocalAllocBuffer::initialize() { | |
199 initialize(NULL, // start | |
200 NULL, // top | |
201 NULL); // end | |
202 | |
203 set_desired_size(initial_desired_size()); | |
204 | |
205 // Following check is needed because at startup the main (primordial) | |
206 // thread is initialized before the heap is. The initialization for | |
207 // this thread is redone in startup_initialization below. | |
208 if (Universe::heap() != NULL) { | |
209 size_t capacity = Universe::heap()->tlab_capacity(myThread()) / HeapWordSize; | |
210 double alloc_frac = desired_size() * target_refills() / (double) capacity; | |
211 _allocation_fraction.sample(alloc_frac); | |
212 } | |
213 | |
214 set_refill_waste_limit(initial_refill_waste_limit()); | |
215 | |
216 initialize_statistics(); | |
217 } | |
218 | |
219 void ThreadLocalAllocBuffer::startup_initialization() { | |
220 | |
221 // Assuming each thread's active tlab is, on average, | |
222 // 1/2 full at a GC | |
223 _target_refills = 100 / (2 * TLABWasteTargetPercent); | |
224 _target_refills = MAX2(_target_refills, (unsigned)1U); | |
225 | |
226 _global_stats = new GlobalTLABStats(); | |
227 | |
228 // During jvm startup, the main (primordial) thread is initialized | |
229 // before the heap is initialized. So reinitialize it now. | |
230 guarantee(Thread::current()->is_Java_thread(), "tlab initialization thread not Java thread"); | |
231 Thread::current()->tlab().initialize(); | |
232 | |
233 if (PrintTLAB && Verbose) { | |
234 gclog_or_tty->print("TLAB min: " SIZE_FORMAT " initial: " SIZE_FORMAT " max: " SIZE_FORMAT "\n", | |
235 min_size(), Thread::current()->tlab().initial_desired_size(), max_size()); | |
236 } | |
237 } | |
238 | |
239 size_t ThreadLocalAllocBuffer::initial_desired_size() { | |
240 size_t init_sz; | |
241 | |
242 if (TLABSize > 0) { | |
243 init_sz = MIN2(TLABSize / HeapWordSize, max_size()); | |
244 } else if (global_stats() == NULL) { | |
245 // Startup issue - main thread initialized before heap initialized. | |
246 init_sz = min_size(); | |
247 } else { | |
248 // Initial size is a function of the average number of allocating threads. | |
249 unsigned nof_threads = global_stats()->allocating_threads_avg(); | |
250 | |
251 init_sz = (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize) / | |
252 (nof_threads * target_refills()); | |
253 init_sz = align_object_size(init_sz); | |
254 init_sz = MIN2(MAX2(init_sz, min_size()), max_size()); | |
255 } | |
256 return init_sz; | |
257 } | |
258 | |
259 const size_t ThreadLocalAllocBuffer::max_size() { | |
260 | |
261 // TLABs can't be bigger than we can fill with a int[Integer.MAX_VALUE]. | |
262 // This restriction could be removed by enabling filling with multiple arrays. | |
263 // If we compute that the reasonable way as | |
264 // header_size + ((sizeof(jint) * max_jint) / HeapWordSize) | |
265 // we'll overflow on the multiply, so we do the divide first. | |
266 // We actually lose a little by dividing first, | |
267 // but that just makes the TLAB somewhat smaller than the biggest array, | |
268 // which is fine, since we'll be able to fill that. | |
269 | |
270 size_t unaligned_max_size = typeArrayOopDesc::header_size(T_INT) + | |
271 sizeof(jint) * | |
272 ((juint) max_jint / (size_t) HeapWordSize); | |
273 return align_size_down(unaligned_max_size, MinObjAlignment); | |
274 } | |
275 | |
276 void ThreadLocalAllocBuffer::print_stats(const char* tag) { | |
277 Thread* thrd = myThread(); | |
278 size_t waste = _gc_waste + _slow_refill_waste + _fast_refill_waste; | |
279 size_t alloc = _number_of_refills * _desired_size; | |
280 double waste_percent = alloc == 0 ? 0.0 : | |
281 100.0 * waste / alloc; | |
282 size_t tlab_used = Universe::heap()->tlab_capacity(thrd) - | |
283 Universe::heap()->unsafe_max_tlab_alloc(thrd); | |
284 gclog_or_tty->print("TLAB: %s thread: " INTPTR_FORMAT " [id: %2d]" | |
285 " desired_size: " SIZE_FORMAT "KB" | |
286 " slow allocs: %d refill waste: " SIZE_FORMAT "B" | |
287 " alloc:%8.5f %8.0fKB refills: %d waste %4.1f%% gc: %dB" | |
288 " slow: %dB fast: %dB\n", | |
289 tag, thrd, thrd->osthread()->thread_id(), | |
290 _desired_size / (K / HeapWordSize), | |
291 _slow_allocations, _refill_waste_limit * HeapWordSize, | |
292 _allocation_fraction.average(), | |
293 _allocation_fraction.average() * tlab_used / K, | |
294 _number_of_refills, waste_percent, | |
295 _gc_waste * HeapWordSize, | |
296 _slow_refill_waste * HeapWordSize, | |
297 _fast_refill_waste * HeapWordSize); | |
298 } | |
299 | |
300 void ThreadLocalAllocBuffer::verify() { | |
301 HeapWord* p = start(); | |
302 HeapWord* t = top(); | |
303 HeapWord* prev_p = NULL; | |
304 while (p < t) { | |
305 oop(p)->verify(); | |
306 prev_p = p; | |
307 p += oop(p)->size(); | |
308 } | |
309 guarantee(p == top(), "end of last object must match end of space"); | |
310 } | |
311 | |
312 Thread* ThreadLocalAllocBuffer::myThread() { | |
313 return (Thread*)(((char *)this) + | |
314 in_bytes(start_offset()) - | |
315 in_bytes(Thread::tlab_start_offset())); | |
316 } | |
317 | |
318 | |
319 GlobalTLABStats::GlobalTLABStats() : | |
320 _allocating_threads_avg(TLABAllocationWeight) { | |
321 | |
322 initialize(); | |
323 | |
324 _allocating_threads_avg.sample(1); // One allocating thread at startup | |
325 | |
326 if (UsePerfData) { | |
327 | |
328 EXCEPTION_MARK; | |
329 ResourceMark rm; | |
330 | |
331 char* cname = PerfDataManager::counter_name("tlab", "allocThreads"); | |
332 _perf_allocating_threads = | |
333 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_None, CHECK); | |
334 | |
335 cname = PerfDataManager::counter_name("tlab", "fills"); | |
336 _perf_total_refills = | |
337 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_None, CHECK); | |
338 | |
339 cname = PerfDataManager::counter_name("tlab", "maxFills"); | |
340 _perf_max_refills = | |
341 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_None, CHECK); | |
342 | |
343 cname = PerfDataManager::counter_name("tlab", "alloc"); | |
344 _perf_allocation = | |
345 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, CHECK); | |
346 | |
347 cname = PerfDataManager::counter_name("tlab", "gcWaste"); | |
348 _perf_gc_waste = | |
349 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, CHECK); | |
350 | |
351 cname = PerfDataManager::counter_name("tlab", "maxGcWaste"); | |
352 _perf_max_gc_waste = | |
353 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, CHECK); | |
354 | |
355 cname = PerfDataManager::counter_name("tlab", "slowWaste"); | |
356 _perf_slow_refill_waste = | |
357 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, CHECK); | |
358 | |
359 cname = PerfDataManager::counter_name("tlab", "maxSlowWaste"); | |
360 _perf_max_slow_refill_waste = | |
361 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, CHECK); | |
362 | |
363 cname = PerfDataManager::counter_name("tlab", "fastWaste"); | |
364 _perf_fast_refill_waste = | |
365 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, CHECK); | |
366 | |
367 cname = PerfDataManager::counter_name("tlab", "maxFastWaste"); | |
368 _perf_max_fast_refill_waste = | |
369 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, CHECK); | |
370 | |
371 cname = PerfDataManager::counter_name("tlab", "slowAlloc"); | |
372 _perf_slow_allocations = | |
373 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_None, CHECK); | |
374 | |
375 cname = PerfDataManager::counter_name("tlab", "maxSlowAlloc"); | |
376 _perf_max_slow_allocations = | |
377 PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_None, CHECK); | |
378 } | |
379 } | |
380 | |
381 void GlobalTLABStats::initialize() { | |
382 // Clear counters summarizing info from all threads | |
383 _allocating_threads = 0; | |
384 _total_refills = 0; | |
385 _max_refills = 0; | |
386 _total_allocation = 0; | |
387 _total_gc_waste = 0; | |
388 _max_gc_waste = 0; | |
389 _total_slow_refill_waste = 0; | |
390 _max_slow_refill_waste = 0; | |
391 _total_fast_refill_waste = 0; | |
392 _max_fast_refill_waste = 0; | |
393 _total_slow_allocations = 0; | |
394 _max_slow_allocations = 0; | |
395 } | |
396 | |
397 void GlobalTLABStats::publish() { | |
398 _allocating_threads_avg.sample(_allocating_threads); | |
399 if (UsePerfData) { | |
400 _perf_allocating_threads ->set_value(_allocating_threads); | |
401 _perf_total_refills ->set_value(_total_refills); | |
402 _perf_max_refills ->set_value(_max_refills); | |
403 _perf_allocation ->set_value(_total_allocation); | |
404 _perf_gc_waste ->set_value(_total_gc_waste); | |
405 _perf_max_gc_waste ->set_value(_max_gc_waste); | |
406 _perf_slow_refill_waste ->set_value(_total_slow_refill_waste); | |
407 _perf_max_slow_refill_waste->set_value(_max_slow_refill_waste); | |
408 _perf_fast_refill_waste ->set_value(_total_fast_refill_waste); | |
409 _perf_max_fast_refill_waste->set_value(_max_fast_refill_waste); | |
410 _perf_slow_allocations ->set_value(_total_slow_allocations); | |
411 _perf_max_slow_allocations ->set_value(_max_slow_allocations); | |
412 } | |
413 } | |
414 | |
415 void GlobalTLABStats::print() { | |
416 size_t waste = _total_gc_waste + _total_slow_refill_waste + _total_fast_refill_waste; | |
417 double waste_percent = _total_allocation == 0 ? 0.0 : | |
418 100.0 * waste / _total_allocation; | |
419 gclog_or_tty->print("TLAB totals: thrds: %d refills: %d max: %d" | |
420 " slow allocs: %d max %d waste: %4.1f%%" | |
421 " gc: " SIZE_FORMAT "B max: " SIZE_FORMAT "B" | |
422 " slow: " SIZE_FORMAT "B max: " SIZE_FORMAT "B" | |
423 " fast: " SIZE_FORMAT "B max: " SIZE_FORMAT "B\n", | |
424 _allocating_threads, | |
425 _total_refills, _max_refills, | |
426 _total_slow_allocations, _max_slow_allocations, | |
427 waste_percent, | |
428 _total_gc_waste * HeapWordSize, | |
429 _max_gc_waste * HeapWordSize, | |
430 _total_slow_refill_waste * HeapWordSize, | |
431 _max_slow_refill_waste * HeapWordSize, | |
432 _total_fast_refill_waste * HeapWordSize, | |
433 _max_fast_refill_waste * HeapWordSize); | |
434 } |