/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.cache; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import it.unimi.dsi.fastutil.longs.LongSet; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.Lifecycle; import org.testng.annotations.Test; import com.opengamma.engine.ComputationTargetSpecification; import com.opengamma.engine.value.ValueProperties; import com.opengamma.engine.value.ValuePropertyNames; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.id.UniqueId; import com.opengamma.util.monitor.OperationTimer; import com.opengamma.util.test.TestGroup; /** * A generic suite of tests for any implementation of {@link IdentifierMap}. */ @Test(groups = TestGroup.INTEGRATION) public abstract class AbstractIdentifierMapTest { private static final Logger s_logger = LoggerFactory.getLogger(AbstractIdentifierMapTest.class); protected abstract IdentifierMap createIdentifierMap(String testName); protected ValueSpecification getValueSpec(String valueName) { ValueSpecification valueSpec = new ValueSpecification("Value", ComputationTargetSpecification.of(UniqueId.of("scheme", valueName)), ValueProperties.with(ValuePropertyNames.FUNCTION, "mockFunctionId").get()); return valueSpec; } protected void stopIdentifierMap(IdentifierMap idMap) { if (idMap instanceof Lifecycle) { ((Lifecycle) idMap).stop(); } } @Test public void simpleOperation() throws IOException { IdentifierMap idMap = createIdentifierMap("simpleOperation"); Map<String, Long> identifiers = new HashMap<String, Long>(); LongSet seenIdentifiers = new LongOpenHashSet(); for (int i = 0; i < 10; i++) { String valueName = "value-" + i; ValueSpecification valueSpec = getValueSpec(valueName); long identifier = idMap.getIdentifier(valueSpec); assertFalse(seenIdentifiers.contains(identifier)); seenIdentifiers.add(identifier); identifiers.put(valueName, identifier); } for (int j = 0; j < 5; j++) { Long2ObjectMap<ValueSpecification> valueSpecs = idMap.getValueSpecifications(seenIdentifiers); assertEquals(seenIdentifiers.size(), valueSpecs.size()); for (int i = 0; i < 10; i++) { String valueName = "value-" + i; ValueSpecification valueSpec = getValueSpec(valueName); long identifier = idMap.getIdentifier(valueSpec); long existingIdentifier = identifiers.get(valueName); assertEquals(identifier, existingIdentifier); assertEquals(valueSpec, idMap.getValueSpecification(identifier)); assertEquals(valueSpec, valueSpecs.get(identifier)); } } stopIdentifierMap(idMap); } /** * @param numRequirementNames * @param numIdentifiers * @param idSource */ private void singleOperationGetIdentifier(final int numRequirementNames, final int numIdentifiers, IdentifierMap idSource) { for (int iRequirementName = 0; iRequirementName < numRequirementNames; iRequirementName++) { String requirementName = "req-" + iRequirementName; for (int iIdentifier = 0; iIdentifier < numIdentifiers; iIdentifier++) { String identifierName = "identifier-" + iIdentifier; ValueSpecification valueSpec = new ValueSpecification(requirementName, ComputationTargetSpecification.of(UniqueId.of("scheme", identifierName)), ValueProperties.with(ValuePropertyNames.FUNCTION, "mockFunctionId").get()); // Just throw away the actual identifier. We don't care. idSource.getIdentifier(valueSpec); } } } /** * @param numRequirementNames * @param numIdentifiers * @param idSource */ private void bulkOperationGetIdentifier(final int numRequirementNames, final int numIdentifiers, IdentifierMap idSource) { for (int iRequirementName = 0; iRequirementName < numRequirementNames; iRequirementName++) { final Collection<ValueSpecification> valueSpecs = new ArrayList<ValueSpecification>(numIdentifiers); final String requirementName = "req-" + iRequirementName; for (int iIdentifier = 0; iIdentifier < numIdentifiers; iIdentifier++) { final String identifierName = "identifier-" + iIdentifier; valueSpecs.add(new ValueSpecification(requirementName, ComputationTargetSpecification.of(UniqueId.of("scheme", identifierName)), ValueProperties.with(ValuePropertyNames.FUNCTION, "mockFunctionId").get())); } idSource.getIdentifiers(valueSpecs); } } protected void putPerformanceTestImpl(final boolean bulkOperation) { final int numRequirementNames = 100; final int numIdentifiers = 100; final long numSpecifications = ((long) numRequirementNames) * ((long) numIdentifiers); IdentifierMap idMap = createIdentifierMap("putPerformanceTestImpl-" + bulkOperation); OperationTimer timer = new OperationTimer(s_logger, "Put performance test with {} elements", numSpecifications); if (bulkOperation) { bulkOperationGetIdentifier(numRequirementNames, numIdentifiers, idMap); } else { singleOperationGetIdentifier(numRequirementNames, numIdentifiers, idMap); } stopIdentifierMap(idMap); long numMillis = timer.finished(); double msPerPut = ((double) numMillis) / ((double) numSpecifications); double putsPerSecond = 1000.0 / msPerPut; s_logger.warn("put {}-{} ({}) Split time was {} ms/put, {} puts/sec", new Object[] {numRequirementNames, numIdentifiers, bulkOperation, msPerPut, putsPerSecond }); } protected void getPerformanceTestImpl(final boolean bulkOperation) { final IdentifierMap idMap = createIdentifierMap("getPerformanceTestImpl-" + bulkOperation); final int numRequirementNames = 100; final int numIdentifiers = 100; final long numSpecifications = ((long) numRequirementNames) * ((long) numIdentifiers); try { if (bulkOperation) { bulkOperationGetIdentifier(numRequirementNames, numIdentifiers, idMap); } else { singleOperationGetIdentifier(numRequirementNames, numIdentifiers, idMap); } final OperationTimer timer = new OperationTimer(s_logger, "Get performance test with {} elements", numSpecifications); if (bulkOperation) { bulkOperationGetIdentifier(numRequirementNames, numIdentifiers, idMap); } else { singleOperationGetIdentifier(numRequirementNames, numIdentifiers, idMap); } final long numMillis = timer.finished(); final double msPerPut = ((double) numMillis) / ((double) numSpecifications); final double putsPerSecond = 1000.0 / msPerPut; s_logger.warn("get {}-{} ({}) Split time was {} ms/get, {} gets/sec", new Object[] {numRequirementNames, numIdentifiers, bulkOperation, msPerPut, putsPerSecond }); } finally { stopIdentifierMap(idMap); } } @Test public void putPerformanceTest() { putPerformanceTestImpl(false); } @Test public void bulkPutPerformanceTest() { putPerformanceTestImpl(true); } @Test public void getPerformanceTest() { getPerformanceTestImpl(false); } @Test public void bulkGetPerformanceTest() { getPerformanceTestImpl(true); } }