src/share/vm/memory/threadLocalAllocBuffer.hpp

Wed, 27 Apr 2016 01:25:04 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:25:04 +0800
changeset 0
f90c822e73f8
child 6876
710a3c8b516e
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/
changeset: 6782:28b50d07f6f8
tag: jdk8u25-b17

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #ifndef SHARE_VM_MEMORY_THREADLOCALALLOCBUFFER_HPP
aoqi@0 26 #define SHARE_VM_MEMORY_THREADLOCALALLOCBUFFER_HPP
aoqi@0 27
aoqi@0 28 #include "gc_implementation/shared/gcUtil.hpp"
aoqi@0 29 #include "oops/typeArrayOop.hpp"
aoqi@0 30 #include "runtime/perfData.hpp"
aoqi@0 31
aoqi@0 32 class GlobalTLABStats;
aoqi@0 33
aoqi@0 34 // ThreadLocalAllocBuffer: a descriptor for thread-local storage used by
aoqi@0 35 // the threads for allocation.
aoqi@0 36 // It is thread-private at any time, but maybe multiplexed over
aoqi@0 37 // time across multiple threads. The park()/unpark() pair is
aoqi@0 38 // used to make it available for such multiplexing.
aoqi@0 39 class ThreadLocalAllocBuffer: public CHeapObj<mtThread> {
aoqi@0 40 friend class VMStructs;
aoqi@0 41 private:
aoqi@0 42 HeapWord* _start; // address of TLAB
aoqi@0 43 HeapWord* _top; // address after last allocation
aoqi@0 44 HeapWord* _pf_top; // allocation prefetch watermark
aoqi@0 45 HeapWord* _end; // allocation end (excluding alignment_reserve)
aoqi@0 46 size_t _desired_size; // desired size (including alignment_reserve)
aoqi@0 47 size_t _refill_waste_limit; // hold onto tlab if free() is larger than this
aoqi@0 48 size_t _allocated_before_last_gc; // total bytes allocated up until the last gc
aoqi@0 49
aoqi@0 50 static size_t _max_size; // maximum size of any TLAB
aoqi@0 51 static unsigned _target_refills; // expected number of refills between GCs
aoqi@0 52
aoqi@0 53 unsigned _number_of_refills;
aoqi@0 54 unsigned _fast_refill_waste;
aoqi@0 55 unsigned _slow_refill_waste;
aoqi@0 56 unsigned _gc_waste;
aoqi@0 57 unsigned _slow_allocations;
aoqi@0 58
aoqi@0 59 AdaptiveWeightedAverage _allocation_fraction; // fraction of eden allocated in tlabs
aoqi@0 60
aoqi@0 61 void accumulate_statistics();
aoqi@0 62 void initialize_statistics();
aoqi@0 63
aoqi@0 64 void set_start(HeapWord* start) { _start = start; }
aoqi@0 65 void set_end(HeapWord* end) { _end = end; }
aoqi@0 66 void set_top(HeapWord* top) { _top = top; }
aoqi@0 67 void set_pf_top(HeapWord* pf_top) { _pf_top = pf_top; }
aoqi@0 68 void set_desired_size(size_t desired_size) { _desired_size = desired_size; }
aoqi@0 69 void set_refill_waste_limit(size_t waste) { _refill_waste_limit = waste; }
aoqi@0 70
aoqi@0 71 size_t initial_refill_waste_limit() { return desired_size() / TLABRefillWasteFraction; }
aoqi@0 72
aoqi@0 73 static int target_refills() { return _target_refills; }
aoqi@0 74 size_t initial_desired_size();
aoqi@0 75
aoqi@0 76 size_t remaining() const { return end() == NULL ? 0 : pointer_delta(hard_end(), top()); }
aoqi@0 77
aoqi@0 78 // Make parsable and release it.
aoqi@0 79 void reset();
aoqi@0 80
aoqi@0 81 // Resize based on amount of allocation, etc.
aoqi@0 82 void resize();
aoqi@0 83
aoqi@0 84 void invariants() const { assert(top() >= start() && top() <= end(), "invalid tlab"); }
aoqi@0 85
aoqi@0 86 void initialize(HeapWord* start, HeapWord* top, HeapWord* end);
aoqi@0 87
aoqi@0 88 void print_stats(const char* tag);
aoqi@0 89
aoqi@0 90 Thread* myThread();
aoqi@0 91
aoqi@0 92 // statistics
aoqi@0 93
aoqi@0 94 int number_of_refills() const { return _number_of_refills; }
aoqi@0 95 int fast_refill_waste() const { return _fast_refill_waste; }
aoqi@0 96 int slow_refill_waste() const { return _slow_refill_waste; }
aoqi@0 97 int gc_waste() const { return _gc_waste; }
aoqi@0 98 int slow_allocations() const { return _slow_allocations; }
aoqi@0 99
aoqi@0 100 static GlobalTLABStats* _global_stats;
aoqi@0 101 static GlobalTLABStats* global_stats() { return _global_stats; }
aoqi@0 102
aoqi@0 103 public:
aoqi@0 104 ThreadLocalAllocBuffer() : _allocation_fraction(TLABAllocationWeight), _allocated_before_last_gc(0) {
aoqi@0 105 // do nothing. tlabs must be inited by initialize() calls
aoqi@0 106 }
aoqi@0 107
aoqi@0 108 static const size_t min_size() { return align_object_size(MinTLABSize / HeapWordSize); }
aoqi@0 109 static const size_t max_size() { assert(_max_size != 0, "max_size not set up"); return _max_size; }
aoqi@0 110 static void set_max_size(size_t max_size) { _max_size = max_size; }
aoqi@0 111
aoqi@0 112 HeapWord* start() const { return _start; }
aoqi@0 113 HeapWord* end() const { return _end; }
aoqi@0 114 HeapWord* hard_end() const { return _end + alignment_reserve(); }
aoqi@0 115 HeapWord* top() const { return _top; }
aoqi@0 116 HeapWord* pf_top() const { return _pf_top; }
aoqi@0 117 size_t desired_size() const { return _desired_size; }
aoqi@0 118 size_t used() const { return pointer_delta(top(), start()); }
aoqi@0 119 size_t used_bytes() const { return pointer_delta(top(), start(), 1); }
aoqi@0 120 size_t free() const { return pointer_delta(end(), top()); }
aoqi@0 121 // Don't discard tlab if remaining space is larger than this.
aoqi@0 122 size_t refill_waste_limit() const { return _refill_waste_limit; }
aoqi@0 123
aoqi@0 124 // Allocate size HeapWords. The memory is NOT initialized to zero.
aoqi@0 125 inline HeapWord* allocate(size_t size);
aoqi@0 126
aoqi@0 127 // Reserve space at the end of TLAB
aoqi@0 128 static size_t end_reserve() {
aoqi@0 129 int reserve_size = typeArrayOopDesc::header_size(T_INT);
aoqi@0 130 return MAX2(reserve_size, VM_Version::reserve_for_allocation_prefetch());
aoqi@0 131 }
aoqi@0 132 static size_t alignment_reserve() { return align_object_size(end_reserve()); }
aoqi@0 133 static size_t alignment_reserve_in_bytes() { return alignment_reserve() * HeapWordSize; }
aoqi@0 134
aoqi@0 135 // Return tlab size or remaining space in eden such that the
aoqi@0 136 // space is large enough to hold obj_size and necessary fill space.
aoqi@0 137 // Otherwise return 0;
aoqi@0 138 inline size_t compute_size(size_t obj_size);
aoqi@0 139
aoqi@0 140 // Record slow allocation
aoqi@0 141 inline void record_slow_allocation(size_t obj_size);
aoqi@0 142
aoqi@0 143 // Initialization at startup
aoqi@0 144 static void startup_initialization();
aoqi@0 145
aoqi@0 146 // Make an in-use tlab parsable, optionally also retiring it.
aoqi@0 147 void make_parsable(bool retire);
aoqi@0 148
aoqi@0 149 // Retire in-use tlab before allocation of a new tlab
aoqi@0 150 void clear_before_allocation();
aoqi@0 151
aoqi@0 152 // Accumulate statistics across all tlabs before gc
aoqi@0 153 static void accumulate_statistics_before_gc();
aoqi@0 154
aoqi@0 155 // Resize tlabs for all threads
aoqi@0 156 static void resize_all_tlabs();
aoqi@0 157
aoqi@0 158 void fill(HeapWord* start, HeapWord* top, size_t new_size);
aoqi@0 159 void initialize();
aoqi@0 160
aoqi@0 161 static size_t refill_waste_limit_increment() { return TLABWasteIncrement; }
aoqi@0 162
aoqi@0 163 // Code generation support
aoqi@0 164 static ByteSize start_offset() { return byte_offset_of(ThreadLocalAllocBuffer, _start); }
aoqi@0 165 static ByteSize end_offset() { return byte_offset_of(ThreadLocalAllocBuffer, _end ); }
aoqi@0 166 static ByteSize top_offset() { return byte_offset_of(ThreadLocalAllocBuffer, _top ); }
aoqi@0 167 static ByteSize pf_top_offset() { return byte_offset_of(ThreadLocalAllocBuffer, _pf_top ); }
aoqi@0 168 static ByteSize size_offset() { return byte_offset_of(ThreadLocalAllocBuffer, _desired_size ); }
aoqi@0 169 static ByteSize refill_waste_limit_offset() { return byte_offset_of(ThreadLocalAllocBuffer, _refill_waste_limit ); }
aoqi@0 170
aoqi@0 171 static ByteSize number_of_refills_offset() { return byte_offset_of(ThreadLocalAllocBuffer, _number_of_refills ); }
aoqi@0 172 static ByteSize fast_refill_waste_offset() { return byte_offset_of(ThreadLocalAllocBuffer, _fast_refill_waste ); }
aoqi@0 173 static ByteSize slow_allocations_offset() { return byte_offset_of(ThreadLocalAllocBuffer, _slow_allocations ); }
aoqi@0 174
aoqi@0 175 void verify();
aoqi@0 176 };
aoqi@0 177
aoqi@0 178 class GlobalTLABStats: public CHeapObj<mtThread> {
aoqi@0 179 private:
aoqi@0 180
aoqi@0 181 // Accumulate perfdata in private variables because
aoqi@0 182 // PerfData should be write-only for security reasons
aoqi@0 183 // (see perfData.hpp)
aoqi@0 184 unsigned _allocating_threads;
aoqi@0 185 unsigned _total_refills;
aoqi@0 186 unsigned _max_refills;
aoqi@0 187 size_t _total_allocation;
aoqi@0 188 size_t _total_gc_waste;
aoqi@0 189 size_t _max_gc_waste;
aoqi@0 190 size_t _total_slow_refill_waste;
aoqi@0 191 size_t _max_slow_refill_waste;
aoqi@0 192 size_t _total_fast_refill_waste;
aoqi@0 193 size_t _max_fast_refill_waste;
aoqi@0 194 unsigned _total_slow_allocations;
aoqi@0 195 unsigned _max_slow_allocations;
aoqi@0 196
aoqi@0 197 PerfVariable* _perf_allocating_threads;
aoqi@0 198 PerfVariable* _perf_total_refills;
aoqi@0 199 PerfVariable* _perf_max_refills;
aoqi@0 200 PerfVariable* _perf_allocation;
aoqi@0 201 PerfVariable* _perf_gc_waste;
aoqi@0 202 PerfVariable* _perf_max_gc_waste;
aoqi@0 203 PerfVariable* _perf_slow_refill_waste;
aoqi@0 204 PerfVariable* _perf_max_slow_refill_waste;
aoqi@0 205 PerfVariable* _perf_fast_refill_waste;
aoqi@0 206 PerfVariable* _perf_max_fast_refill_waste;
aoqi@0 207 PerfVariable* _perf_slow_allocations;
aoqi@0 208 PerfVariable* _perf_max_slow_allocations;
aoqi@0 209
aoqi@0 210 AdaptiveWeightedAverage _allocating_threads_avg;
aoqi@0 211
aoqi@0 212 public:
aoqi@0 213 GlobalTLABStats();
aoqi@0 214
aoqi@0 215 // Initialize all counters
aoqi@0 216 void initialize();
aoqi@0 217
aoqi@0 218 // Write all perf counters to the perf_counters
aoqi@0 219 void publish();
aoqi@0 220
aoqi@0 221 void print();
aoqi@0 222
aoqi@0 223 // Accessors
aoqi@0 224 unsigned allocating_threads_avg() {
aoqi@0 225 return MAX2((unsigned)(_allocating_threads_avg.average() + 0.5), 1U);
aoqi@0 226 }
aoqi@0 227
aoqi@0 228 size_t allocation() {
aoqi@0 229 return _total_allocation;
aoqi@0 230 }
aoqi@0 231
aoqi@0 232 // Update methods
aoqi@0 233
aoqi@0 234 void update_allocating_threads() {
aoqi@0 235 _allocating_threads++;
aoqi@0 236 }
aoqi@0 237 void update_number_of_refills(unsigned value) {
aoqi@0 238 _total_refills += value;
aoqi@0 239 _max_refills = MAX2(_max_refills, value);
aoqi@0 240 }
aoqi@0 241 void update_allocation(size_t value) {
aoqi@0 242 _total_allocation += value;
aoqi@0 243 }
aoqi@0 244 void update_gc_waste(size_t value) {
aoqi@0 245 _total_gc_waste += value;
aoqi@0 246 _max_gc_waste = MAX2(_max_gc_waste, value);
aoqi@0 247 }
aoqi@0 248 void update_fast_refill_waste(size_t value) {
aoqi@0 249 _total_fast_refill_waste += value;
aoqi@0 250 _max_fast_refill_waste = MAX2(_max_fast_refill_waste, value);
aoqi@0 251 }
aoqi@0 252 void update_slow_refill_waste(size_t value) {
aoqi@0 253 _total_slow_refill_waste += value;
aoqi@0 254 _max_slow_refill_waste = MAX2(_max_slow_refill_waste, value);
aoqi@0 255 }
aoqi@0 256 void update_slow_allocations(unsigned value) {
aoqi@0 257 _total_slow_allocations += value;
aoqi@0 258 _max_slow_allocations = MAX2(_max_slow_allocations, value);
aoqi@0 259 }
aoqi@0 260 };
aoqi@0 261
aoqi@0 262 #endif // SHARE_VM_MEMORY_THREADLOCALALLOCBUFFER_HPP

mercurial