// =================================================================================================
// Copyright 2011 Twitter, Inc.
// -------------------------------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this work except in compliance with the License.
// You may obtain a copy of the License in the LICENSE file, or at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =================================================================================================
package com.twitter.common.objectsize;
import java.util.LinkedList;
import org.junit.Before;
import com.twitter.common.objectsize.ObjectSizeCalculator.MemoryLayoutSpecification;
import junit.framework.TestCase;
/**
* @author Attila Szegedi
*/
public class ObjectSizeCalculatorTest extends TestCase {
private int A;
private int O;
private int R;
private int S;
private ObjectSizeCalculator objectSizeCalculator;
@Before
public void setUp() {
MemoryLayoutSpecification memoryLayoutSpecification =
new MemoryLayoutSpecification() {
@Override public int getArrayHeaderSize() {
return 16;
}
@Override public int getObjectHeaderSize() {
return 12;
}
@Override public int getObjectPadding() {
return 8;
}
@Override public int getReferenceSize() {
return 4;
}
@Override public int getSuperclassFieldPadding() {
return 4;
}
};
A = memoryLayoutSpecification.getArrayHeaderSize();
O = memoryLayoutSpecification.getObjectHeaderSize();
R = memoryLayoutSpecification.getReferenceSize();
S = memoryLayoutSpecification.getSuperclassFieldPadding();
objectSizeCalculator = new ObjectSizeCalculator(memoryLayoutSpecification);
}
public void testRounding() {
assertEquals(0, roundTo(0, 8));
assertEquals(8, roundTo(1, 8));
assertEquals(8, roundTo(7, 8));
assertEquals(8, roundTo(8, 8));
assertEquals(16, roundTo(9, 8));
assertEquals(16, roundTo(15, 8));
assertEquals(16, roundTo(16, 8));
assertEquals(24, roundTo(17, 8));
}
public void testObjectSize() {
assertSizeIs(O, new Object());
}
public void testStringSize() {
// String has 3 int fields and one reference field
assertSizeIs(O + 3 * 4 + R + A, new String());
}
public static class Class1 {
private boolean b1;
}
public void testOneBooleanSize() {
assertSizeIs(O + 1, new Class1());
}
public static class Class2 extends Class1 {
private int i1;
}
public void testSimpleSubclassSize() {
assertSizeIs(O + roundTo(1, S) + 4, new Class2());
}
public void testZeroLengthArray() {
assertSizeIs(A, new byte[0]);
assertSizeIs(A, new int[0]);
assertSizeIs(A, new long[0]);
assertSizeIs(A, new Object[0]);
}
public void testByteArrays() {
assertSizeIs(A + 1, new byte[1]);
assertSizeIs(A + 8, new byte[8]);
assertSizeIs(A + 9, new byte[9]);
}
public void testCharArrays() {
assertSizeIs(A + 2 * 1, new char[1]);
assertSizeIs(A + 2 * 4, new char[4]);
assertSizeIs(A + 2 * 5, new char[5]);
}
public void testIntArrays() {
assertSizeIs(A + 4 * 1, new int[1]);
assertSizeIs(A + 4 * 2, new int[2]);
assertSizeIs(A + 4 * 3, new int[3]);
}
public void testLongArrays() {
assertSizeIs(A + 8 * 1, new long[1]);
assertSizeIs(A + 8 * 2, new long[2]);
assertSizeIs(A + 8 * 3, new long[3]);
}
public void testObjectArrays() {
assertSizeIs(A + R * 1, new Object[1]);
assertSizeIs(A + R * 2, new Object[2]);
assertSizeIs(A + R * 3, new Object[3]);
assertSizeIs(A + R * 1, new String[1]);
assertSizeIs(A + R * 2, new String[2]);
assertSizeIs(A + R * 3, new String[3]);
}
public static class Circular {
Circular c;
}
public void testCircular() {
Circular c1 = new Circular();
long size = objectSizeCalculator.calculateObjectSize(c1);
c1.c = c1;
assertEquals(size, objectSizeCalculator.calculateObjectSize(c1));
}
public void testLongList() {
// TODO(John Sirois): Fails under a 64-bit uncompressed OOPs memory layout of:
// arrayHeaderSize = 24
// objectHeaderSize = 16
// objectPadding = 8
// referenceSize = 8
// auperclassFieldPadding = 8
LinkedList<Object> l = new LinkedList<Object>();
for(int i = 0; i < 100000; ++i) {
l.addLast(new Object());
}
assertSizeIs(roundTo(O + 4 + R, 8) + roundTo(O + 3 * R, 8) * 100001 +
roundTo(O, 8) * 100000, l);
}
private void assertSizeIs(long size, Object o) {
assertEquals(roundTo(size, 8), objectSizeCalculator.calculateObjectSize(o));
}
private static long roundTo(long x, int multiple) {
return ObjectSizeCalculator.roundTo(x, multiple);
}
}