package rocks.inspectit.server.cache;
/**
* This class has some changes in the calculations for the memory size of the objects when IBM JVM
* is run.
*
* @author Ivan Senic
*
*/
public abstract class AbstractObjectSizesIbm extends AbstractObjectSizes {
/**
* {@inheritDoc}
* <p>
* IBM JVM uses 4 bytes per boolean and does not pack booleans together.
*/
@Override
public long getPrimitiveTypesSize(int referenceCount, int booleanCount, int intCount, int floatCount, int longCount, int doubleCount) {
return super.getPrimitiveTypesSize(referenceCount, 0, intCount + booleanCount, floatCount, longCount, doubleCount);
}
/**
* {@inheritDoc}
* <p>
* IBM JVM does not keep size of array in one int field.
*/
@Override
public long getSizeOfArray(int arraySize) {
long size = this.getSizeOfObjectHeader();
size += this.getPrimitiveTypesSize(arraySize, 0, 0, 0, 0, 0);
return alignTo8Bytes(size);
}
/**
* {@inheritDoc}
* <p>
* IBM JVM does not keep size of array in one int field.
*/
@Override
public long getSizeOfPrimitiveArray(int arraySize, long primitiveSize) {
long size = this.getSizeOfObjectHeader();
size += arraySize * primitiveSize;
return alignTo8Bytes(size);
}
/**
* {@inheritDoc}
* <p>
* The HashSet in IBM JVM has the shared map value as static variable.
*/
@Override
public long getSizeOfHashSet(int hashSetSize, int initialCapacity) {
long size = this.getSizeOfObjectHeader();
size += this.getPrimitiveTypesSize(1, 0, 0, 0, 0, 0);
size += this.getSizeOfHashMap(hashSetSize, initialCapacity);
return alignTo8Bytes(size);
}
/**
* {@inheritDoc}
* <p>
* The IBM JVM has the object header of 8 bytes, but the minimum object size is 16 bytes. Don't
* know why this is.
*/
@Override
public long alignTo8Bytes(long size) {
long s = super.alignTo8Bytes(size);
if (size < 16) {
return 16;
} else {
return s;
}
}
/**
* {@inheritDoc}
* <p>
* HashMap from IBM JVM handles in different way the map capacity calculations.
*/
@Override
public int getHashMapCapacityFromSize(int hashMapSize, int initialCapacity) {
return super.getHashMapCapacityFromSize(hashMapSize, calculateHashMapCapacity(initialCapacity));
}
/**
* This method is same as the HashMap implementation of IBM JVM calculates the capacity of
* HashMap with given specified capacity from constructors.
*
* @param specifiedCapacity
* Capacity specified in map constructor.
* @return Real starting capacity.
*/
private static int calculateHashMapCapacity(int specifiedCapacity) {
int capacity = 1;
while (capacity < specifiedCapacity) {
capacity <<= 1;
}
return capacity;
}
/**
* {@inheritDoc}
*/
@Override
protected int getNumberOfConcurrentSegments(int mapSize, int concurrencyLevel) {
int segments = 1;
while (segments < concurrencyLevel) {
segments <<= 1;
}
return segments;
}
/**
* {@inheritDoc}
* <p>
* I can not figure out what I am missing, but seams that I am missing one reference size here.
*/
@Override
protected long getSizeOfConcurrentSeqment(int seqmentCapacity) {
long size = super.getSizeOfConcurrentSeqment(seqmentCapacity);
// for unknown reasons i miss one reference
size += this.getPrimitiveTypesSize(1, 0, 0, 0, 0, 0);
return alignTo8Bytes(size);
}
/**
* Returns the concurrent hash map segment capacity from its size and initial capacity.
*
* @param seqmentSize
* Number of elements in the segment.
* @param initialCapacity
* Initial capacity.
* @return Size in bytes.
*/
@Override
protected int getSegmentCapacityFromSize(int seqmentSize, int initialCapacity) {
int capacity = initialCapacity;
float loadFactor = 0.75f;
int threshold = (int) (capacity * loadFactor);
while ((threshold + 1) < seqmentSize) {
capacity <<= 1;
threshold = (int) (capacity * loadFactor);
}
return capacity;
}
}