aurora-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ma...@apache.org
Subject aurora git commit: Implementing benchmark for snapshot restore.
Date Mon, 18 May 2015 19:35:31 GMT
Repository: aurora
Updated Branches:
  refs/heads/master 07ab0bbf4 -> 209ab932e


Implementing benchmark for snapshot restore.

Bugs closed: AURORA-1318, AURORA-1321

Reviewed at https://reviews.apache.org/r/34301/


Project: http://git-wip-us.apache.org/repos/asf/aurora/repo
Commit: http://git-wip-us.apache.org/repos/asf/aurora/commit/209ab932
Tree: http://git-wip-us.apache.org/repos/asf/aurora/tree/209ab932
Diff: http://git-wip-us.apache.org/repos/asf/aurora/diff/209ab932

Branch: refs/heads/master
Commit: 209ab932e791015245aebd1d0c8723f161f3e4b3
Parents: 07ab0bb
Author: Maxim Khutornenko <maxim@apache.org>
Authored: Mon May 18 12:35:19 2015 -0700
Committer: Maxim Khutornenko <maxim@apache.org>
Committed: Mon May 18 12:35:19 2015 -0700

----------------------------------------------------------------------
 .../org/apache/aurora/benchmark/JobUpdates.java | 119 +++++++++++++++++
 .../aurora/benchmark/SnapshotBenchmarks.java    | 130 +++++++++++++++++++
 .../aurora/benchmark/UpdateStoreBenchmarks.java | 103 +++++----------
 .../aurora/scheduler/storage/db/DbModule.java   |  21 ++-
 4 files changed, 301 insertions(+), 72 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/aurora/blob/209ab932/src/jmh/java/org/apache/aurora/benchmark/JobUpdates.java
----------------------------------------------------------------------
diff --git a/src/jmh/java/org/apache/aurora/benchmark/JobUpdates.java b/src/jmh/java/org/apache/aurora/benchmark/JobUpdates.java
new file mode 100644
index 0000000..3c6d4c9
--- /dev/null
+++ b/src/jmh/java/org/apache/aurora/benchmark/JobUpdates.java
@@ -0,0 +1,119 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.benchmark;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.UUID;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+import org.apache.aurora.gen.ExecutorConfig;
+import org.apache.aurora.gen.InstanceTaskConfig;
+import org.apache.aurora.gen.JobInstanceUpdateEvent;
+import org.apache.aurora.gen.JobKey;
+import org.apache.aurora.gen.JobUpdate;
+import org.apache.aurora.gen.JobUpdateAction;
+import org.apache.aurora.gen.JobUpdateDetails;
+import org.apache.aurora.gen.JobUpdateEvent;
+import org.apache.aurora.gen.JobUpdateInstructions;
+import org.apache.aurora.gen.JobUpdateKey;
+import org.apache.aurora.gen.JobUpdateSettings;
+import org.apache.aurora.gen.JobUpdateStatus;
+import org.apache.aurora.gen.JobUpdateSummary;
+import org.apache.aurora.gen.Range;
+import org.apache.aurora.gen.TaskConfig;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateDetails;
+
+/**
+ * Job update factory.
+ */
+final class JobUpdates {
+
+  static final class Builder {
+    private static final String USER = "user";
+    private int numEvents = 1;
+    private int numInstanceEvents = 5000;
+
+    Builder setNumEvents(int newCount) {
+      numEvents = newCount;
+      return this;
+    }
+
+    Builder setNumInstanceEvents(int newCount) {
+      numInstanceEvents = newCount;
+      return this;
+    }
+
+    Set<IJobUpdateDetails> build(int count) {
+      ImmutableSet.Builder<IJobUpdateDetails> result = ImmutableSet.builder();
+      for (int i = 0; i < count; i++) {
+        JobKey job = new JobKey("role", "env", UUID.randomUUID().toString());
+        JobUpdateKey key = new JobUpdateKey().setJob(job).setId(UUID.randomUUID().toString());
+
+        TaskConfig task = new TaskConfig()
+            .setJob(job)
+            .setExecutorConfig(new ExecutorConfig("cfg", string(10000)));
+
+        JobUpdate update = new JobUpdate()
+            .setSummary(new JobUpdateSummary()
+                .setKey(key)
+                .setUpdateId(key.getId())
+                .setJobKey(job)
+                .setUser(USER))
+            .setInstructions(new JobUpdateInstructions()
+                .setSettings(new JobUpdateSettings()
+                    .setUpdateGroupSize(100)
+                    .setMaxFailedInstances(1)
+                    .setMaxPerInstanceFailures(1)
+                    .setMaxWaitToInstanceRunningMs(1)
+                    .setMinWaitInInstanceRunningMs(1)
+                    .setRollbackOnFailure(true)
+                    .setWaitForBatchCompletion(false))
+                .setInitialState(ImmutableSet.of(new InstanceTaskConfig()
+                    .setTask(task)
+                    .setInstances(ImmutableSet.of(new Range(0, 10)))))
+                .setDesiredState(new InstanceTaskConfig()
+                    .setTask(task)
+                    .setInstances(ImmutableSet.of(new Range(0, numInstanceEvents)))));
+
+        ImmutableList.Builder<JobUpdateEvent> events = ImmutableList.builder();
+        for (int j = 0; j < numEvents; j++) {
+          events.add(new JobUpdateEvent(JobUpdateStatus.ROLLING_FORWARD, j)
+              .setUser(USER)
+              .setMessage("message"));
+        }
+
+        ImmutableList.Builder<JobInstanceUpdateEvent> instances = ImmutableList.builder();
+        for (int k = 0; k < numInstanceEvents; k++) {
+          instances.add(new JobInstanceUpdateEvent(k, 0L, JobUpdateAction.INSTANCE_UPDATING));
+        }
+
+        result.add(IJobUpdateDetails.build(new JobUpdateDetails()
+            .setUpdate(update)
+            .setUpdateEvents(events.build())
+            .setInstanceEvents(instances.build())));
+      }
+
+      return result.build();
+    }
+
+    private static String string(int numChars) {
+      char[] chars = new char[numChars];
+      Arrays.fill(chars, 'a');
+      return new String(chars);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/209ab932/src/jmh/java/org/apache/aurora/benchmark/SnapshotBenchmarks.java
----------------------------------------------------------------------
diff --git a/src/jmh/java/org/apache/aurora/benchmark/SnapshotBenchmarks.java b/src/jmh/java/org/apache/aurora/benchmark/SnapshotBenchmarks.java
new file mode 100644
index 0000000..03dd5d9
--- /dev/null
+++ b/src/jmh/java/org/apache/aurora/benchmark/SnapshotBenchmarks.java
@@ -0,0 +1,130 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.benchmark;
+
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Singleton;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.twitter.common.inject.Bindings;
+import com.twitter.common.stats.StatsProvider;
+import com.twitter.common.util.Clock;
+
+import org.apache.aurora.benchmark.fakes.FakeStatsProvider;
+import org.apache.aurora.gen.Lock;
+import org.apache.aurora.gen.LockKey;
+import org.apache.aurora.gen.storage.Snapshot;
+import org.apache.aurora.gen.storage.StoredJobUpdateDetails;
+import org.apache.aurora.scheduler.storage.Storage;
+import org.apache.aurora.scheduler.storage.db.DbModule;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateDetails;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateKey;
+import org.apache.aurora.scheduler.storage.log.SnapshotStoreImpl;
+import org.apache.thrift.TException;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+
+/**
+ * Performance benchmarks for snapshot related operations.
+ */
+public class SnapshotBenchmarks {
+  @BenchmarkMode(Mode.Throughput)
+  @OutputTimeUnit(TimeUnit.SECONDS)
+  @Warmup(iterations = 1, time = 10, timeUnit = TimeUnit.SECONDS)
+  @Measurement(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS)
+  @Fork(1)
+  @Threads(1)
+  @State(Scope.Thread)
+  public static class RestoreSnapshotWithUpdatesBenchmark {
+    private SnapshotStoreImpl snapshotStore;
+    private Snapshot snapshot;
+
+    @Param({"1", "5", "10"})
+    private int updateCount;
+
+    @Setup(Level.Trial)
+    public void setUp() {
+      snapshotStore = getSnapshotStore();
+    }
+
+    @Setup(Level.Iteration)
+    public void setUpIteration() {
+      snapshot = createSnapshot(updateCount, 100, 10000);
+    }
+
+    @Benchmark
+    public boolean run() throws TException {
+      snapshotStore.applySnapshot(snapshot);
+      // Return non-guessable result to satisfy "blackhole" requirement.
+      return System.currentTimeMillis() % 5 == 0;
+    }
+  }
+
+  private static SnapshotStoreImpl getSnapshotStore() {
+    Bindings.KeyFactory keyFactory = Bindings.annotatedKeyFactory(Storage.Volatile.class);
+    Injector injector = Guice.createInjector(
+        new AbstractModule() {
+          @Override
+          protected void configure() {
+            bind(Clock.class).toInstance(Clock.SYSTEM_CLOCK);
+            bind(StatsProvider.class).toInstance(new FakeStatsProvider());
+            bind(SnapshotStoreImpl.class).in(Singleton.class);
+          }
+        },
+        DbModule.testModule(new DbModule.TaskStoreModule(keyFactory), keyFactory));
+
+    Storage storage = injector.getInstance(Key.get(Storage.class, Storage.Volatile.class));
+    storage.prepare();
+    return injector.getInstance(SnapshotStoreImpl.class);
+  }
+
+  private static Snapshot createSnapshot(int updates, int events, int instanceEvents) {
+    Set<IJobUpdateDetails> updateDetails = new JobUpdates.Builder()
+        .setNumEvents(events)
+        .setNumInstanceEvents(instanceEvents)
+        .build(updates);
+
+    ImmutableSet.Builder<Lock> lockBuilder = ImmutableSet.builder();
+    ImmutableSet.Builder<StoredJobUpdateDetails> detailsBuilder = ImmutableSet.builder();
+    for (IJobUpdateDetails details : updateDetails) {
+      IJobUpdateKey key = details.getUpdate().getSummary().getKey();
+      String lockToken = UUID.randomUUID().toString();
+
+      lockBuilder.add(new Lock(LockKey.job(key.getJob().newBuilder()), lockToken, "user",
0L));
+      detailsBuilder.add(new StoredJobUpdateDetails(details.newBuilder(), lockToken));
+    }
+
+    return new Snapshot()
+        .setLocks(lockBuilder.build())
+        .setJobUpdateDetails(detailsBuilder.build());
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/209ab932/src/jmh/java/org/apache/aurora/benchmark/UpdateStoreBenchmarks.java
----------------------------------------------------------------------
diff --git a/src/jmh/java/org/apache/aurora/benchmark/UpdateStoreBenchmarks.java b/src/jmh/java/org/apache/aurora/benchmark/UpdateStoreBenchmarks.java
index e526929..f361caa 100644
--- a/src/jmh/java/org/apache/aurora/benchmark/UpdateStoreBenchmarks.java
+++ b/src/jmh/java/org/apache/aurora/benchmark/UpdateStoreBenchmarks.java
@@ -13,12 +13,13 @@
  */
 package org.apache.aurora.benchmark;
 
-import java.util.Arrays;
+import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
@@ -26,27 +27,12 @@ import com.twitter.common.stats.StatsProvider;
 import com.twitter.common.util.Clock;
 
 import org.apache.aurora.benchmark.fakes.FakeStatsProvider;
-import org.apache.aurora.gen.ExecutorConfig;
-import org.apache.aurora.gen.InstanceTaskConfig;
-import org.apache.aurora.gen.JobInstanceUpdateEvent;
-import org.apache.aurora.gen.JobKey;
-import org.apache.aurora.gen.JobUpdate;
-import org.apache.aurora.gen.JobUpdateAction;
-import org.apache.aurora.gen.JobUpdateEvent;
-import org.apache.aurora.gen.JobUpdateInstructions;
-import org.apache.aurora.gen.JobUpdateKey;
-import org.apache.aurora.gen.JobUpdateSettings;
-import org.apache.aurora.gen.JobUpdateStatus;
-import org.apache.aurora.gen.JobUpdateSummary;
 import org.apache.aurora.gen.Lock;
 import org.apache.aurora.gen.LockKey;
-import org.apache.aurora.gen.Range;
-import org.apache.aurora.gen.TaskConfig;
 import org.apache.aurora.scheduler.storage.JobUpdateStore;
 import org.apache.aurora.scheduler.storage.Storage;
 import org.apache.aurora.scheduler.storage.db.DbModule;
 import org.apache.aurora.scheduler.storage.entities.IJobInstanceUpdateEvent;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdate;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateDetails;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateEvent;
 import org.apache.aurora.scheduler.storage.entities.IJobUpdateKey;
@@ -63,6 +49,7 @@ import org.openjdk.jmh.annotations.Param;
 import org.openjdk.jmh.annotations.Scope;
 import org.openjdk.jmh.annotations.Setup;
 import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
 import org.openjdk.jmh.annotations.Warmup;
 
 public class UpdateStoreBenchmarks {
@@ -76,7 +63,7 @@ public class UpdateStoreBenchmarks {
   public static class JobDetailsBenchmark {
     private static final String USER = "user";
     private Storage storage;
-    private IJobUpdateKey key;
+    private Set<IJobUpdateKey> keys;
 
     @Param({"1000", "5000", "10000"})
     private int instances;
@@ -98,66 +85,45 @@ public class UpdateStoreBenchmarks {
 
     @Setup(Level.Iteration)
     public void setUpIteration() {
-      final JobKey job = new JobKey("role", "env", UUID.randomUUID().toString());
-      key = IJobUpdateKey.build(new JobUpdateKey()
-          .setJob(job)
-          .setId(UUID.randomUUID().toString()));
-
-      TaskConfig task = new TaskConfig()
-          .setJob(job)
-          .setExecutorConfig(new ExecutorConfig("cfg", string(10000)));
-
-      final JobUpdate update = new JobUpdate()
-          .setSummary(new JobUpdateSummary()
-              .setKey(key.newBuilder())
-              .setUpdateId(key.getId())
-              .setJobKey(job)
-              .setUser(USER))
-          .setInstructions(new JobUpdateInstructions()
-              .setSettings(new JobUpdateSettings()
-                  .setUpdateGroupSize(100)
-                  .setMaxFailedInstances(1)
-                  .setMaxPerInstanceFailures(1)
-                  .setMaxWaitToInstanceRunningMs(1)
-                  .setMinWaitInInstanceRunningMs(1)
-                  .setRollbackOnFailure(true)
-                  .setWaitForBatchCompletion(false))
-              .setInitialState(ImmutableSet.of(new InstanceTaskConfig()
-                  .setTask(task)
-                  .setInstances(ImmutableSet.of(new Range(0, 10)))))
-              .setDesiredState(new InstanceTaskConfig()
-                  .setTask(task)
-                  .setInstances(ImmutableSet.of(new Range(0, instances)))));
-
       storage.write(new Storage.MutateWork.NoResult.Quiet() {
         @Override
         protected void execute(Storage.MutableStoreProvider storeProvider) {
-          String lockToken = UUID.randomUUID().toString();
-          storeProvider.getLockStore().saveLock(
-              ILock.build(new Lock(LockKey.job(job), lockToken, USER, 0L)));
-
           JobUpdateStore.Mutable updateStore = storeProvider.getJobUpdateStore();
-          updateStore.saveJobUpdate(IJobUpdate.build(update), Optional.of(lockToken));
-          updateStore.saveJobUpdateEvent(
-              key,
-              IJobUpdateEvent.build(new JobUpdateEvent(JobUpdateStatus.ROLLING_FORWARD, 0L)
-                  .setUser(USER)
-                  .setMessage("message")));
+          Set<IJobUpdateDetails> updates =
+              new JobUpdates.Builder().setNumInstanceEvents(instances).build(1);
+
+          ImmutableSet.Builder<IJobUpdateKey> keyBuilder = ImmutableSet.builder();
+          for (IJobUpdateDetails details : updates) {
+            IJobUpdateKey key = details.getUpdate().getSummary().getKey();
+            keyBuilder.add(key);
+            String lockToken = UUID.randomUUID().toString();
+            storeProvider.getLockStore().saveLock(
+                ILock.build(new Lock(LockKey.job(key.getJob().newBuilder()), lockToken, USER,
0L)));
+
+            updateStore.saveJobUpdate(details.getUpdate(), Optional.of(lockToken));
+
+            for (IJobUpdateEvent updateEvent : details.getUpdateEvents()) {
+              updateStore.saveJobUpdateEvent(key, updateEvent);
+            }
 
-          for (int i = 0; i < instances; i++) {
-            updateStore.saveJobInstanceUpdateEvent(
-                key,
-                IJobInstanceUpdateEvent.build(
-                    new JobInstanceUpdateEvent(i, 0L, JobUpdateAction.INSTANCE_UPDATING)));
+            for (IJobInstanceUpdateEvent instanceEvent : details.getInstanceEvents()) {
+              updateStore.saveJobInstanceUpdateEvent(key, instanceEvent);
+            }
           }
+          keys = keyBuilder.build();
         }
       });
     }
 
-    private static String string(int numChars) {
-      char[] chars = new char[numChars];
-      Arrays.fill(chars, 'a');
-      return new String(chars);
+    @TearDown(Level.Iteration)
+    public void tearDownIteration() {
+      storage.write(new Storage.MutateWork.NoResult.Quiet() {
+        @Override
+        protected void execute(Storage.MutableStoreProvider storeProvider) {
+          storeProvider.getJobUpdateStore().deleteAllUpdatesAndEvents();
+          storeProvider.getLockStore().deleteLocks();
+        }
+      });
     }
 
     @Benchmark
@@ -165,7 +131,8 @@ public class UpdateStoreBenchmarks {
       return storage.read(new Storage.Work.Quiet<IJobUpdateDetails>() {
         @Override
         public IJobUpdateDetails apply(Storage.StoreProvider store) {
-          return store.getJobUpdateStore().fetchJobUpdateDetails(key).get();
+          return store.getJobUpdateStore().fetchJobUpdateDetails(
+              Iterables.getOnlyElement(keys)).get();
         }
       });
     }

http://git-wip-us.apache.org/repos/asf/aurora/blob/209ab932/src/main/java/org/apache/aurora/scheduler/storage/db/DbModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/DbModule.java b/src/main/java/org/apache/aurora/scheduler/storage/db/DbModule.java
index e351588..436d384 100644
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/DbModule.java
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/DbModule.java
@@ -109,21 +109,34 @@ public final class DbModule extends PrivateModule {
 
   /**
    * Creates a module that will prepare a private in-memory database, using a specific task
store
-   * implementation bound within the provided module.
+   * implementation bound within the provided module and a key factory.
    *
    * @param taskStoreModule Module providing task store bindings.
+   * @param keyFactory Key factory to use.
    * @return A new database module for testing.
    */
   @VisibleForTesting
-  public static Module testModule(Module taskStoreModule) {
+  public static Module testModule(Module taskStoreModule, KeyFactory keyFactory) {
     return new DbModule(
-        KeyFactory.PLAIN,
+        keyFactory,
         taskStoreModule,
         // A non-zero close delay is used here to avoid eager database cleanup in tests that
         // make use of multiple threads.  Since all test databases are separately scoped
by the
         // included UUID, multiple DB instances will overlap in time but they should be distinct
         // in content.
-        "testdb-" + UUID.randomUUID().toString() + ";DB_CLOSE_DELAY=5");
+        "testdb-" + UUID.randomUUID().toString() + ";DB_CLOSE_DELAY=5;");
+  }
+
+  /**
+   * Creates a module that will prepare a private in-memory database using specific task
store
+   * module.
+   *
+   * @param taskStoreModule Module providing task store bindings.
+   * @return A new database module for testing.
+   */
+  @VisibleForTesting
+  public static Module testModule(Module taskStoreModule) {
+    return testModule(taskStoreModule, KeyFactory.PLAIN);
   }
 
   /**


Mime
View raw message