Mercurial > hg > graal-jvmci-8
annotate src/share/vm/services/g1MemoryPool.hpp @ 1754:e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
Summary: The way we were caluclating the max value meant that it might fluctuate during the run and this broke some assumptions inside the MBeans framework. This change sets the max value of each pool to -1, which means undefined according to the spec.
Reviewed-by: mchung, johnc
author | tonyp |
---|---|
date | Wed, 25 Aug 2010 08:44:58 -0400 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
rev | line source |
---|---|
1089 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1093
diff
changeset
|
2 * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. |
1089 | 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:
1093
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1093
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:
1093
diff
changeset
|
21 * questions. |
1089 | 22 * |
23 */ | |
24 | |
25 class G1CollectedHeap; | |
26 | |
27 // This file contains the three classes that represent the memory | |
28 // pools of the G1 spaces: G1EdenPool, G1SurvivorPool, and | |
29 // G1OldGenPool. In G1, unlike our other GCs, we do not have a | |
30 // physical space for each of those spaces. Instead, we allocate | |
31 // regions for all three spaces out of a single pool of regions (that | |
32 // pool basically covers the entire heap). As a result, the eden, | |
33 // survivor, and old gen are considered logical spaces in G1, as each | |
34 // is a set of non-contiguous regions. This is also reflected in the | |
35 // way we map them to memory pools here. The easiest way to have done | |
36 // this would have been to map the entire G1 heap to a single memory | |
37 // pool. However, it's helpful to show how large the eden and survivor | |
38 // get, as this does affect the performance and behavior of G1. Which | |
39 // is why we introduce the three memory pools implemented here. | |
40 // | |
41 // The above approach inroduces a couple of challenging issues in the | |
42 // implementation of the three memory pools: | |
43 // | |
44 // 1) The used space calculation for a pool is not necessarily | |
45 // independent of the others. We can easily get from G1 the overall | |
46 // used space in the entire heap, the number of regions in the young | |
47 // generation (includes both eden and survivors), and the number of | |
48 // survivor regions. So, from that we calculate: | |
49 // | |
50 // survivor_used = survivor_num * region_size | |
51 // eden_used = young_region_num * region_size - survivor_used | |
52 // old_gen_used = overall_used - eden_used - survivor_used | |
53 // | |
54 // Note that survivor_used and eden_used are upper bounds. To get the | |
55 // actual value we would have to iterate over the regions and add up | |
56 // ->used(). But that'd be expensive. So, we'll accept some lack of | |
57 // accuracy for those two. But, we have to be careful when calculating | |
58 // old_gen_used, in case we subtract from overall_used more then the | |
59 // actual number and our result goes negative. | |
60 // | |
61 // 2) Calculating the used space is straightforward, as described | |
62 // above. However, how do we calculate the committed space, given that | |
63 // we allocate space for the eden, survivor, and old gen out of the | |
64 // same pool of regions? One way to do this is to use the used value | |
65 // as also the committed value for the eden and survivor spaces and | |
66 // then calculate the old gen committed space as follows: | |
67 // | |
68 // old_gen_committed = overall_committed - eden_committed - survivor_committed | |
69 // | |
70 // Maybe a better way to do that would be to calculate used for eden | |
71 // and survivor as a sum of ->used() over their regions and then | |
72 // calculate committed as region_num * region_size (i.e., what we use | |
73 // to calculate the used space now). This is something to consider | |
74 // in the future. | |
75 // | |
76 // 3) Another decision that is again not straightforward is what is | |
1754
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
77 // the max size that each memory pool can grow to. One way to do this |
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
78 // would be to use the committed size for the max for the eden and |
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
79 // survivors and calculate the old gen max as follows (basically, it's |
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
80 // a similar pattern to what we use for the committed space, as |
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
81 // described above): |
1089 | 82 // |
83 // old_gen_max = overall_max - eden_max - survivor_max | |
84 // | |
1754
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
85 // Unfortunately, the above makes the max of each pool fluctuate over |
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
86 // time and, even though this is allowed according to the spec, it |
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
87 // broke several assumptions in the M&M framework (there were cases |
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
88 // where used would reach a value greater than max). So, for max we |
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
89 // use -1, which means "undefined" according to the spec. |
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
90 // |
1089 | 91 // 4) Now, there is a very subtle issue with all the above. The |
92 // framework will call get_memory_usage() on the three pools | |
93 // asynchronously. As a result, each call might get a different value | |
94 // for, say, survivor_num which will yield inconsistent values for | |
95 // eden_used, survivor_used, and old_gen_used (as survivor_num is used | |
96 // in the calculation of all three). This would normally be | |
97 // ok. However, it's possible that this might cause the sum of | |
98 // eden_used, survivor_used, and old_gen_used to go over the max heap | |
99 // size and this seems to sometimes cause JConsole (and maybe other | |
100 // clients) to get confused. There's not a really an easy / clean | |
101 // solution to this problem, due to the asynchrounous nature of the | |
102 // framework. | |
103 | |
104 | |
105 // This class is shared by the three G1 memory pool classes | |
106 // (G1EdenPool, G1SurvivorPool, G1OldGenPool). Given that the way we | |
107 // calculate used / committed bytes for these three pools is related | |
108 // (see comment above), we put the calculations in this class so that | |
109 // we can easily share them among the subclasses. | |
110 class G1MemoryPoolSuper : public CollectedMemoryPool { | |
111 private: | |
112 // It returns x - y if x > y, 0 otherwise. | |
113 // As described in the comment above, some of the inputs to the | |
114 // calculations we have to do are obtained concurrently and hence | |
115 // may be inconsistent with each other. So, this provides a | |
116 // defensive way of performing the subtraction and avoids the value | |
117 // going negative (which would mean a very large result, given that | |
118 // the parameter are size_t). | |
119 static size_t subtract_up_to_zero(size_t x, size_t y) { | |
120 if (x > y) { | |
121 return x - y; | |
122 } else { | |
123 return 0; | |
124 } | |
125 } | |
126 | |
127 protected: | |
1093
afc30fccf324
6906565: G1: deal with compilation warning in g1MemoryPool.hpp
tonyp
parents:
1092
diff
changeset
|
128 G1CollectedHeap* _g1h; |
afc30fccf324
6906565: G1: deal with compilation warning in g1MemoryPool.hpp
tonyp
parents:
1092
diff
changeset
|
129 |
1089 | 130 // Would only be called from subclasses. |
131 G1MemoryPoolSuper(G1CollectedHeap* g1h, | |
132 const char* name, | |
133 size_t init_size, | |
134 bool support_usage_threshold); | |
135 | |
136 // The reason why all the code is in static methods is so that it | |
137 // can be safely called from the constructors of the subclasses. | |
138 | |
1754
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
139 static size_t undefined_max() { |
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
140 return (size_t) -1; |
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
141 } |
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
142 |
1089 | 143 static size_t overall_committed(G1CollectedHeap* g1h) { |
144 return g1h->capacity(); | |
145 } | |
146 static size_t overall_used(G1CollectedHeap* g1h) { | |
147 return g1h->used_unlocked(); | |
148 } | |
149 | |
150 static size_t eden_space_committed(G1CollectedHeap* g1h); | |
151 static size_t eden_space_used(G1CollectedHeap* g1h); | |
152 | |
153 static size_t survivor_space_committed(G1CollectedHeap* g1h); | |
154 static size_t survivor_space_used(G1CollectedHeap* g1h); | |
155 | |
156 static size_t old_space_committed(G1CollectedHeap* g1h); | |
157 static size_t old_space_used(G1CollectedHeap* g1h); | |
158 }; | |
159 | |
160 // Memory pool that represents the G1 eden. | |
161 class G1EdenPool : public G1MemoryPoolSuper { | |
162 public: | |
163 G1EdenPool(G1CollectedHeap* g1h); | |
164 | |
165 size_t used_in_bytes() { | |
1093
afc30fccf324
6906565: G1: deal with compilation warning in g1MemoryPool.hpp
tonyp
parents:
1092
diff
changeset
|
166 return eden_space_used(_g1h); |
1089 | 167 } |
1093
afc30fccf324
6906565: G1: deal with compilation warning in g1MemoryPool.hpp
tonyp
parents:
1092
diff
changeset
|
168 size_t max_size() const { |
1754
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
169 return undefined_max(); |
1089 | 170 } |
171 MemoryUsage get_memory_usage(); | |
172 }; | |
173 | |
174 // Memory pool that represents the G1 survivor. | |
175 class G1SurvivorPool : public G1MemoryPoolSuper { | |
176 public: | |
177 G1SurvivorPool(G1CollectedHeap* g1h); | |
178 | |
179 size_t used_in_bytes() { | |
1093
afc30fccf324
6906565: G1: deal with compilation warning in g1MemoryPool.hpp
tonyp
parents:
1092
diff
changeset
|
180 return survivor_space_used(_g1h); |
1089 | 181 } |
1093
afc30fccf324
6906565: G1: deal with compilation warning in g1MemoryPool.hpp
tonyp
parents:
1092
diff
changeset
|
182 size_t max_size() const { |
1754
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
183 return undefined_max(); |
1089 | 184 } |
185 MemoryUsage get_memory_usage(); | |
186 }; | |
187 | |
188 // Memory pool that represents the G1 old gen. | |
189 class G1OldGenPool : public G1MemoryPoolSuper { | |
190 public: | |
191 G1OldGenPool(G1CollectedHeap* g1h); | |
192 | |
193 size_t used_in_bytes() { | |
1093
afc30fccf324
6906565: G1: deal with compilation warning in g1MemoryPool.hpp
tonyp
parents:
1092
diff
changeset
|
194 return old_space_used(_g1h); |
1089 | 195 } |
1093
afc30fccf324
6906565: G1: deal with compilation warning in g1MemoryPool.hpp
tonyp
parents:
1092
diff
changeset
|
196 size_t max_size() const { |
1754
e967bad2a9ab
6941275: G1: The MemoryPools are incorrectly supported for G1
tonyp
parents:
1552
diff
changeset
|
197 return undefined_max(); |
1089 | 198 } |
199 MemoryUsage get_memory_usage(); | |
200 }; |