1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.io;
21
22 import java.io.IOException;
23 import java.lang.management.ManagementFactory;
24 import java.lang.management.RuntimeMXBean;
25 import java.nio.ByteBuffer;
26 import java.util.ArrayList;
27 import java.util.Map;
28 import java.util.TreeMap;
29 import java.util.concurrent.ConcurrentHashMap;
30 import java.util.concurrent.ConcurrentSkipListMap;
31 import java.util.concurrent.CopyOnWriteArrayList;
32 import java.util.concurrent.CopyOnWriteArraySet;
33 import java.util.concurrent.atomic.AtomicBoolean;
34 import java.util.concurrent.atomic.AtomicInteger;
35 import java.util.concurrent.atomic.AtomicLong;
36 import java.util.concurrent.locks.ReentrantReadWriteLock;
37
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.apache.hadoop.hbase.KeyValue;
41 import org.apache.hadoop.hbase.testclassification.SmallTests;
42 import org.apache.hadoop.hbase.client.Delete;
43 import org.apache.hadoop.hbase.client.Put;
44 import org.apache.hadoop.hbase.io.hfile.BlockCacheKey;
45 import org.apache.hadoop.hbase.io.hfile.LruCachedBlock;
46 import org.apache.hadoop.hbase.io.hfile.LruBlockCache;
47 import org.apache.hadoop.hbase.regionserver.CellSkipListSet;
48 import org.apache.hadoop.hbase.regionserver.DefaultMemStore;
49 import org.apache.hadoop.hbase.regionserver.HRegion;
50 import org.apache.hadoop.hbase.regionserver.HStore;
51 import org.apache.hadoop.hbase.regionserver.TimeRangeTracker;
52 import org.apache.hadoop.hbase.util.ClassSize;
53 import org.junit.BeforeClass;
54 import org.junit.Test;
55 import org.junit.experimental.categories.Category;
56
57 import static org.junit.Assert.assertEquals;
58 import static org.junit.Assert.assertTrue;
59
60
61
62
63
64 @Category(SmallTests.class)
65 public class TestHeapSize {
66 private static final Log LOG = LogFactory.getLog(TestHeapSize.class);
67
68
69
70
71 @BeforeClass
72 public static void beforeClass() throws Exception {
73
74 RuntimeMXBean b = ManagementFactory.getRuntimeMXBean();
75 LOG.info("name=" + b.getName());
76 LOG.info("specname=" + b.getSpecName());
77 LOG.info("specvendor=" + b.getSpecVendor());
78 LOG.info("vmname=" + b.getVmName());
79 LOG.info("vmversion=" + b.getVmVersion());
80 LOG.info("vmvendor=" + b.getVmVendor());
81 Map<String, String> p = b.getSystemProperties();
82 LOG.info("properties=" + p);
83 }
84
85
86
87
88 @Test
89 public void testNativeSizes() throws IOException {
90 Class<?> cl;
91 long expected;
92 long actual;
93
94
95 cl = ArrayList.class;
96 expected = ClassSize.estimateBase(cl, false);
97 actual = ClassSize.ARRAYLIST;
98 if(expected != actual) {
99 ClassSize.estimateBase(cl, true);
100 assertEquals(expected, actual);
101 }
102
103
104 cl = ByteBuffer.class;
105 expected = ClassSize.estimateBase(cl, false);
106 actual = ClassSize.BYTE_BUFFER;
107 if(expected != actual) {
108 ClassSize.estimateBase(cl, true);
109 assertEquals(expected, actual);
110 }
111
112
113 cl = Integer.class;
114 expected = ClassSize.estimateBase(cl, false);
115 actual = ClassSize.INTEGER;
116 if(expected != actual) {
117 ClassSize.estimateBase(cl, true);
118 assertEquals(expected, actual);
119 }
120
121
122
123
124
125
126
127
128
129
130
131
132 cl = Object.class;
133 expected = ClassSize.estimateBase(cl, false);
134 actual = ClassSize.align(ClassSize.OBJECT);
135 if(expected != actual) {
136 ClassSize.estimateBase(cl, true);
137 assertEquals(expected, actual);
138 }
139
140
141 cl = TreeMap.class;
142 expected = ClassSize.estimateBase(cl, false);
143 actual = ClassSize.TREEMAP;
144 if(expected != actual) {
145 ClassSize.estimateBase(cl, true);
146 assertEquals(expected, actual);
147 }
148
149
150 cl = String.class;
151 expected = ClassSize.estimateBase(cl, false);
152 actual = ClassSize.STRING;
153 if(expected != actual) {
154 ClassSize.estimateBase(cl, true);
155 assertEquals(expected, actual);
156 }
157
158
159 cl = ConcurrentHashMap.class;
160 expected = ClassSize.estimateBase(cl, false);
161 actual = ClassSize.CONCURRENT_HASHMAP;
162 if(expected != actual) {
163 ClassSize.estimateBase(cl, true);
164 assertEquals(expected, actual);
165 }
166
167
168 cl = ConcurrentSkipListMap.class;
169 expected = ClassSize.estimateBase(cl, false);
170 actual = ClassSize.CONCURRENT_SKIPLISTMAP;
171 if(expected != actual) {
172 ClassSize.estimateBase(cl, true);
173 assertEquals(expected, actual);
174 }
175
176
177 cl = ReentrantReadWriteLock.class;
178 expected = ClassSize.estimateBase(cl, false);
179 actual = ClassSize.REENTRANT_LOCK;
180 if(expected != actual) {
181 ClassSize.estimateBase(cl, true);
182 assertEquals(expected, actual);
183 }
184
185
186 cl = AtomicLong.class;
187 expected = ClassSize.estimateBase(cl, false);
188 actual = ClassSize.ATOMIC_LONG;
189 if(expected != actual) {
190 ClassSize.estimateBase(cl, true);
191 assertEquals(expected, actual);
192 }
193
194
195 cl = AtomicInteger.class;
196 expected = ClassSize.estimateBase(cl, false);
197 actual = ClassSize.ATOMIC_INTEGER;
198 if(expected != actual) {
199 ClassSize.estimateBase(cl, true);
200 assertEquals(expected, actual);
201 }
202
203
204 cl = AtomicBoolean.class;
205 expected = ClassSize.estimateBase(cl, false);
206 actual = ClassSize.ATOMIC_BOOLEAN;
207 if(expected != actual) {
208 ClassSize.estimateBase(cl, true);
209 assertEquals(expected, actual);
210 }
211
212
213 cl = CopyOnWriteArraySet.class;
214 expected = ClassSize.estimateBase(cl, false);
215 actual = ClassSize.COPYONWRITE_ARRAYSET;
216 if(expected != actual) {
217 ClassSize.estimateBase(cl, true);
218 assertEquals(expected, actual);
219 }
220
221
222 cl = CopyOnWriteArrayList.class;
223 expected = ClassSize.estimateBase(cl, false);
224 actual = ClassSize.COPYONWRITE_ARRAYLIST;
225 if(expected != actual) {
226 ClassSize.estimateBase(cl, true);
227 assertEquals(expected, actual);
228 }
229
230
231 cl = TimeRangeTracker.class;
232 expected = ClassSize.estimateBase(cl, false);
233 actual = ClassSize.TIMERANGE_TRACKER;
234 if (expected != actual) {
235 ClassSize.estimateBase(cl, true);
236 assertEquals(expected, actual);
237 }
238
239
240 cl = CellSkipListSet.class;
241 expected = ClassSize.estimateBase(cl, false);
242 actual = ClassSize.CELL_SKIPLIST_SET;
243 if (expected != actual) {
244 ClassSize.estimateBase(cl, true);
245 assertEquals(expected, actual);
246 }
247 }
248
249
250
251
252
253
254
255 @Test
256 public void testSizes() throws IOException {
257 Class<?> cl;
258 long expected;
259 long actual;
260
261
262 cl = KeyValue.class;
263 expected = ClassSize.estimateBase(cl, false);
264 KeyValue kv = new KeyValue();
265 actual = kv.heapSize();
266 if(expected != actual) {
267 ClassSize.estimateBase(cl, true);
268 assertEquals(expected, actual);
269 }
270
271
272 cl = LruBlockCache.class;
273 actual = LruBlockCache.CACHE_FIXED_OVERHEAD;
274 expected = ClassSize.estimateBase(cl, false);
275 if(expected != actual) {
276 ClassSize.estimateBase(cl, true);
277 assertEquals(expected, actual);
278 }
279
280
281
282
283 cl = LruCachedBlock.class;
284 actual = LruCachedBlock.PER_BLOCK_OVERHEAD;
285 expected = ClassSize.estimateBase(cl, false);
286 expected += ClassSize.estimateBase(String.class, false);
287 expected += ClassSize.estimateBase(ByteBuffer.class, false);
288 if(expected != actual) {
289 ClassSize.estimateBase(cl, true);
290 ClassSize.estimateBase(String.class, true);
291 ClassSize.estimateBase(ByteBuffer.class, true);
292 assertEquals(expected, actual);
293 }
294
295
296 cl = DefaultMemStore.class;
297 actual = DefaultMemStore.FIXED_OVERHEAD;
298 expected = ClassSize.estimateBase(cl, false);
299 if(expected != actual) {
300 ClassSize.estimateBase(cl, true);
301 assertEquals(expected, actual);
302 }
303
304
305 actual = DefaultMemStore.DEEP_OVERHEAD;
306 expected = ClassSize.estimateBase(cl, false);
307 expected += (2 * ClassSize.estimateBase(AtomicLong.class, false));
308 expected += (2 * ClassSize.estimateBase(CellSkipListSet.class, false));
309 expected += (2 * ClassSize.estimateBase(ConcurrentSkipListMap.class, false));
310 expected += (2 * ClassSize.estimateBase(TimeRangeTracker.class, false));
311 if(expected != actual) {
312 ClassSize.estimateBase(cl, true);
313 ClassSize.estimateBase(AtomicLong.class, true);
314 ClassSize.estimateBase(AtomicLong.class, true);
315 ClassSize.estimateBase(CellSkipListSet.class, true);
316 ClassSize.estimateBase(CellSkipListSet.class, true);
317 ClassSize.estimateBase(ConcurrentSkipListMap.class, true);
318 ClassSize.estimateBase(ConcurrentSkipListMap.class, true);
319 ClassSize.estimateBase(TimeRangeTracker.class, true);
320 ClassSize.estimateBase(TimeRangeTracker.class, true);
321 assertEquals(expected, actual);
322 }
323
324
325 cl = HStore.class;
326 actual = HStore.FIXED_OVERHEAD;
327 expected = ClassSize.estimateBase(cl, false);
328 if(expected != actual) {
329 ClassSize.estimateBase(cl, true);
330 assertEquals(expected, actual);
331 }
332
333
334 cl = HRegion.class;
335 actual = HRegion.FIXED_OVERHEAD;
336 expected = ClassSize.estimateBase(cl, false);
337 if (expected != actual) {
338 ClassSize.estimateBase(cl, true);
339 assertEquals(expected, actual);
340 }
341
342
343
344 cl = BlockCacheKey.class;
345 actual = BlockCacheKey.FIXED_OVERHEAD;
346 expected = ClassSize.estimateBase(cl, false);
347 if (expected != actual) {
348 ClassSize.estimateBase(cl, true);
349 assertEquals(expected, actual);
350 }
351
352
353
354
355
356
357
358 }
359
360 @Test
361 public void testMutations(){
362 Class<?> cl;
363 long expected;
364 long actual;
365
366 cl = TimeRange.class;
367 actual = ClassSize.TIMERANGE;
368 expected = ClassSize.estimateBase(cl, false);
369 if (expected != actual) {
370 ClassSize.estimateBase(cl, true);
371 assertEquals(expected, actual);
372 }
373
374 byte[] row = new byte[] { 0 };
375 cl = Put.class;
376 actual = new Put(row).MUTATION_OVERHEAD + ClassSize.align(ClassSize.ARRAY);
377 expected = ClassSize.estimateBase(cl, false);
378
379 expected += ClassSize.align(ClassSize.TREEMAP);
380 expected += ClassSize.align(ClassSize.INTEGER);
381 if (expected != actual) {
382 ClassSize.estimateBase(cl, true);
383 assertEquals(expected, actual);
384 }
385
386 cl = Delete.class;
387 actual = new Delete(row).MUTATION_OVERHEAD + ClassSize.align(ClassSize.ARRAY);
388 expected = ClassSize.estimateBase(cl, false);
389
390 expected += ClassSize.align(ClassSize.TREEMAP);
391 expected += ClassSize.align(ClassSize.INTEGER);
392 if (expected != actual) {
393 ClassSize.estimateBase(cl, true);
394 assertEquals(expected, actual);
395 }
396 }
397
398 @Test
399 public void testReferenceSize() {
400 LOG.info("ClassSize.REFERENCE is " + ClassSize.REFERENCE);
401
402 assertTrue(ClassSize.REFERENCE == 4 || ClassSize.REFERENCE == 8);
403 }
404
405 @Test
406 public void testObjectSize() throws IOException {
407 LOG.info("header:" + ClassSize.OBJECT);
408 LOG.info("array header:" + ClassSize.ARRAY);
409
410 if (ClassSize.is32BitJVM()) {
411 assertEquals(ClassSize.OBJECT, 8);
412 } else {
413 assertTrue(ClassSize.OBJECT == 12 || ClassSize.OBJECT == 16);
414 }
415 assertEquals(ClassSize.OBJECT + 4, ClassSize.ARRAY);
416 }
417
418 }
419