/** * 根据统计信息调整当前线程的本地分配缓冲区的基准大小 */ void ThreadLocalAllocBuffer::resize() { if (ResizeTLAB) { //允许调整线程的本地分配缓冲区大小 // Compute the next tlab size using expected allocation amount size_t alloc = (size_t)(_allocation_fraction.average() * (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize)); size_t new_size = alloc / _target_refills; //根据本地分配缓冲区大小允许的最大值/最小值来调整缓冲区的新大小 new_size = MIN2(MAX2(new_size, min_size()), max_size()); //内存对齐后的大小 size_t aligned_new_size = align_object_size(new_size); if (PrintTLAB && Verbose) { gclog_or_tty->print("TLAB new size: thread: " INTPTR_FORMAT " [id: %2d]" " refills %d alloc: %8.6f desired_size: " SIZE_FORMAT " -> " SIZE_FORMAT "\n", myThread(), myThread()->osthread()->thread_id(), _target_refills, _allocation_fraction.average(), desired_size(), aligned_new_size); } set_desired_size(aligned_new_size); set_refill_waste_limit(initial_refill_waste_limit()); } }
void ThreadLocalAllocBuffer::fill(HeapWord* start, HeapWord* top, size_t new_size) { _number_of_refills++; if (PrintTLAB && Verbose) { print_stats("fill"); } assert(top <= start + new_size - alignment_reserve(), "size too small"); initialize(start, top, start + new_size - alignment_reserve()); // Reset amount of internal fragmentation set_refill_waste_limit(initial_refill_waste_limit()); }
void ThreadLocalAllocBuffer::record_slow_allocation(size_t obj_size) { // Raise size required to bypass TLAB next time. Why? Else there's // a risk that a thread that repeatedly allocates objects of one // size will get stuck on this slow path. set_refill_waste_limit(refill_waste_limit() + refill_waste_limit_increment()); _slow_allocations++; if (PrintTLAB && Verbose) { Thread* thrd = myThread(); gclog_or_tty->print("TLAB: %s thread: "INTPTR_FORMAT" [id: %2d]" " obj: "SIZE_FORMAT " free: "SIZE_FORMAT " waste: "SIZE_FORMAT"\n", "slow", thrd, thrd->osthread()->thread_id(), obj_size, free(), refill_waste_limit()); } }
void ThreadLocalAllocBuffer::resize() { // Compute the next tlab size using expected allocation amount assert(ResizeTLAB, "Should not call this otherwise"); size_t alloc = (size_t)(_allocation_fraction.average() * (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize)); size_t new_size = alloc / _target_refills; new_size = MIN2(MAX2(new_size, min_size()), max_size()); size_t aligned_new_size = align_object_size(new_size); if (PrintTLAB && Verbose) { gclog_or_tty->print("TLAB new size: thread: " INTPTR_FORMAT " [id: %2d]" " refills %d alloc: %8.6f desired_size: " SIZE_FORMAT " -> " SIZE_FORMAT "\n", p2i(myThread()), myThread()->osthread()->thread_id(), _target_refills, _allocation_fraction.average(), desired_size(), aligned_new_size); } set_desired_size(aligned_new_size); set_refill_waste_limit(initial_refill_waste_limit()); }
void ThreadLocalAllocBuffer::initialize() { initialize(NULL, // start NULL, // top NULL); // end set_desired_size(initial_desired_size()); // Following check is needed because at startup the main (primordial) // thread is initialized before the heap is. The initialization for // this thread is redone in startup_initialization below. if (Universe::heap() != NULL) { size_t capacity = Universe::heap()->tlab_capacity(myThread()) / HeapWordSize; double alloc_frac = desired_size() * target_refills() / (double) capacity; _allocation_fraction.sample(alloc_frac); } set_refill_waste_limit(initial_refill_waste_limit()); initialize_statistics(); }