24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "memory/allocation.inline.hpp" |
26 #include "memory/allocation.inline.hpp" |
27 #include "gc/g1/g1EvacStats.hpp" |
27 #include "gc/g1/g1EvacStats.hpp" |
28 #include "gc/shared/gcId.hpp" |
28 #include "gc/shared/gcId.hpp" |
|
29 #include "logging/log.hpp" |
29 #include "trace/tracing.hpp" |
30 #include "trace/tracing.hpp" |
30 |
31 |
31 void G1EvacStats::adjust_desired_plab_sz() { |
32 void G1EvacStats::adjust_desired_plab_sz() { |
32 if (PrintPLAB) { |
33 if (!ResizePLAB) { |
33 gclog_or_tty->print(" (allocated = " SIZE_FORMAT " wasted = " SIZE_FORMAT " " |
34 log_debug(gc, plab)(" (allocated = " SIZE_FORMAT " wasted = " SIZE_FORMAT " " |
34 "unused = " SIZE_FORMAT " used = " SIZE_FORMAT " " |
35 "unused = " SIZE_FORMAT " used = " SIZE_FORMAT " " |
35 "undo_waste = " SIZE_FORMAT " region_end_waste = " SIZE_FORMAT " " |
36 "undo_waste = " SIZE_FORMAT " region_end_waste = " SIZE_FORMAT " " |
36 "regions filled = %u direct_allocated = " SIZE_FORMAT " " |
37 "regions filled = %u direct_allocated = " SIZE_FORMAT " " |
37 "failure_used = " SIZE_FORMAT " failure_waste = " SIZE_FORMAT ") ", |
38 "failure_used = " SIZE_FORMAT " failure_waste = " SIZE_FORMAT ") ", |
38 _allocated, _wasted, _unused, used(), _undo_wasted, _region_end_waste, |
39 _allocated, _wasted, _unused, used(), _undo_wasted, _region_end_waste, |
39 _regions_filled, _direct_allocated, _failure_used, _failure_waste); |
40 _regions_filled, _direct_allocated, _failure_used, _failure_waste); |
|
41 // Clear accumulators for next round. |
|
42 reset(); |
|
43 return; |
40 } |
44 } |
41 |
45 |
42 if (ResizePLAB) { |
46 assert(is_object_aligned(max_size()) && min_size() <= max_size(), |
|
47 "PLAB clipping computation may be incorrect"); |
43 |
48 |
44 assert(is_object_aligned(max_size()) && min_size() <= max_size(), |
49 if (_allocated == 0) { |
45 "PLAB clipping computation may be incorrect"); |
50 assert((_unused == 0), |
|
51 "Inconsistency in PLAB stats: " |
|
52 "_allocated: " SIZE_FORMAT ", " |
|
53 "_wasted: " SIZE_FORMAT ", " |
|
54 "_region_end_waste: " SIZE_FORMAT ", " |
|
55 "_unused: " SIZE_FORMAT ", " |
|
56 "_used : " SIZE_FORMAT, |
|
57 _allocated, _wasted, _region_end_waste, _unused, used()); |
|
58 _allocated = 1; |
|
59 } |
|
60 // The size of the PLAB caps the amount of space that can be wasted at the |
|
61 // end of the collection. In the worst case the last PLAB could be completely |
|
62 // empty. |
|
63 // This allows us to calculate the new PLAB size to achieve the |
|
64 // TargetPLABWastePct given the latest memory usage and that the last buffer |
|
65 // will be G1LastPLABAverageOccupancy full. |
|
66 // |
|
67 // E.g. assume that if in the current GC 100 words were allocated and a |
|
68 // TargetPLABWastePct of 10 had been set. |
|
69 // |
|
70 // So we could waste up to 10 words to meet that percentage. Given that we |
|
71 // also assume that that buffer is typically half-full, the new desired PLAB |
|
72 // size is set to 20 words. |
|
73 // |
|
74 // The amount of allocation performed should be independent of the number of |
|
75 // threads, so should the maximum waste we can spend in total. So if |
|
76 // we used n threads to allocate, each of them can spend maximum waste/n words in |
|
77 // a first rough approximation. The number of threads only comes into play later |
|
78 // when actually retrieving the actual desired PLAB size. |
|
79 // |
|
80 // After calculating this optimal PLAB size the algorithm applies the usual |
|
81 // exponential decaying average over this value to guess the next PLAB size. |
|
82 // |
|
83 // We account region end waste fully to PLAB allocation (in the calculation of |
|
84 // what we consider as "used_for_waste_calculation" below). This is not |
|
85 // completely fair, but is a conservative assumption because PLABs may be sized |
|
86 // flexibly while we cannot adjust inline allocations. |
|
87 // Allocation during GC will try to minimize region end waste so this impact |
|
88 // should be minimal. |
|
89 // |
|
90 // We need to cover overflow when calculating the amount of space actually used |
|
91 // by objects in PLABs when subtracting the region end waste. |
|
92 // Region end waste may be higher than actual allocation. This may occur if many |
|
93 // threads do not allocate anything but a few rather large objects. In this |
|
94 // degenerate case the PLAB size would simply quickly tend to minimum PLAB size, |
|
95 // which is an okay reaction. |
|
96 size_t const used_for_waste_calculation = used() > _region_end_waste ? used() - _region_end_waste : 0; |
46 |
97 |
47 if (_allocated == 0) { |
98 size_t const total_waste_allowed = used_for_waste_calculation * TargetPLABWastePct; |
48 assert((_unused == 0), |
99 size_t const cur_plab_sz = (size_t)((double)total_waste_allowed / G1LastPLABAverageOccupancy); |
49 "Inconsistency in PLAB stats: " |
100 // Take historical weighted average |
50 "_allocated: " SIZE_FORMAT ", " |
101 _filter.sample(cur_plab_sz); |
51 "_wasted: " SIZE_FORMAT ", " |
102 // Clip from above and below, and align to object boundary |
52 "_region_end_waste: " SIZE_FORMAT ", " |
103 size_t plab_sz; |
53 "_unused: " SIZE_FORMAT ", " |
104 plab_sz = MAX2(min_size(), (size_t)_filter.average()); |
54 "_used : " SIZE_FORMAT, |
105 plab_sz = MIN2(max_size(), plab_sz); |
55 _allocated, _wasted, _region_end_waste, _unused, used()); |
106 plab_sz = align_object_size(plab_sz); |
56 _allocated = 1; |
107 // Latch the result |
57 } |
108 _desired_net_plab_sz = plab_sz; |
58 // The size of the PLAB caps the amount of space that can be wasted at the |
|
59 // end of the collection. In the worst case the last PLAB could be completely |
|
60 // empty. |
|
61 // This allows us to calculate the new PLAB size to achieve the |
|
62 // TargetPLABWastePct given the latest memory usage and that the last buffer |
|
63 // will be G1LastPLABAverageOccupancy full. |
|
64 // |
|
65 // E.g. assume that if in the current GC 100 words were allocated and a |
|
66 // TargetPLABWastePct of 10 had been set. |
|
67 // |
|
68 // So we could waste up to 10 words to meet that percentage. Given that we |
|
69 // also assume that that buffer is typically half-full, the new desired PLAB |
|
70 // size is set to 20 words. |
|
71 // |
|
72 // The amount of allocation performed should be independent of the number of |
|
73 // threads, so should the maximum waste we can spend in total. So if |
|
74 // we used n threads to allocate, each of them can spend maximum waste/n words in |
|
75 // a first rough approximation. The number of threads only comes into play later |
|
76 // when actually retrieving the actual desired PLAB size. |
|
77 // |
|
78 // After calculating this optimal PLAB size the algorithm applies the usual |
|
79 // exponential decaying average over this value to guess the next PLAB size. |
|
80 // |
|
81 // We account region end waste fully to PLAB allocation (in the calculation of |
|
82 // what we consider as "used_for_waste_calculation" below). This is not |
|
83 // completely fair, but is a conservative assumption because PLABs may be sized |
|
84 // flexibly while we cannot adjust inline allocations. |
|
85 // Allocation during GC will try to minimize region end waste so this impact |
|
86 // should be minimal. |
|
87 // |
|
88 // We need to cover overflow when calculating the amount of space actually used |
|
89 // by objects in PLABs when subtracting the region end waste. |
|
90 // Region end waste may be higher than actual allocation. This may occur if many |
|
91 // threads do not allocate anything but a few rather large objects. In this |
|
92 // degenerate case the PLAB size would simply quickly tend to minimum PLAB size, |
|
93 // which is an okay reaction. |
|
94 size_t const used_for_waste_calculation = used() > _region_end_waste ? used() - _region_end_waste : 0; |
|
95 |
109 |
96 size_t const total_waste_allowed = used_for_waste_calculation * TargetPLABWastePct; |
110 log_debug(gc, plab)(" (allocated = " SIZE_FORMAT " wasted = " SIZE_FORMAT " " |
97 size_t const cur_plab_sz = (size_t)((double)total_waste_allowed / G1LastPLABAverageOccupancy); |
111 "unused = " SIZE_FORMAT " used = " SIZE_FORMAT " " |
98 // Take historical weighted average |
112 "undo_waste = " SIZE_FORMAT " region_end_waste = " SIZE_FORMAT " " |
99 _filter.sample(cur_plab_sz); |
113 "regions filled = %u direct_allocated = " SIZE_FORMAT " " |
100 // Clip from above and below, and align to object boundary |
114 "failure_used = " SIZE_FORMAT " failure_waste = " SIZE_FORMAT ") " |
101 size_t plab_sz; |
115 " (plab_sz = " SIZE_FORMAT " desired_plab_sz = " SIZE_FORMAT ")", |
102 plab_sz = MAX2(min_size(), (size_t)_filter.average()); |
116 _allocated, _wasted, _unused, used(), _undo_wasted, _region_end_waste, |
103 plab_sz = MIN2(max_size(), plab_sz); |
117 _regions_filled, _direct_allocated, _failure_used, _failure_waste, |
104 plab_sz = align_object_size(plab_sz); |
118 cur_plab_sz, plab_sz); |
105 // Latch the result |
119 |
106 _desired_net_plab_sz = plab_sz; |
|
107 if (PrintPLAB) { |
|
108 gclog_or_tty->print(" (plab_sz = " SIZE_FORMAT " desired_plab_sz = " SIZE_FORMAT ") ", cur_plab_sz, plab_sz); |
|
109 } |
|
110 } |
|
111 if (PrintPLAB) { |
|
112 gclog_or_tty->cr(); |
|
113 } |
|
114 // Clear accumulators for next round. |
120 // Clear accumulators for next round. |
115 reset(); |
121 reset(); |
116 } |
122 } |
117 |
123 |
118 G1EvacStats::~G1EvacStats() { } |
124 G1EvacStats::~G1EvacStats() { } |