blob: 55b93e913c055590539774ceef322abb557bdb0c [file] [log] [blame]
/**
* <copyright> Copyright (c) 2008-2009 Jonas Helming, Maximilian Koegel. All rights reserved. This program and the
* accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this
* distribution, and is available at http://www.eclipse.org/legal/epl-v10.html </copyright>
*/
package org.eclipse.emf.emfstore.performance.test;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.emfstore.bowling.BowlingPackage;
import org.eclipse.emf.emfstore.client.ESLocalProject;
import org.eclipse.emf.emfstore.client.test.common.cases.ESTestWithLoggedInUserMock;
import org.eclipse.emf.emfstore.client.test.common.util.ProjectUtil;
import org.eclipse.emf.emfstore.client.util.ESVoidCallable;
import org.eclipse.emf.emfstore.client.util.RunESCommand;
import org.eclipse.emf.emfstore.fuzzy.emf.junit.ESDefaultModelMutator;
import org.eclipse.emf.emfstore.internal.client.model.ESWorkspaceProviderImpl;
import org.eclipse.emf.emfstore.internal.client.model.ProjectSpace;
import org.eclipse.emf.emfstore.internal.common.model.Project;
import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil;
import org.eclipse.emf.emfstore.modelmutator.ESModelMutatorConfiguration;
import org.eclipse.emf.emfstore.modelmutator.ESModelMutatorUtil;
import org.eclipse.emf.emfstore.server.exceptions.ESException;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* This TestCase tests all methods in the main {@link org.unicase.emfstore.EmfStore} interface.
*
* @author Dmitry Litvinov
*/
public class PerformanceTest extends ESTestWithLoggedInUserMock {
private static final int PROJECTSIZE = 10000;
private static final int NR_OF_CHANGES = 100;
@BeforeClass
public static void beforeClass() {
startEMFStore();
}
@AfterClass
public static void afterClass() {
stopEMFStore();
}
private final static String MODEL_KEY = "http://org/eclipse/example/bowling";
private static final int NUM_ITERATIONS = 10;
private final long seed = 1234567800;
private static MemoryMeter memoryMeter;
private long lastSeed = seed + 1;
private static final double ACCEPTED_VARIANCE = 1.5;
private double memAfterThreshold;
double[] times;
long[] memBefore, memDuring, memAfter;
/**
* Start server and gain session id.
*
* @throws ESException in case of failure
* @throws IOException
*/
@Override
public void before() {
super.before();
generateModels(getProjectSpace(), PROJECTSIZE);
System.out.println("MODEL SIZE: " + getLocalProject().getAllModelElements().size());
initMeasurments();
}
@Override
public void after() {
super.after();
memoryMeter.finish();
}
/**
* Opens projects of different sizes, shares them with the server and then deletes them. r
*
* @see org.unicase.emfstore.EmfStore#createProject(org.eclipse.emf.emfstore.server.model.SessionId, String, String,
* org.eclipse.emf.emfstore.server.model.versioning.LogMessage, Project)
* @see org.unicase.emfstore.EmfStore#getProjectList(org.eclipse.emf.emfstore.server.model.SessionId)
* @throws ESException in case of failure.
* @throws IOException
*/
@Test
public void testShareProject() throws ESException, IOException {
initMeasurments();
for (int i = 0; i < NUM_ITERATIONS; i++) {
memoryMeter.startMeasurements();
memBefore[i] = usedMemory();
long time = System.currentTimeMillis();
ProjectUtil.share(getUsersession(), getLocalProject());
times[i] = (System.currentTimeMillis() - time) / 1000.0;
memAfter[i] = usedMemory();
memDuring[i] = memoryMeter.stopMeasurements();
ModelUtil.logInfo("share project - iteration #" + (i + 1) + ": time=" + times[i] + ", memory used before: "
+ memBefore[i] / 1024 / 1024 + "MB, during: " + memDuring[i] / 1024 / 1024 + "MB, after: "
+ memAfter[i] / 1024 / 1024 + "MB");
// if (i > 0 && memAfter[i] > memAfterThreshold * ACCEPTED_VARIANCE) {
// fail();
// }
memAfterThreshold = memAfter[i];
// Configuration.getClientBehavior().flushCommandStack();
System.out.println(usedMemory() / 1024 / 1024 + " MB");
} // for loop with iterations
ModelUtil.logInfo("times=" + Arrays.toString(times));
}
/**
* Measures average time, spent for the checkout operation. Opens projects of different sizes, shares them with the
* server, checkouts and then deletes them.
*
* @see org.unicase.emfstore.EmfStore#createProject(org.eclipse.emf.emfstore.server.model.SessionId, String, String,
* org.eclipse.emf.emfstore.server.model.versioning.LogMessage, Project)
* @see org.unicase.emfstore.EmfStore#getProjectList(org.eclipse.emf.emfstore.server.model.SessionId)
* @throws ESException in case of failure.
*/
@Test
public void testCheckoutProject() throws ESException {
ProjectUtil.share(getUsersession(), getLocalProject());
long memAfterThreshold = 0;
for (int i = 0; i < NUM_ITERATIONS; i++) {
memoryMeter.startMeasurements();
memBefore[i] = usedMemory();
long time = System.currentTimeMillis();
ProjectUtil.checkout(getLocalProject());
times[i] = (System.currentTimeMillis() - time) / 1000.0;
memAfter[i] = usedMemory();
memDuring[i] = memoryMeter.stopMeasurements();
ModelUtil.logInfo("checkout project " + getProjectSpace().getProjectName() + " iteration #" + (i + 1)
+ ": time=" + times[i] + ", memory used before: " + memBefore[i] / 1024 / 1024 + "MB, during: "
+ memDuring[i] / 1024 / 1024 + "MB, after: " + memAfter[i] / 1024 / 1024 + "MB");
if (i > 0 && memAfter[i] > memAfterThreshold * 1.2) {
fail("Memory consumption too high.");
}
memAfterThreshold = memAfter[i];
}
ModelUtil.logInfo("times=" + Arrays.toString(times));
}
/**
* Measures average time, spent for the commit and update operations. Opens projects of different sizes, shares them
* with the server and checks it out as two different projects. Then the test generates changes in one of the
* projects, using the ModelMutator, commits them to the server, and updates the second project. The test performs
* model change, commit and update NUM_ITERATIONS times and calculates times for commit and update operations
*
* @see org.unicase.emfstore.EmfStore#createProject(org.eclipse.emf.emfstore.server.model.SessionId, String, String,
* org.eclipse.emf.emfstore.server.model.versioning.LogMessage, Project)
* @see org.unicase.emfstore.EmfStore#getProjectList(org.eclipse.emf.emfstore.server.model.SessionId)
* @throws ESException in case of failure.
*/
@Test
public void testCommitAndUpdateProject() throws ESException {
getLocalProject().shareProject(nullMonitor());
final ESLocalProject checkout = ProjectUtil.checkout(getLocalProject());
double[] modelChangeTimes = new double[NUM_ITERATIONS];
double[] commitTimes = new double[NUM_ITERATIONS];
double[] updateTimes = new double[NUM_ITERATIONS];
long[] memBeforeMut = new long[NUM_ITERATIONS];
long[] memDuringMut = new long[NUM_ITERATIONS];
long[] memAfterMut = new long[NUM_ITERATIONS];
long[] memDuringCommit = new long[NUM_ITERATIONS];
long[] memAfterCommit = new long[NUM_ITERATIONS];
long[] memDuringUpdate = new long[NUM_ITERATIONS];
long[] memAfterUpdate = new long[NUM_ITERATIONS];
for (int i = 0; i < NUM_ITERATIONS; i++) {
memoryMeter.startMeasurements();
memBeforeMut[i] = usedMemory();
long time = System.currentTimeMillis();
// TODO: Nr of changes
changeModel(getProjectSpace(), NR_OF_CHANGES);
modelChangeTimes[i] = (System.currentTimeMillis() - time) / 1000.0;
memDuringMut[i] = memoryMeter.stopMeasurements();
memAfterMut[i] = usedMemory();
ModelUtil.logInfo("change model- iteration #" + (i + 1) + ": time=" + modelChangeTimes[i]
+ " memory used before:" + memBeforeMut[i] / 1024 / 1024 + "MB, during: " + memDuringMut[i] / 1024
/ 1024 + "MB, after: " + memAfterMut[i] / 1024 / 1024 + "MB");
System.out.println("VERSION BEFORE commit:" + getLocalProject().getBaseVersion().getIdentifier());
time = System.currentTimeMillis();
memoryMeter.startMeasurements();
time = System.currentTimeMillis();
getLocalProject().commit(null, null, null);
commitTimes[i] = (System.currentTimeMillis() - time) / 1000.0;
memDuringCommit[i] = memoryMeter.stopMeasurements();
memAfterCommit[i] = usedMemory();
ModelUtil.logInfo("commit project - iteration #" + (i + 1) + ": time=" + commitTimes[i]
+ ", memory used before: " + memAfterMut[i] / 1024 / 1024 + "MB, during: " + memDuringCommit[i] / 1024
/ 1024 + "MB, after: " + memAfterCommit[i] / 1024 / 1024 + "MB");
if (i > 0 && memAfter[i] > memAfterThreshold * ACCEPTED_VARIANCE) {
fail();
}
memAfterThreshold = memAfter[i];
memoryMeter.startMeasurements();
time = System.currentTimeMillis();
checkout.update(new NullProgressMonitor());
updateTimes[i] = (System.currentTimeMillis() - time) / 1000.0;
// TODO: re-enable clean memory task
// CleanMemoryTask task = new CleanMemoryTask(ESWorkspaceProviderImpl.getInstance().getCurrentWorkspace()
// .getResourceSet());
// task.run();
memDuringUpdate[i] = memoryMeter.stopMeasurements();
memAfterUpdate[i] = usedMemory();
ModelUtil.logInfo("update project - iteration #" + (i + 1) + ": time=" + updateTimes[i]
+ ", memory used before: " + memAfterCommit[i] / 1024 / 1024 + "MB, during: " + memDuringUpdate[i]
/ 1024 / 1024 + "MB, after: " + memAfterUpdate[i] / 1024 / 1024 + "MB");
if (i > 0 && memAfter[i] > memAfterThreshold * ACCEPTED_VARIANCE) {
fail();
}
memAfterThreshold = memAfter[i];
}
ModelUtil.logInfo("Mutate model - average=" + Calculate.average(modelChangeTimes) + ", min="
+ Calculate.min(modelChangeTimes) + ", max=" + Calculate.max(modelChangeTimes) + ", mean="
+ Calculate.mean(modelChangeTimes));
}
private void initMeasurments() {
memoryMeter = new MemoryMeter();
memoryMeter.start();
times = new double[NUM_ITERATIONS];
memBefore = new long[NUM_ITERATIONS];
memDuring = new long[NUM_ITERATIONS];
memAfter = new long[NUM_ITERATIONS];
}
public static long usedMemory() {
Runtime.getRuntime().gc();
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
private static IProgressMonitor nullMonitor() {
return new NullProgressMonitor();
}
public void generateModels(final ProjectSpace projectSpace, int numberOfModleElements) {
lastSeed = lastSeed == seed ? seed + 1 : seed;
final ESModelMutatorConfiguration mmc = new ESModelMutatorConfiguration(
ESModelMutatorUtil.getEPackage(MODEL_KEY),
projectSpace.getProject(), lastSeed);
mmc.setMaxDeleteCount(1);
mmc.setUseEcoreUtilDelete(false);
mmc.setMinObjectsCount(numberOfModleElements);
mmc.setEditingDomain(ESWorkspaceProviderImpl.getInstance().getInternalWorkspace().getEditingDomain());
Collection<EStructuralFeature> features = new ArrayList<EStructuralFeature>();
features.add(org.eclipse.emf.emfstore.internal.common.model.ModelPackage.eINSTANCE.getProject_CutElements());
mmc.seteStructuralFeaturesToIgnore(features);
RunESCommand.run(new ESVoidCallable() {
@Override
public void run() {
ESDefaultModelMutator.generateModel(mmc);
}
});
// System.out.println("Number of changes: " + projectSpace.getOperations().size());
}
public void changeModel(final ProjectSpace prjSpace, final int nrOfChanges) {
lastSeed = lastSeed == seed ? seed + 1 : seed;
final ESModelMutatorConfiguration mmc = new ESModelMutatorConfiguration(
ESModelMutatorUtil.getEPackage(MODEL_KEY),
prjSpace.getProject(), lastSeed);
mmc.setMaxDeleteCount(1);
mmc.setUseEcoreUtilDelete(false);
mmc.setMinObjectsCount(1);
mmc.setEditingDomain(ESWorkspaceProviderImpl.getInstance().getInternalWorkspace().getEditingDomain());
Collection<EStructuralFeature> features = new ArrayList<EStructuralFeature>();
features.add(org.eclipse.emf.emfstore.internal.common.model.ModelPackage.eINSTANCE.getProject_CutElements());
mmc.seteStructuralFeaturesToIgnore(features);
List<EPackage> packages = new ArrayList<EPackage>();
packages.add(BowlingPackage.eINSTANCE);
mmc.setModelPackages(packages);
long time = System.currentTimeMillis();
RunESCommand.run(new ESVoidCallable() {
@Override
public void run() {
mmc.setMinObjectsCount(nrOfChanges);
ESDefaultModelMutator.changeModel(mmc);
}
});
System.out.println("Changed model: " + (System.currentTimeMillis() - time) / 1000.0 + "sec");
// System.out.println("Number of changes: " + prjSpace.getOperations().size());
}
}