You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/07/01 12:53:52 UTC
[3/4] git commit: Testing performance of entity persistence
Testing performance of entity persistence
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/870a1b8f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/870a1b8f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/870a1b8f
Branch: refs/heads/master
Commit: 870a1b8fb66792f45db372f2b3a2752dd8680d09
Parents: b8f1a04
Author: Aled Sage <al...@gmail.com>
Authored: Tue Jun 24 08:19:20 2014 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Jul 1 11:06:33 2014 +0100
----------------------------------------------------------------------
.../BrooklynMementoPersisterToObjectStore.java | 16 +-
.../rebind/persister/MementoFileWriter.java | 2 +-
.../entity/rebind/RebindTestFixture.java | 12 +-
.../SshMachineLocationPerformanceTest.java | 11 +-
.../qa/performance/AbstractPerformanceTest.java | 10 +-
.../qa/performance/EntityPerformanceTest.java | 2 +-
.../EntityPersistencePerformanceTest.java | 81 +++++++++
.../FilePersistencePerformanceTest.java | 171 +++++++++++++++++++
.../GroovyYardStickPerformanceTest.groovy | 44 +++++
.../JavaYardStickPerformanceTest.java | 4 +-
.../qa/performance/PerformanceTestUtils.java | 81 +++++++++
.../java/brooklyn/test/policy/TestPolicy.java | 5 +
12 files changed, 415 insertions(+), 24 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/870a1b8f/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
index dec2bf7..54f4943 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
@@ -266,9 +266,10 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
if (LOG.isDebugEnabled()) LOG.debug("Ignoring checkpointing entire memento, because not running");
return;
}
- if (LOG.isDebugEnabled()) LOG.debug("Checkpointing entire memento");
objectStore.prepareForMasterUse();
+ Stopwatch stopwatch = Stopwatch.createStarted();
+
for (EntityMemento entity : newMemento.getEntityMementos().values()) {
persist("entities", entity);
}
@@ -281,6 +282,8 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
for (EnricherMemento enricher : newMemento.getEnricherMementos().values()) {
persist("enrichers", enricher);
}
+
+ if (LOG.isDebugEnabled()) LOG.debug("Checkpointed entire memento in {}", Time.makeTimeStringRounded(stopwatch));
}
@Override
@@ -289,12 +292,10 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
if (LOG.isDebugEnabled()) LOG.debug("Ignoring checkpointed delta of memento, because not running");
return;
}
- if (LOG.isDebugEnabled()) LOG.debug("Checkpointed delta of memento; updating {} entities, {} locations and {} policies; " +
- "removing {} entities, {} locations and {} policies",
- new Object[] {delta.entities(), delta.locations(), delta.policies(),
- delta.removedEntityIds(), delta.removedLocationIds(), delta.removedPolicyIds()});
objectStore.prepareForMasterUse();
+ Stopwatch stopwatch = Stopwatch.createStarted();
+
for (EntityMemento entity : delta.entities()) {
persist("entities", entity);
}
@@ -320,6 +321,11 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
for (String id : delta.removedEnricherIds()) {
delete("enrichers", id);
}
+
+ if (LOG.isDebugEnabled()) LOG.debug("Checkpointed delta of memento in {}; updated {} entities, {} locations and {} policies; " +
+ "removing {} entities, {} locations and {} policies",
+ new Object[] {Time.makeTimeStringRounded(stopwatch), delta.entities(), delta.locations(), delta.policies(),
+ delta.removedEntityIds(), delta.removedLocationIds(), delta.removedPolicyIds()});
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/870a1b8f/core/src/main/java/brooklyn/entity/rebind/persister/MementoFileWriter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/MementoFileWriter.java b/core/src/main/java/brooklyn/entity/rebind/persister/MementoFileWriter.java
index 83af866..959f875 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/MementoFileWriter.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/MementoFileWriter.java
@@ -32,7 +32,7 @@ import brooklyn.util.time.Time;
* scheduled, we will just rely on the existing one; otherwise we will write now.
*
* @author aled
- * @deprecated used only by now-deprecated {@link BrooklynMementoPersisterToMultiFile},
+ * @deprecated since 0.7.0; used only by now-deprecated {@link BrooklynMementoPersisterToMultiFile},
* impl largely moved to {@link FileBasedStoreObjectAccessor}
*/
@Deprecated
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/870a1b8f/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
index 92effff..89ac7a1 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
@@ -2,6 +2,8 @@ package brooklyn.entity.rebind;
import java.io.File;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -21,6 +23,8 @@ import brooklyn.util.time.Duration;
public abstract class RebindTestFixture<T extends StartableApplication> {
+ private static final Logger LOG = LoggerFactory.getLogger(RebindTestFixture.class);
+
protected static final Duration TIMEOUT_MS = Duration.TEN_SECONDS;
protected ClassLoader classLoader = getClass().getClassLoader();
@@ -40,8 +44,14 @@ public abstract class RebindTestFixture<T extends StartableApplication> {
origEnricherPersistenceEnabled = BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_ENRICHER_PERSISTENCE_PROPERTY);
mementoDir = Os.newTempDir(getClass());
- origManagementContext = RebindTestUtils.newPersistingManagementContext(mementoDir, classLoader, 1);
+ origManagementContext = RebindTestUtils.newPersistingManagementContext(mementoDir, classLoader, getPersistPeriodMillis());
origApp = createApp();
+
+ LOG.info("Test "+getClass()+" persisting to "+mementoDir);
+ }
+
+ protected int getPersistPeriodMillis() {
+ return 1;
}
/** optionally, create the app as part of every test; can be no-op if tests wish to set origApp themselves */
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/870a1b8f/core/src/test/java/brooklyn/location/basic/SshMachineLocationPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/location/basic/SshMachineLocationPerformanceTest.java b/core/src/test/java/brooklyn/location/basic/SshMachineLocationPerformanceTest.java
index ee8fa44..f2d40aa 100644
--- a/core/src/test/java/brooklyn/location/basic/SshMachineLocationPerformanceTest.java
+++ b/core/src/test/java/brooklyn/location/basic/SshMachineLocationPerformanceTest.java
@@ -1,22 +1,19 @@
package brooklyn.location.basic;
import java.io.ByteArrayOutputStream;
-import java.lang.management.ManagementFactory;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import brooklyn.qa.performance.PerformanceTestUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.net.Networking;
@@ -125,9 +122,7 @@ public class SshMachineLocationPerformanceTest {
}
private void runMany(final Runnable task, final String context, int concurrentRuns, int iterations) throws Exception {
- MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
- ObjectName osMBeanName = ObjectName.getInstance(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
- long preCpuTime = (Long) mbeanServer.getAttribute(osMBeanName, "ProcessCpuTime");
+ long preCpuTime = PerformanceTestUtils.getProcessCpuTime();
Stopwatch stopwatch = Stopwatch.createStarted();
for (int i = 0; i < iterations; i++) {
@@ -145,7 +140,7 @@ public class SshMachineLocationPerformanceTest {
}
Futures.allAsList(futures).get();
- long postCpuTime = (Long) mbeanServer.getAttribute(osMBeanName, "ProcessCpuTime");
+ long postCpuTime = PerformanceTestUtils.getProcessCpuTime();
long elapsedTime = stopwatch.elapsed(TimeUnit.MILLISECONDS);
double fractionCpu = (elapsedTime > 0) ? ((double)postCpuTime-preCpuTime) / TimeUnit.MILLISECONDS.toNanos(elapsedTime) : -1;
LOG.info("Executing {}; completed {}; took {}; fraction cpu {}",
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/870a1b8f/core/src/test/java/brooklyn/qa/performance/AbstractPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/qa/performance/AbstractPerformanceTest.java b/core/src/test/java/brooklyn/qa/performance/AbstractPerformanceTest.java
index b395e9a..e585b7c 100644
--- a/core/src/test/java/brooklyn/qa/performance/AbstractPerformanceTest.java
+++ b/core/src/test/java/brooklyn/qa/performance/AbstractPerformanceTest.java
@@ -50,14 +50,14 @@ public class AbstractPerformanceTest {
protected SimulatedLocation loc;
@BeforeMethod(alwaysRun=true)
- public void setUp() {
+ public void setUp() throws Exception {
for (int i = 0; i < 5; i++) System.gc();
loc = new SimulatedLocation();
app = ApplicationBuilder.newManagedApp(TestApplication.class);
}
@AfterMethod(alwaysRun=true)
- public void tearDown() {
+ public void tearDown() throws Exception {
if (app != null) Entities.destroyAll(app.getManagementContext());
}
@@ -87,8 +87,7 @@ public class AbstractPerformanceTest {
long nextLogTime = logInterval;
// Give it some warm-up cycles
- Stopwatch warmupWatch = new Stopwatch();
- warmupWatch.start();
+ Stopwatch warmupWatch = Stopwatch.createStarted();
for (int i = 0; i < (numIterations/10); i++) {
if (warmupWatch.elapsed(TimeUnit.MILLISECONDS) >= nextLogTime) {
LOG.info("Warm-up "+prefix+" iteration="+i+" at "+warmupWatch.elapsed(TimeUnit.MILLISECONDS)+"ms");
@@ -97,8 +96,7 @@ public class AbstractPerformanceTest {
r.run();
}
- Stopwatch stopwatch = new Stopwatch();
- stopwatch.start();
+ Stopwatch stopwatch = Stopwatch.createStarted();
nextLogTime = 0;
for (int i = 0; i < numIterations; i++) {
if (stopwatch.elapsed(TimeUnit.MILLISECONDS) >= nextLogTime) {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/870a1b8f/core/src/test/java/brooklyn/qa/performance/EntityPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/qa/performance/EntityPerformanceTest.java b/core/src/test/java/brooklyn/qa/performance/EntityPerformanceTest.java
index b5811e6..74ab04b 100644
--- a/core/src/test/java/brooklyn/qa/performance/EntityPerformanceTest.java
+++ b/core/src/test/java/brooklyn/qa/performance/EntityPerformanceTest.java
@@ -34,7 +34,7 @@ public class EntityPerformanceTest extends AbstractPerformanceTest {
@BeforeMethod(alwaysRun=true)
@Override
- public void setUp() {
+ public void setUp() throws Exception {
super.setUp();
entities = Lists.newArrayList();
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/870a1b8f/core/src/test/java/brooklyn/qa/performance/EntityPersistencePerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/qa/performance/EntityPersistencePerformanceTest.java b/core/src/test/java/brooklyn/qa/performance/EntityPersistencePerformanceTest.java
new file mode 100644
index 0000000..3a1a16c
--- /dev/null
+++ b/core/src/test/java/brooklyn/qa/performance/EntityPersistencePerformanceTest.java
@@ -0,0 +1,81 @@
+package brooklyn.qa.performance;
+
+import java.util.List;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.testng.annotations.Test;
+
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.RebindTestFixtureWithApp;
+import brooklyn.location.LocationSpec;
+import brooklyn.location.basic.SimulatedLocation;
+import brooklyn.policy.Policy;
+import brooklyn.policy.PolicySpec;
+import brooklyn.test.entity.TestEntity;
+import brooklyn.test.policy.TestPolicy;
+import brooklyn.util.repeat.Repeater;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Callables;
+
+public class EntityPersistencePerformanceTest extends RebindTestFixtureWithApp {
+
+ // TODO Not measuring performance per cycle; just looking at CPU usage during test
+
+ protected int getPersistPeriodMillis() {
+ return 1000;
+ }
+
+ @Test(groups="Integration")
+ public void testManyEntities() throws Exception {
+ final int NUM_ENTITIES = 100;
+ final Duration TEST_LENGTH = Duration.of(60, TimeUnit.SECONDS);
+ final Duration REPEAT_EVERY = Duration.of(500, TimeUnit.MILLISECONDS);
+ run(NUM_ENTITIES, TEST_LENGTH, REPEAT_EVERY, "manyEntities");
+ }
+
+ @Test(groups="Integration")
+ public void testRapidChanges() throws Exception {
+ final int NUM_ENTITIES = 10;
+ final Duration TEST_LENGTH = Duration.of(60, TimeUnit.SECONDS);
+ final Duration REPEAT_EVERY = Duration.of(10, TimeUnit.MILLISECONDS);
+ run(NUM_ENTITIES, TEST_LENGTH, REPEAT_EVERY, "rapidChanges");
+ }
+
+ protected void run(int numEntities, Duration testLength, Duration repeatEvery, String loggingContext) throws Exception {
+ final List<TestEntity> entities = Lists.newArrayList();
+ final List<SimulatedLocation> locs = Lists.newArrayList();
+
+ for (int i = 0; i < numEntities; i++) {
+ TestEntity entity = origApp.createAndManageChild(EntitySpec.create(TestEntity.class));
+ entity.addPolicy(PolicySpec.create(TestPolicy.class));
+ SimulatedLocation loc = origManagementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
+ entities.add(entity);
+ locs.add(loc);
+ }
+
+ Future<?> future = PerformanceTestUtils.sampleProcessCpuTime(Duration.ONE_SECOND, "during "+loggingContext);
+ try {
+ Repeater.create()
+ .every(repeatEvery)
+ .repeat(new Runnable() {
+ int i = 0;
+ public void run() {
+ for (TestEntity entity : entities) {
+ entity.setAttribute(TestEntity.SEQUENCE, i++);
+ Policy policy = Iterables.find(entity.getPolicies(), Predicates.instanceOf(TestPolicy.class));
+ policy.setConfig(TestPolicy.CONF_NAME, "name-"+i);
+ }
+ }})
+ .limitTimeTo(testLength)
+ .until(Callables.returning(false))
+ .run();
+ } finally {
+ future.cancel(true);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/870a1b8f/core/src/test/java/brooklyn/qa/performance/FilePersistencePerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/qa/performance/FilePersistencePerformanceTest.java b/core/src/test/java/brooklyn/qa/performance/FilePersistencePerformanceTest.java
new file mode 100644
index 0000000..eaf81ae
--- /dev/null
+++ b/core/src/test/java/brooklyn/qa/performance/FilePersistencePerformanceTest.java
@@ -0,0 +1,171 @@
+package brooklyn.qa.performance;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.rebind.persister.FileBasedStoreObjectAccessor;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.internal.ssh.process.ProcessTool;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+
+public class FilePersistencePerformanceTest extends AbstractPerformanceTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FilePersistencePerformanceTest.class);
+
+ File file;
+ FileBasedStoreObjectAccessor fileAccessor;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ file = File.createTempFile("fileBasedStoreObject", ".txt");
+ Files.write("initial", file, Charsets.UTF_8);
+ fileAccessor = new FileBasedStoreObjectAccessor(file, "mytmpextension");
+
+ app.start(ImmutableList.of(loc));
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ if (file != null) file.delete();
+ }
+
+ protected int numIterations() {
+ return 100;
+ }
+
+ @Test(groups={"Integration", "Acceptance"})
+ public void testFileBasedStoreObjectPuts() throws Exception {
+ int numIterations = numIterations();
+ double minRatePerSec = 100 * PERFORMANCE_EXPECTATION;
+ final AtomicInteger i = new AtomicInteger();
+
+ measureAndAssert("FileBasedStoreObjectAccessor.put", numIterations, minRatePerSec, new Runnable() {
+ public void run() {
+ fileAccessor.put(""+i.incrementAndGet());
+ }});
+ }
+
+ @Test(groups={"Integration", "Acceptance"})
+ public void testFileBasedStoreObjectGet() throws Exception {
+ // The file system will have done a lot of caching here - we are unlikely to touch the disk more than once.
+ int numIterations = numIterations();
+ double minRatePerSec = 100 * PERFORMANCE_EXPECTATION;
+
+ measureAndAssert("FileBasedStoreObjectAccessor.get", numIterations, minRatePerSec, new Runnable() {
+ public void run() {
+ fileAccessor.get();
+ }});
+ }
+
+ @Test(groups={"Integration", "Acceptance"})
+ public void testFileBasedStoreObjectDelete() throws Exception {
+ int numIterations = numIterations();
+ double minRatePerSec = 100 * PERFORMANCE_EXPECTATION;
+
+ // Will do 10% warm up runs first
+ final List<File> files = Lists.newArrayList();
+ for (int i = 0; i < (numIterations * 1.1 + 1); i++) {
+ file = File.createTempFile("fileBasedStoreObjectDelete-"+i, ".txt");
+ Files.write(""+i, file, Charsets.UTF_8);
+ files.add(file);
+ }
+
+ final AtomicInteger i = new AtomicInteger();
+
+ try {
+ measureAndAssert("FileBasedStoreObjectAccessor.delete", numIterations, minRatePerSec, new Runnable() {
+ public void run() {
+ File file = files.get(i.getAndIncrement());
+ FileBasedStoreObjectAccessor fileAccessor = new FileBasedStoreObjectAccessor(file, "mytmpextension");
+ fileAccessor.delete();
+ }});
+ } finally {
+ for (File file : files) {
+ if (file != null) file.delete();
+ }
+ }
+ }
+
+ // fileAccessor.put() is implemented with an execCommands("mv") so look at performance of just that piece
+ @Test(groups={"Integration", "Acceptance"})
+ public void testProcessToolExecCommand() {
+ int numIterations = numIterations();
+ double minRatePerSec = 10 * PERFORMANCE_EXPECTATION;
+
+ measureAndAssert("ProcessTool.exec", numIterations, minRatePerSec, new Runnable() {
+ public void run() {
+ String cmd = "true";
+ new ProcessTool().execCommands(MutableMap.<String,String>of(), MutableList.of(cmd), null);
+ }});
+ }
+
+ @Test(groups={"Integration", "Acceptance"})
+ public void testJavaUtilFileRenames() {
+ int numIterations = numIterations();
+ double minRatePerSec = 10 * PERFORMANCE_EXPECTATION;
+
+ final File parentDir = file.getParentFile();
+ final AtomicInteger i = new AtomicInteger();
+
+ measureAndAssert("java.util.File.rename", numIterations, minRatePerSec, new Runnable() {
+ public void run() {
+ File newFile = new File(parentDir, "fileRename-"+i.incrementAndGet()+".txt");
+ file.renameTo(newFile);
+ file = newFile;
+ }});
+ }
+
+ @Test(groups={"Integration", "Acceptance"})
+ public void testGuavaFileWrites() {
+ int numIterations = numIterations();
+ double minRatePerSec = 10 * PERFORMANCE_EXPECTATION;
+
+ final AtomicInteger i = new AtomicInteger();
+
+ measureAndAssert("guava.Files.write", numIterations, minRatePerSec, new Runnable() {
+ public void run() {
+ try {
+ Files.write(""+i.incrementAndGet(), file, Charsets.UTF_8);
+ } catch (IOException e) {
+ throw Exceptions.propagate(e);
+ }
+ }});
+ }
+
+ @Test(groups={"Integration", "Acceptance"})
+ public void testGuavaFileMoves() {
+ int numIterations = numIterations();
+ double minRatePerSec = 10 * PERFORMANCE_EXPECTATION;
+
+ final File parentDir = file.getParentFile();
+ final AtomicInteger i = new AtomicInteger();
+
+ measureAndAssert("guava.Files.move", numIterations, minRatePerSec, new Runnable() {
+ public void run() {
+ File newFile = new File(parentDir, "fileRename-"+i.incrementAndGet()+".txt");
+ try {
+ Files.move(file, newFile);
+ } catch (IOException e) {
+ throw Exceptions.propagate(e);
+ }
+ file = newFile;
+ }});
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/870a1b8f/core/src/test/java/brooklyn/qa/performance/GroovyYardStickPerformanceTest.groovy
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/qa/performance/GroovyYardStickPerformanceTest.groovy b/core/src/test/java/brooklyn/qa/performance/GroovyYardStickPerformanceTest.groovy
new file mode 100644
index 0000000..bb385a3
--- /dev/null
+++ b/core/src/test/java/brooklyn/qa/performance/GroovyYardStickPerformanceTest.groovy
@@ -0,0 +1,44 @@
+package brooklyn.qa.performance;
+
+import static org.testng.Assert.assertTrue
+
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+import java.util.concurrent.atomic.AtomicInteger
+
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import org.testng.annotations.AfterMethod
+import org.testng.annotations.BeforeMethod
+import org.testng.annotations.Test
+
+public class GroovyYardStickPerformanceTest extends AbstractPerformanceTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(GroovyYardStickPerformanceTest.class);
+
+ protected static final long TIMEOUT_MS = 10*1000;
+
+ private ExecutorService executor;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() {
+ super.setUp();
+ executor = Executors.newCachedThreadPool();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() {
+ super.tearDown();
+ if (executor != null) executor.shutdownNow();
+ }
+
+ @Test(groups=["Integration", "Acceptance"])
+ public void testGroovyNoopToEnsureTestFrameworkIsVeryFast() {
+ int numIterations = 1000000;
+ double minRatePerSec = 1000000 * PERFORMANCE_EXPECTATION;
+ AtomicInteger i = new AtomicInteger();
+
+ measureAndAssert("noop-groovy", numIterations, minRatePerSec, { i.incrementAndGet() });
+ assertTrue(i.get() >= numIterations, "i="+i);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/870a1b8f/core/src/test/java/brooklyn/qa/performance/JavaYardStickPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/qa/performance/JavaYardStickPerformanceTest.java b/core/src/test/java/brooklyn/qa/performance/JavaYardStickPerformanceTest.java
index 8f4db29..5954b8a 100644
--- a/core/src/test/java/brooklyn/qa/performance/JavaYardStickPerformanceTest.java
+++ b/core/src/test/java/brooklyn/qa/performance/JavaYardStickPerformanceTest.java
@@ -23,13 +23,13 @@ public class JavaYardStickPerformanceTest extends AbstractPerformanceTest {
private ExecutorService executor;
@BeforeMethod(alwaysRun=true)
- public void setUp() {
+ public void setUp() throws Exception {
super.setUp();
executor = Executors.newCachedThreadPool();
}
@AfterMethod(alwaysRun=true)
- public void tearDown() {
+ public void tearDown() throws Exception {
super.tearDown();
if (executor != null) executor.shutdownNow();
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/870a1b8f/core/src/test/java/brooklyn/qa/performance/PerformanceTestUtils.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/qa/performance/PerformanceTestUtils.java b/core/src/test/java/brooklyn/qa/performance/PerformanceTestUtils.java
new file mode 100644
index 0000000..984ae30
--- /dev/null
+++ b/core/src/test/java/brooklyn/qa/performance/PerformanceTestUtils.java
@@ -0,0 +1,81 @@
+package brooklyn.qa.performance;
+
+import java.lang.management.ManagementFactory;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Stopwatch;
+
+public class PerformanceTestUtils {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PerformanceTestUtils.class);
+
+ private static boolean hasLoggedProcessCpuTimeUnavailable;
+
+ public static long getProcessCpuTime() {
+ try {
+ MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
+ ObjectName osMBeanName = ObjectName.getInstance(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
+ return (Long) mbeanServer.getAttribute(osMBeanName, "ProcessCpuTime");
+ } catch (Exception e) {
+ if (!hasLoggedProcessCpuTimeUnavailable) {
+ hasLoggedProcessCpuTimeUnavailable = true;
+ LOG.warn("ProcessCPuTime not available in local JVM MXBean "+ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME+" (only available in sun JVM?)");
+ }
+ return -1;
+ }
+ }
+
+ /**
+ * Creates a background thread that will log.info the CPU fraction usage repeatedly, sampling at the given period.
+ * Callers <em>must</em> cancel the returned future, e.g. {@code future.cancel(true)}, otherwise it will keep
+ * logging until the JVM exits.
+ */
+ public static Future<?> sampleProcessCpuTime(final Duration period, final String loggingContext) {
+ final ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
+ @Override public Thread newThread(Runnable r) {
+ Thread thread = new Thread(r, "brooklyn-sampleProcessCpuTime-"+loggingContext);
+ thread.setDaemon(true); // let the JVM exit
+ return thread;
+ }});
+ Future<?> future = executor.submit(new Runnable() {
+ @Override public void run() {
+ try {
+ long prevCpuTime = getProcessCpuTime();
+ if (prevCpuTime == -1) {
+ LOG.warn("ProcessCPuTime not available; cannot sample; aborting");
+ return;
+ }
+ while (true) {
+ Stopwatch stopwatch = Stopwatch.createStarted();
+ Thread.sleep(period.toMilliseconds());
+ long currentCpuTime = getProcessCpuTime();
+
+ long elapsedTime = stopwatch.elapsed(TimeUnit.MILLISECONDS);
+ double fractionCpu = (elapsedTime > 0) ? ((double)currentCpuTime-prevCpuTime) / TimeUnit.MILLISECONDS.toNanos(elapsedTime) : -1;
+ prevCpuTime = currentCpuTime;
+
+ LOG.info("CPU fraction over last {} was {} ({})", new Object[] {
+ Time.makeTimeStringRounded(elapsedTime), fractionCpu, loggingContext});
+ }
+ } catch (InterruptedException e) {
+ return; // graceful termination
+ } finally {
+ executor.shutdownNow();
+ }
+ }});
+ return future;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/870a1b8f/core/src/test/java/brooklyn/test/policy/TestPolicy.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/test/policy/TestPolicy.java b/core/src/test/java/brooklyn/test/policy/TestPolicy.java
index ca928e8..c5fd202 100644
--- a/core/src/test/java/brooklyn/test/policy/TestPolicy.java
+++ b/core/src/test/java/brooklyn/test/policy/TestPolicy.java
@@ -35,4 +35,9 @@ public class TestPolicy extends AbstractPolicy {
public Map<?, ?> getLeftoverProperties() {
return Collections.unmodifiableMap(leftoverProperties);
}
+
+ @Override
+ protected <T> void doReconfigureConfig(ConfigKey<T> key, T val) {
+ // no-op
+ }
}