/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.engine.target.ComputationTargetReference;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.util.NormalizingWeakInstanceCache;
import com.opengamma.util.WeakInstanceCache;
/**
* Badly named class collating all of the hacks used to reduce the memory footprint of some algorithms.
*/
public final class MemoryUtils {
// TODO: Why do we need value specifications everywhere; can't we just work with the longs that go into the jobs? Converting ValueSpecifications to/from the longs
// is cheap enough - if in the cache, map operations no more costly than the approach here
private static final WeakInstanceCache<? extends ComputationTargetReference> s_computationTargetReference = new NormalizingWeakInstanceCache<ComputationTargetReference>() {
@Override
protected ComputationTargetReference normalize(final ComputationTargetReference value) {
return value.normalize();
}
};
private static final WeakInstanceCache<ValueProperties> s_valueProperties = new WeakInstanceCache<ValueProperties>();
private static final WeakInstanceCache<ValueRequirement> s_valueRequirement = new NormalizingWeakInstanceCache<ValueRequirement>() {
@Override
protected ValueRequirement normalize(final ValueRequirement valueRequirement) {
final ComputationTargetReference ctspec = instance(valueRequirement.getTargetReference());
final ValueProperties constraints = instance(valueRequirement.getConstraints());
if ((ctspec == valueRequirement.getTargetReference()) && (constraints == valueRequirement.getConstraints())) {
return valueRequirement;
} else {
return new ValueRequirement(valueRequirement.getValueName(), ctspec, constraints);
}
}
};
private static final WeakInstanceCache<ValueSpecification> s_valueSpecification = new NormalizingWeakInstanceCache<ValueSpecification>() {
@Override
protected ValueSpecification normalize(final ValueSpecification valueSpecification) {
final ComputationTargetSpecification ctspec = instance(valueSpecification.getTargetSpecification());
final ValueProperties properties = instance(valueSpecification.getProperties());
if ((ctspec == valueSpecification.getTargetSpecification()) && (properties == valueSpecification.getProperties())) {
return valueSpecification;
} else {
return new ValueSpecification(valueSpecification.getValueName(), ctspec, properties);
}
}
};
private MemoryUtils() {
}
@SuppressWarnings("unchecked")
public static <T extends ComputationTargetReference> T instance(final T computationTargetReference) {
return ((WeakInstanceCache<T>) s_computationTargetReference).get(computationTargetReference);
}
public static ValueProperties instance(final ValueProperties valueProperties) {
return s_valueProperties.get(valueProperties);
}
public static ValueRequirement instance(final ValueRequirement valueRequirement) {
return s_valueRequirement.get(valueRequirement);
}
public static ValueSpecification instance(final ValueSpecification valueSpecification) {
return s_valueSpecification.get(valueSpecification);
}
/**
* Estimate the size of an object in memory. This is based on its serialized form which is crude but better than nothing.
*
* @param object the object to estimate the size of
* @return the size estimate in bytes
*/
public static long estimateSize(final Serializable object) {
if (object == null) {
return 0;
}
try {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final ObjectOutputStream out = new ObjectOutputStream(baos);
out.writeObject(object);
out.close();
return baos.toByteArray().length;
} catch (IOException e) {
throw new OpenGammaRuntimeException("I/O error", e);
}
}
}