1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.util;
22
23 import java.lang.reflect.Field;
24 import java.lang.reflect.Modifier;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.ConcurrentSkipListMap;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.hadoop.hbase.classification.InterfaceAudience;
31
32
33
34
35
36
37
38 @InterfaceAudience.Private
39 public class ClassSize {
40 private static final Log LOG = LogFactory.getLog(ClassSize.class);
41
42 private static int nrOfRefsPerObj = 2;
43
44
45 public static final int ARRAY;
46
47
48 public static final int ARRAYLIST;
49
50
51 public static final int BYTE_BUFFER;
52
53
54 public static final int INTEGER;
55
56
57 public static final int MAP_ENTRY;
58
59
60 public static final int OBJECT;
61
62
63 public static final int REFERENCE;
64
65
66 public static final int STRING;
67
68
69 public static final int TREEMAP;
70
71
72 public static final int CONCURRENT_HASHMAP;
73
74
75 public static final int CONCURRENT_HASHMAP_ENTRY;
76
77
78 public static final int CONCURRENT_HASHMAP_SEGMENT;
79
80
81 public static final int CONCURRENT_SKIPLISTMAP;
82
83
84 public static final int CONCURRENT_SKIPLISTMAP_ENTRY;
85
86
87 public static final int REENTRANT_LOCK;
88
89
90 public static final int ATOMIC_LONG;
91
92
93 public static final int ATOMIC_INTEGER;
94
95
96 public static final int ATOMIC_BOOLEAN;
97
98
99 public static final int COPYONWRITE_ARRAYSET;
100
101
102 public static final int COPYONWRITE_ARRAYLIST;
103
104
105 public static final int TIMERANGE;
106
107
108 public static final int TIMERANGE_TRACKER;
109
110
111 public static final int CELL_SKIPLIST_SET;
112
113
114
115
116
117 static {
118
119 if (is32BitJVM()) {
120 REFERENCE = 4;
121 } else {
122 REFERENCE = 8;
123 }
124
125 OBJECT = 2 * REFERENCE;
126
127 ARRAY = align(3 * REFERENCE);
128
129 ARRAYLIST = align(OBJECT + align(REFERENCE) + align(ARRAY) +
130 (2 * Bytes.SIZEOF_INT));
131
132
133 BYTE_BUFFER = align(OBJECT + align(REFERENCE) + align(ARRAY) +
134 (5 * Bytes.SIZEOF_INT) +
135 (3 * Bytes.SIZEOF_BOOLEAN) + Bytes.SIZEOF_LONG);
136
137 INTEGER = align(OBJECT + Bytes.SIZEOF_INT);
138
139 MAP_ENTRY = align(OBJECT + 5 * REFERENCE + Bytes.SIZEOF_BOOLEAN);
140
141 TREEMAP = align(OBJECT + (2 * Bytes.SIZEOF_INT) + align(7 * REFERENCE));
142
143
144
145 STRING = (int) estimateBase(String.class, false);
146
147
148
149
150 CONCURRENT_HASHMAP = (int) estimateBase(ConcurrentHashMap.class, false);
151
152 CONCURRENT_HASHMAP_ENTRY = align(REFERENCE + OBJECT + (3 * REFERENCE) +
153 (2 * Bytes.SIZEOF_INT));
154
155 CONCURRENT_HASHMAP_SEGMENT = align(REFERENCE + OBJECT +
156 (3 * Bytes.SIZEOF_INT) + Bytes.SIZEOF_FLOAT + ARRAY);
157
158
159 CONCURRENT_SKIPLISTMAP = (int) estimateBase(ConcurrentSkipListMap.class, false);
160
161 CONCURRENT_SKIPLISTMAP_ENTRY = align(
162 align(OBJECT + (3 * REFERENCE)) +
163 align((OBJECT + (3 * REFERENCE))/2));
164
165 REENTRANT_LOCK = align(OBJECT + (3 * REFERENCE));
166
167 ATOMIC_LONG = align(OBJECT + Bytes.SIZEOF_LONG);
168
169 ATOMIC_INTEGER = align(OBJECT + Bytes.SIZEOF_INT);
170
171 ATOMIC_BOOLEAN = align(OBJECT + Bytes.SIZEOF_BOOLEAN);
172
173 COPYONWRITE_ARRAYSET = align(OBJECT + REFERENCE);
174
175 COPYONWRITE_ARRAYLIST = align(OBJECT + (2 * REFERENCE) + ARRAY);
176
177 TIMERANGE = align(ClassSize.OBJECT + Bytes.SIZEOF_LONG * 2 + Bytes.SIZEOF_BOOLEAN);
178
179 TIMERANGE_TRACKER = align(ClassSize.OBJECT + Bytes.SIZEOF_LONG * 2);
180
181 CELL_SKIPLIST_SET = align(OBJECT + REFERENCE);
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199 @SuppressWarnings("unchecked")
200 private static int [] getSizeCoefficients(Class cl, boolean debug) {
201 int primitives = 0;
202 int arrays = 0;
203
204 int references = nrOfRefsPerObj;
205 int index = 0;
206
207 for ( ; null != cl; cl = cl.getSuperclass()) {
208 Field[] field = cl.getDeclaredFields();
209 if (null != field) {
210 for (Field aField : field) {
211 if (Modifier.isStatic(aField.getModifiers())) continue;
212 Class fieldClass = aField.getType();
213 if (fieldClass.isArray()) {
214 arrays++;
215 references++;
216 } else if (!fieldClass.isPrimitive()) {
217 references++;
218 } else {
219 String name = fieldClass.getName();
220
221 if (name.equals("int") || name.equals("I"))
222 primitives += Bytes.SIZEOF_INT;
223 else if (name.equals("long") || name.equals("J"))
224 primitives += Bytes.SIZEOF_LONG;
225 else if (name.equals("boolean") || name.equals("Z"))
226 primitives += Bytes.SIZEOF_BOOLEAN;
227 else if (name.equals("short") || name.equals("S"))
228 primitives += Bytes.SIZEOF_SHORT;
229 else if (name.equals("byte") || name.equals("B"))
230 primitives += Bytes.SIZEOF_BYTE;
231 else if (name.equals("char") || name.equals("C"))
232 primitives += Bytes.SIZEOF_CHAR;
233 else if (name.equals("float") || name.equals("F"))
234 primitives += Bytes.SIZEOF_FLOAT;
235 else if (name.equals("double") || name.equals("D"))
236 primitives += Bytes.SIZEOF_DOUBLE;
237 }
238 if (debug) {
239 if (LOG.isDebugEnabled()) {
240 LOG.debug("" + index + " " + aField.getName() + " " + aField.getType());
241 }
242 }
243 index++;
244 }
245 }
246 }
247 return new int [] {primitives, arrays, references};
248 }
249
250
251
252
253
254
255
256
257
258
259 private static long estimateBaseFromCoefficients(int [] coeff, boolean debug) {
260 long prealign_size = coeff[0] + align(coeff[1] * ARRAY) + coeff[2] * REFERENCE;
261
262
263 long size = align(prealign_size);
264 if(debug) {
265 if (LOG.isDebugEnabled()) {
266 LOG.debug("Primitives=" + coeff[0] + ", arrays=" + coeff[1] +
267 ", references(includes " + nrOfRefsPerObj +
268 " for object overhead)=" + coeff[2] + ", refSize " + REFERENCE +
269 ", size=" + size + ", prealign_size=" + prealign_size);
270 }
271 }
272 return size;
273 }
274
275
276
277
278
279
280
281
282
283
284
285
286 @SuppressWarnings("unchecked")
287 public static long estimateBase(Class cl, boolean debug) {
288 return estimateBaseFromCoefficients( getSizeCoefficients(cl, debug), debug);
289 }
290
291
292
293
294
295
296 public static int align(int num) {
297 return (int)(align((long)num));
298 }
299
300
301
302
303
304
305 public static long align(long num) {
306
307
308 return ((num + 7) >> 3) << 3;
309 }
310
311
312
313
314
315 public static boolean is32BitJVM() {
316 return System.getProperty("sun.arch.data.model").equals("32");
317 }
318
319 }
320