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 += ClassSize.estimateBase(AtomicInteger.class, false);
309 expected += (2 * ClassSize.estimateBase(CellSkipListSet.class, false));
310 expected += (2 * ClassSize.estimateBase(ConcurrentSkipListMap.class, false));
311 expected += (2 * ClassSize.estimateBase(TimeRangeTracker.class, false));
312 if (expected != actual) {
313 ClassSize.estimateBase(cl, true);
314 ClassSize.estimateBase(AtomicLong.class, true);
315 ClassSize.estimateBase(AtomicLong.class, true);
316 ClassSize.estimateBase(AtomicInteger.class, true);
317 ClassSize.estimateBase(CellSkipListSet.class, true);
318 ClassSize.estimateBase(CellSkipListSet.class, true);
319 ClassSize.estimateBase(ConcurrentSkipListMap.class, true);
320 ClassSize.estimateBase(ConcurrentSkipListMap.class, true);
321 ClassSize.estimateBase(TimeRangeTracker.class, true);
322 ClassSize.estimateBase(TimeRangeTracker.class, true);
323 assertEquals(expected, actual);
324 }
325
326
327 cl = HStore.class;
328 actual = HStore.FIXED_OVERHEAD;
329 expected = ClassSize.estimateBase(cl, false);
330 if(expected != actual) {
331 ClassSize.estimateBase(cl, true);
332 assertEquals(expected, actual);
333 }
334
335
336 cl = HRegion.class;
337 actual = HRegion.FIXED_OVERHEAD;
338 expected = ClassSize.estimateBase(cl, false);
339 if (expected != actual) {
340 ClassSize.estimateBase(cl, true);
341 assertEquals(expected, actual);
342 }
343
344
345
346 cl = BlockCacheKey.class;
347 actual = BlockCacheKey.FIXED_OVERHEAD;
348 expected = ClassSize.estimateBase(cl, false);
349 if (expected != actual) {
350 ClassSize.estimateBase(cl, true);
351 assertEquals(expected, actual);
352 }
353
354
355
356
357
358
359
360 }
361
362 @Test
363 public void testMutations(){
364 Class<?> cl;
365 long expected;
366 long actual;
367
368 cl = TimeRange.class;
369 actual = ClassSize.TIMERANGE;
370 expected = ClassSize.estimateBase(cl, false);
371 if (expected != actual) {
372 ClassSize.estimateBase(cl, true);
373 assertEquals(expected, actual);
374 }
375
376 byte[] row = new byte[] { 0 };
377 cl = Put.class;
378 actual = new Put(row).MUTATION_OVERHEAD + ClassSize.align(ClassSize.ARRAY);
379 expected = ClassSize.estimateBase(cl, false);
380
381 expected += ClassSize.align(ClassSize.TREEMAP);
382 expected += ClassSize.align(ClassSize.INTEGER);
383 if (expected != actual) {
384 ClassSize.estimateBase(cl, true);
385 assertEquals(expected, actual);
386 }
387
388 cl = Delete.class;
389 actual = new Delete(row).MUTATION_OVERHEAD + ClassSize.align(ClassSize.ARRAY);
390 expected = ClassSize.estimateBase(cl, false);
391
392 expected += ClassSize.align(ClassSize.TREEMAP);
393 expected += ClassSize.align(ClassSize.INTEGER);
394 if (expected != actual) {
395 ClassSize.estimateBase(cl, true);
396 assertEquals(expected, actual);
397 }
398 }
399
400 @Test
401 public void testReferenceSize() {
402 LOG.info("ClassSize.REFERENCE is " + ClassSize.REFERENCE);
403
404 assertTrue(ClassSize.REFERENCE == 4 || ClassSize.REFERENCE == 8);
405 }
406
407 @Test
408 public void testObjectSize() throws IOException {
409 LOG.info("header:" + ClassSize.OBJECT);
410 LOG.info("array header:" + ClassSize.ARRAY);
411
412 if (ClassSize.is32BitJVM()) {
413 assertEquals(ClassSize.OBJECT, 8);
414 } else {
415 assertTrue(ClassSize.OBJECT == 12 || ClassSize.OBJECT == 16);
416 }
417 assertEquals(ClassSize.OBJECT + 4, ClassSize.ARRAY);
418 }
419
420 }
421