< prev index next >

src/share/vm/gc/shared/threadLocalAllocBuffer.cpp

Print this page
rev 12310 : [mq]: gcinterface.patch


  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()) {
  52     thread->tlab().accumulate_statistics();
  53     thread->tlab().initialize_statistics();
  54   }
  55 
  56   // Publish new stats if some allocation occurred.
  57   if (global_stats()->allocation() != 0) {
  58     global_stats()->publish();
  59     global_stats()->print();
  60   }
  61 }
  62 
  63 void ThreadLocalAllocBuffer::accumulate_statistics() {
  64   Thread* thread = myThread();
  65   size_t capacity = Universe::heap()->tlab_capacity(thread);
  66   size_t used     = Universe::heap()->tlab_used(thread);
  67 
  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;
  72 
  73   print_stats("gc");
  74 
  75   if (_number_of_refills > 0) {
  76     // Update allocation history if a reasonable amount of eden was allocated.
  77     bool update_allocation_history = used > 0.5 * capacity;
  78 
  79     if (update_allocation_history) {
  80       // Average the fraction of eden allocated in a tlab by this
  81       // thread for use in the next resize operation.
  82       // _gc_waste is not subtracted because it's included in
  83       // "used".
  84       // The result can be larger than 1.0 due to direct to old allocations.
  85       // These allocations should ideally not be counted but since it is not possible
  86       // to filter them out here we just cap the fraction to be at most 1.0.


 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));
 144   size_t new_size = alloc / _target_refills;
 145 
 146   new_size = MIN2(MAX2(new_size, min_size()), max_size());
 147 
 148   size_t aligned_new_size = align_object_size(new_size);
 149 
 150   log_trace(gc, tlab)("TLAB new size: thread: " INTPTR_FORMAT " [id: %2d]"
 151                       " refills %d  alloc: %8.6f desired_size: " SIZE_FORMAT " -> " SIZE_FORMAT,
 152                       p2i(myThread()), myThread()->osthread()->thread_id(),
 153                       _target_refills, _allocation_fraction.average(), desired_size(), aligned_new_size);
 154 
 155   set_desired_size(aligned_new_size);
 156   set_refill_waste_limit(initial_refill_waste_limit());
 157 }
 158 
 159 void ThreadLocalAllocBuffer::initialize_statistics() {
 160     _number_of_refills = 0;
 161     _fast_refill_waste = 0;
 162     _slow_refill_waste = 0;
 163     _gc_waste          = 0;


 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 
 207   initialize_statistics();
 208 }
 209 
 210 void ThreadLocalAllocBuffer::startup_initialization() {
 211 
 212   // Assuming each thread's active tlab is, on average,
 213   // 1/2 full at a GC
 214   _target_refills = 100 / (2 * TLABWasteTargetPercent);
 215   _target_refills = MAX2(_target_refills, (unsigned)1U);
 216 
 217   _global_stats = new GlobalTLABStats();
 218 
 219 #ifdef COMPILER2
 220   // If the C2 compiler is present, extra space is needed at the end of


 239 #endif
 240 
 241   // During jvm startup, the main (primordial) thread is initialized
 242   // before the heap is initialized.  So reinitialize it now.
 243   guarantee(Thread::current()->is_Java_thread(), "tlab initialization thread not Java thread");
 244   Thread::current()->tlab().initialize();
 245 
 246   log_develop_trace(gc, tlab)("TLAB min: " SIZE_FORMAT " initial: " SIZE_FORMAT " max: " SIZE_FORMAT,
 247                                min_size(), Thread::current()->tlab().initial_desired_size(), max_size());
 248 }
 249 
 250 size_t ThreadLocalAllocBuffer::initial_desired_size() {
 251   size_t init_sz = 0;
 252 
 253   if (TLABSize > 0) {
 254     init_sz = TLABSize / HeapWordSize;
 255   } else if (global_stats() != NULL) {
 256     // Initial size is a function of the average number of allocating threads.
 257     unsigned nof_threads = global_stats()->allocating_threads_avg();
 258 
 259     init_sz  = (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize) /
 260                       (nof_threads * target_refills());
 261     init_sz = align_object_size(init_sz);
 262   }
 263   init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
 264   return init_sz;
 265 }
 266 
 267 void ThreadLocalAllocBuffer::print_stats(const char* tag) {
 268   Log(gc, tlab) log;
 269   if (!log.is_trace()) {
 270     return;
 271   }
 272 
 273   Thread* thrd = myThread();
 274   size_t waste = _gc_waste + _slow_refill_waste + _fast_refill_waste;
 275   size_t alloc = _number_of_refills * _desired_size;
 276   double waste_percent = alloc == 0 ? 0.0 :
 277                       100.0 * waste / alloc;
 278   size_t tlab_used  = Universe::heap()->tlab_used(thrd);
 279   log.trace("TLAB: %s thread: " INTPTR_FORMAT " [id: %2d]"
 280             " desired_size: " SIZE_FORMAT "KB"
 281             " slow allocs: %d  refill waste: " SIZE_FORMAT "B"
 282             " alloc:%8.5f %8.0fKB refills: %d waste %4.1f%% gc: %dB"
 283             " slow: %dB fast: %dB",
 284             tag, p2i(thrd), thrd->osthread()->thread_id(),
 285             _desired_size / (K / HeapWordSize),
 286             _slow_allocations, _refill_waste_limit * HeapWordSize,
 287             _allocation_fraction.average(),
 288             _allocation_fraction.average() * tlab_used / K,
 289             _number_of_refills, waste_percent,
 290             _gc_waste * HeapWordSize,
 291             _slow_refill_waste * HeapWordSize,
 292             _fast_refill_waste * HeapWordSize);
 293 }
 294 
 295 void ThreadLocalAllocBuffer::verify() {
 296   HeapWord* p = start();
 297   HeapWord* t = top();
 298   HeapWord* prev_p = NULL;




  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()) {
  52     thread->tlab().accumulate_statistics();
  53     thread->tlab().initialize_statistics();
  54   }
  55 
  56   // Publish new stats if some allocation occurred.
  57   if (global_stats()->allocation() != 0) {
  58     global_stats()->publish();
  59     global_stats()->print();
  60   }
  61 }
  62 
  63 void ThreadLocalAllocBuffer::accumulate_statistics() {
  64   Thread* thread = myThread();
  65   size_t capacity = GC::gc()->heap()->tlab_capacity(thread);
  66   size_t used     = GC::gc()->heap()->tlab_used(thread);
  67 
  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;
  72 
  73   print_stats("gc");
  74 
  75   if (_number_of_refills > 0) {
  76     // Update allocation history if a reasonable amount of eden was allocated.
  77     bool update_allocation_history = used > 0.5 * capacity;
  78 
  79     if (update_allocation_history) {
  80       // Average the fraction of eden allocated in a tlab by this
  81       // thread for use in the next resize operation.
  82       // _gc_waste is not subtracted because it's included in
  83       // "used".
  84       // The result can be larger than 1.0 due to direct to old allocations.
  85       // These allocations should ideally not be counted but since it is not possible
  86       // to filter them out here we just cap the fraction to be at most 1.0.


 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                           (GC::gc()->heap()->tlab_capacity(myThread()) / HeapWordSize));
 144   size_t new_size = alloc / _target_refills;
 145 
 146   new_size = MIN2(MAX2(new_size, min_size()), max_size());
 147 
 148   size_t aligned_new_size = align_object_size(new_size);
 149 
 150   log_trace(gc, tlab)("TLAB new size: thread: " INTPTR_FORMAT " [id: %2d]"
 151                       " refills %d  alloc: %8.6f desired_size: " SIZE_FORMAT " -> " SIZE_FORMAT,
 152                       p2i(myThread()), myThread()->osthread()->thread_id(),
 153                       _target_refills, _allocation_fraction.average(), desired_size(), aligned_new_size);
 154 
 155   set_desired_size(aligned_new_size);
 156   set_refill_waste_limit(initial_refill_waste_limit());
 157 }
 158 
 159 void ThreadLocalAllocBuffer::initialize_statistics() {
 160     _number_of_refills = 0;
 161     _fast_refill_waste = 0;
 162     _slow_refill_waste = 0;
 163     _gc_waste          = 0;


 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 (GC::gc()->heap() != NULL) {
 200     size_t capacity   = GC::gc()->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 
 207   initialize_statistics();
 208 }
 209 
 210 void ThreadLocalAllocBuffer::startup_initialization() {
 211 
 212   // Assuming each thread's active tlab is, on average,
 213   // 1/2 full at a GC
 214   _target_refills = 100 / (2 * TLABWasteTargetPercent);
 215   _target_refills = MAX2(_target_refills, (unsigned)1U);
 216 
 217   _global_stats = new GlobalTLABStats();
 218 
 219 #ifdef COMPILER2
 220   // If the C2 compiler is present, extra space is needed at the end of


 239 #endif
 240 
 241   // During jvm startup, the main (primordial) thread is initialized
 242   // before the heap is initialized.  So reinitialize it now.
 243   guarantee(Thread::current()->is_Java_thread(), "tlab initialization thread not Java thread");
 244   Thread::current()->tlab().initialize();
 245 
 246   log_develop_trace(gc, tlab)("TLAB min: " SIZE_FORMAT " initial: " SIZE_FORMAT " max: " SIZE_FORMAT,
 247                                min_size(), Thread::current()->tlab().initial_desired_size(), max_size());
 248 }
 249 
 250 size_t ThreadLocalAllocBuffer::initial_desired_size() {
 251   size_t init_sz = 0;
 252 
 253   if (TLABSize > 0) {
 254     init_sz = TLABSize / HeapWordSize;
 255   } else if (global_stats() != NULL) {
 256     // Initial size is a function of the average number of allocating threads.
 257     unsigned nof_threads = global_stats()->allocating_threads_avg();
 258 
 259     init_sz  = (GC::gc()->heap()->tlab_capacity(myThread()) / HeapWordSize) /
 260                       (nof_threads * target_refills());
 261     init_sz = align_object_size(init_sz);
 262   }
 263   init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
 264   return init_sz;
 265 }
 266 
 267 void ThreadLocalAllocBuffer::print_stats(const char* tag) {
 268   Log(gc, tlab) log;
 269   if (!log.is_trace()) {
 270     return;
 271   }
 272 
 273   Thread* thrd = myThread();
 274   size_t waste = _gc_waste + _slow_refill_waste + _fast_refill_waste;
 275   size_t alloc = _number_of_refills * _desired_size;
 276   double waste_percent = alloc == 0 ? 0.0 :
 277                       100.0 * waste / alloc;
 278   size_t tlab_used  = GC::gc()->heap()->tlab_used(thrd);
 279   log.trace("TLAB: %s thread: " INTPTR_FORMAT " [id: %2d]"
 280             " desired_size: " SIZE_FORMAT "KB"
 281             " slow allocs: %d  refill waste: " SIZE_FORMAT "B"
 282             " alloc:%8.5f %8.0fKB refills: %d waste %4.1f%% gc: %dB"
 283             " slow: %dB fast: %dB",
 284             tag, p2i(thrd), thrd->osthread()->thread_id(),
 285             _desired_size / (K / HeapWordSize),
 286             _slow_allocations, _refill_waste_limit * HeapWordSize,
 287             _allocation_fraction.average(),
 288             _allocation_fraction.average() * tlab_used / K,
 289             _number_of_refills, waste_percent,
 290             _gc_waste * HeapWordSize,
 291             _slow_refill_waste * HeapWordSize,
 292             _fast_refill_waste * HeapWordSize);
 293 }
 294 
 295 void ThreadLocalAllocBuffer::verify() {
 296   HeapWord* p = start();
 297   HeapWord* t = top();
 298   HeapWord* prev_p = NULL;


< prev index next >