jvpp-benchmark: introduce abstract JVppBenchmark 89/12789/1
authorMarek Gradzki <[email protected]>
Tue, 29 May 2018 14:54:49 +0000 (16:54 +0200)
committerMarek Gradzki <[email protected]>
Tue, 29 May 2018 15:22:18 +0000 (17:22 +0200)
Change-Id: I957edd6813b1be43232845d9bf6a4f13ed01ecfb
Signed-off-by: Marek Gradzki <[email protected]>
it/jvpp-benchmark/asciidoc/Readme.adoc
it/jvpp-benchmark/src/main/java/io/fd/hc2vpp/it/jvpp/benchmark/acl/AclUpdateBenchmark.java
it/jvpp-benchmark/src/main/java/io/fd/hc2vpp/it/jvpp/benchmark/classify/ClassifyTableBenchmark.java [new file with mode: 0644]
it/jvpp-benchmark/src/main/java/io/fd/hc2vpp/it/jvpp/benchmark/util/JVppBenchmark.java [moved from it/jvpp-benchmark/src/main/java/io/fd/hc2vpp/it/jvpp/benchmark/classify/ClassifyTableCreateBenchmark.java with 67% similarity]

index 65aeff2..b50327e 100644 (file)
@@ -54,7 +54,7 @@ sudo java -jar ./target/jvpp-benchmark*executable.jar -p mode=L2 AclUpdateBenchm
 ---
 
 
-== ClassifyTableCreateBenchmark
+== ClassifyTableBenchmark
 
 Synchronously creates classify tables using classifyAddDelTable operation.
 By default 20x2s warmup and 100x2s measurement iterations are performed.
@@ -68,11 +68,11 @@ Tables from the set are used in round-robin fashion.
 Run with:
 [source,shell]
 ---
-sudo java -jar ./target/jvpp-benchmark*executable.jar ClassifyTableCreateBenchmark
+sudo java -jar ./target/jvpp-benchmark*executable.jar ClassifyTableBenchmark
 ---
 
 To specify tableSetSize (default=100), use:
 [source,shell]
 ---
-sudo java -jar ./target/jvpp-benchmark*executable.jar ClassifyTableCreateBenchmark -p aclSetSize=1000
+sudo java -jar ./target/jvpp-benchmark*executable.jar ClassifyTableBenchmark -p aclSetSize=1000
 ---
index e8bf2a8..4042f8a 100644 (file)
@@ -19,8 +19,8 @@ package io.fd.hc2vpp.it.jvpp.benchmark.acl;
 import static io.fd.hc2vpp.it.jvpp.benchmark.acl.AclUpdateBenchmark.InterfaceMode.L2;
 import static io.fd.hc2vpp.it.jvpp.benchmark.acl.AclUpdateBenchmark.InterfaceMode.L3;
 
-import com.google.common.io.CharStreams;
-import io.fd.vpp.jvpp.JVppRegistryImpl;
+import io.fd.hc2vpp.it.jvpp.benchmark.util.JVppBenchmark;
+import io.fd.vpp.jvpp.JVppRegistry;
 import io.fd.vpp.jvpp.acl.JVppAclImpl;
 import io.fd.vpp.jvpp.acl.dto.AclInterfaceSetAclList;
 import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
@@ -32,41 +32,14 @@ import io.fd.vpp.jvpp.core.dto.SwInterfaceAddDelAddress;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceSetFlags;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceSetL2Bridge;
 import io.fd.vpp.jvpp.core.future.FutureJVppCoreFacade;
-import io.fd.vpp.jvpp.dto.JVppReply;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.concurrent.CompletionStage;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
 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.TearDown;
-import org.openjdk.jmh.annotations.Threads;
-import org.openjdk.jmh.annotations.Timeout;
-import org.openjdk.jmh.annotations.Warmup;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-@BenchmarkMode(Mode.AverageTime)
-@State(Scope.Thread)
-@Fork(1)
-@Threads(1)
-@Timeout(time = 5)
-@Warmup(iterations = 20, time = 2)
-@Measurement(iterations = 100, time = 2)
-@OutputTimeUnit(TimeUnit.MILLISECONDS)
-public class AclUpdateBenchmark {
+public class AclUpdateBenchmark extends JVppBenchmark {
     private static final Logger LOG = LoggerFactory.getLogger(AclUpdateBenchmark.class);
 
     @Param( {"100"})
@@ -79,84 +52,37 @@ public class AclUpdateBenchmark {
     private InterfaceMode mode;
 
     private AclProvider aclProvider;
-    private JVppRegistryImpl registry;
     private FutureJVppAclFacade jvppAcl;
     private FutureJVppCoreFacade jvppCore;
 
     @Benchmark
-    public void testMethod() throws Exception {
-        // In real application, reply may be ignored by the caller, so we ignore as well.
+    public void testUpdate() throws Exception {
+        // In a real application, reply may be ignored by the caller, so we ignore it as well.
         jvppAcl.aclAddReplace(aclProvider.next()).toCompletableFuture().get();
     }
 
-    @Setup(Level.Iteration)
-    public void setup() throws Exception {
-        initAclProvider();
-        startVpp();
-        connect();
-        initAcl();
-    }
-
-    @TearDown(Level.Iteration)
-    public void tearDown() throws Exception {
-        disconnect();
-        stopVpp();
-    }
-
-    private void initAclProvider() {
+    /**
+     * Initializes loopback interface, creates ACL and assigns it to loop0.
+     */
+    @Override
+    protected void iterationSetup() throws Exception {
         aclProvider = new AclProviderImpl(aclSetSize, aclSize);
-    }
-
-    private void startVpp() throws Exception {
-        LOG.info("Starting VPP ...");
-        final String[] cmd = {"/bin/sh", "-c", "sudo service vpp start"};
-        exec(cmd);
-        LOG.info("VPP started successfully");
-    }
-
-    private void stopVpp() throws Exception {
-        LOG.info("Stopping VPP ...");
-        final String[] cmd = {"/bin/sh", "-c", "sudo service vpp stop"};
-        exec(cmd);
-
-        // Wait to be sure VPP was stopped.
-        // Prevents VPP start failure: "vpp.service: Start request repeated too quickly".
-        Thread.sleep(1500);
-        LOG.info("VPP stopped successfully");
 
-    }
-
-    private static void exec(String[] command) throws IOException, InterruptedException {
-        Process process = Runtime.getRuntime().exec(command);
-        process.waitFor();
-        if (process.exitValue() != 0) {
-            String error_msg = "Failed to execute " + Arrays.toString(command) + ": " +
-                CharStreams.toString(new InputStreamReader(process.getErrorStream(), StandardCharsets.UTF_8));
-            throw new IllegalStateException(error_msg);
+        // Init loop0 interface
+        final int swIfIndex = initLoop0();
+        if (L3.equals(mode)) {
+            initL3(swIfIndex);
+        } else if (L2.equals(mode)) {
+            initL2(swIfIndex);
         }
-    }
-
-    private void connect() throws IOException {
-        LOG.info("Connecting to JVPP ...");
-        registry = new JVppRegistryImpl("ACLUpdateBenchmark");
-        jvppCore = new FutureJVppCoreFacade(registry, new JVppCoreImpl());
-        jvppAcl = new FutureJVppAclFacade(registry, new JVppAclImpl());
-        LOG.info("Successfully connected to JVPP");
-    }
+        // Create ACL and assign to loop0
+        final int aclId = initAcl(swIfIndex);
 
-    private void disconnect() throws Exception {
-        LOG.info("Disconnecting ...");
-        jvppAcl.close();
-        jvppCore.close();
-        registry.close();
-        LOG.info("Successfully disconnected ...");
+        // Use ACL index in subsequent executions of aclProvider.next() method
+        aclProvider.setAclIndex(aclId);
     }
 
-    /**
-     * Initializes loopback interface, creates ACL and assigns it to loop0.
-     */
-    private void initAcl()
-        throws ExecutionException, InterruptedException {
+    private int initLoop0() throws ExecutionException, InterruptedException {
         // Create loopback interface
         final CreateLoopbackReply loop0 = invoke(jvppCore.createLoopback(new CreateLoopback()));
 
@@ -165,51 +91,62 @@ public class AclUpdateBenchmark {
         flags.adminUpDown = 1;
         flags.swIfIndex = loop0.swIfIndex;
         invoke(jvppCore.swInterfaceSetFlags(flags));
+        return loop0.swIfIndex;
+    }
 
-        if (L3.equals(mode)) {
-            // Assign IP to loop0
-            final SwInterfaceAddDelAddress address = new SwInterfaceAddDelAddress();
-            address.address = new byte[]{1,0,0,0};
-            address.addressLength = 8;
-            address.isAdd = 1;
-            address.swIfIndex = loop0.swIfIndex;
-            invoke(jvppCore.swInterfaceAddDelAddress(address));
-        } else if (L2.equals(mode)) {
-            // Create bridge domain 1
-            final BridgeDomainAddDel bd = new BridgeDomainAddDel();
-            bd.bdId = 1;
-            bd.isAdd = 1;
-            invoke(jvppCore.bridgeDomainAddDel(bd));
-
-            // Assign loop0 to BD1:
-            final SwInterfaceSetL2Bridge loop0Bridge = new SwInterfaceSetL2Bridge();
-            loop0Bridge.bdId = bd.bdId;
-            loop0Bridge.rxSwIfIndex = loop0.swIfIndex;
-            loop0Bridge.enable = 1; // set L2 mode
-            invoke(jvppCore.swInterfaceSetL2Bridge(loop0Bridge));
-        }
+    private void initL3(final int swIfIndex) throws ExecutionException, InterruptedException {
+        // Assign IP to loop0
+        final SwInterfaceAddDelAddress address = new SwInterfaceAddDelAddress();
+        address.address = new byte[] {1, 0, 0, 0};
+        address.addressLength = 8;
+        address.isAdd = 1;
+        address.swIfIndex = swIfIndex;
+        invoke(jvppCore.swInterfaceAddDelAddress(address));
+    }
 
+    private void initL2(final int swIfIndex) throws ExecutionException, InterruptedException {
+        // Create bridge domain with id=1
+        final BridgeDomainAddDel bd = new BridgeDomainAddDel();
+        bd.bdId = 1;
+        bd.isAdd = 1;
+        invoke(jvppCore.bridgeDomainAddDel(bd));
+
+        // Assign loop0 to BD1:
+        final SwInterfaceSetL2Bridge loop0Bridge = new SwInterfaceSetL2Bridge();
+        loop0Bridge.bdId = bd.bdId;
+        loop0Bridge.rxSwIfIndex = swIfIndex;
+        loop0Bridge.enable = 1; // set L2 mode
+        invoke(jvppCore.swInterfaceSetL2Bridge(loop0Bridge));
+    }
+
+    private int initAcl(final int swIfIndex) throws ExecutionException, InterruptedException {
         // Create ACL
         final int aclId = invoke(jvppAcl.aclAddReplace(aclProvider.next())).aclIndex;
 
         // Assign the ACL to loop0 interface
         final AclInterfaceSetAclList aclList = new AclInterfaceSetAclList();
-        aclList.swIfIndex = loop0.swIfIndex;
+        aclList.swIfIndex = swIfIndex;
         aclList.count = 1;
         aclList.nInput = 1;
         aclList.acls = new int[] {aclId};
         invoke(jvppAcl.aclInterfaceSetAclList(aclList));
 
-        // Use ACL index in subsequent executions of aclProvider.next() method
-        aclProvider.setAclIndex(aclId);
+        return aclId;
     }
 
-    public enum InterfaceMode {
-        L2, L3
+    @Override
+    protected void connect(final JVppRegistry registry) throws IOException {
+        jvppCore = new FutureJVppCoreFacade(registry, new JVppCoreImpl());
+        jvppAcl = new FutureJVppAclFacade(registry, new JVppAclImpl());
     }
 
-    private static <R extends JVppReply<?>> R invoke(final CompletionStage<R> completionStage)
-        throws ExecutionException, InterruptedException {
-        return completionStage.toCompletableFuture().get();
+    @Override
+    protected void disconnect() throws Exception {
+        jvppAcl.close();
+        jvppCore.close();
+    }
+
+    public enum InterfaceMode {
+        L2, L3
     }
 }
diff --git a/it/jvpp-benchmark/src/main/java/io/fd/hc2vpp/it/jvpp/benchmark/classify/ClassifyTableBenchmark.java b/it/jvpp-benchmark/src/main/java/io/fd/hc2vpp/it/jvpp/benchmark/classify/ClassifyTableBenchmark.java
new file mode 100644 (file)
index 0000000..ba234e4
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.hc2vpp.it.jvpp.benchmark.classify;
+
+import io.fd.hc2vpp.it.jvpp.benchmark.util.JVppBenchmark;
+import io.fd.vpp.jvpp.JVppRegistry;
+import io.fd.vpp.jvpp.core.JVppCoreImpl;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply;
+import io.fd.vpp.jvpp.core.future.FutureJVppCoreFacade;
+import java.io.IOException;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ClassifyTableBenchmark extends JVppBenchmark {
+    private static final Logger LOG = LoggerFactory.getLogger(ClassifyTableBenchmark.class);
+
+    @Param( {"100"})
+    private int tableSetSize;
+
+    private FutureJVppCoreFacade jvppCore;
+    private ClassifyTableProvider classifyTableProvider;
+
+    @Benchmark
+    public ClassifyAddDelTableReply testCreate() throws Exception {
+        // Caller may want to process reply, so return it to prevent JVM from dead code elimination
+        return jvppCore.classifyAddDelTable(classifyTableProvider.next()).toCompletableFuture().get();
+    }
+
+    @Override
+    protected void iterationSetup() throws Exception {
+        classifyTableProvider = new ClassifyTableProviderImpl(tableSetSize);
+    }
+
+    @Override
+    protected void connect(final JVppRegistry registry) throws IOException {
+        jvppCore = new FutureJVppCoreFacade(registry, new JVppCoreImpl());
+    }
+
+    @Override
+    protected void disconnect() throws Exception {
+        jvppCore.close();
+    }
+}
  * limitations under the License.
  */
 
-package io.fd.hc2vpp.it.jvpp.benchmark.classify;
+package io.fd.hc2vpp.it.jvpp.benchmark.util;
 
 import com.google.common.io.CharStreams;
+import io.fd.vpp.jvpp.JVppRegistry;
 import io.fd.vpp.jvpp.JVppRegistryImpl;
+import io.fd.vpp.jvpp.acl.JVppAclImpl;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
 import io.fd.vpp.jvpp.core.JVppCoreImpl;
-import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply;
 import io.fd.vpp.jvpp.core.future.FutureJVppCoreFacade;
+import io.fd.vpp.jvpp.dto.JVppReply;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
-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;
@@ -48,41 +51,34 @@ import org.slf4j.LoggerFactory;
 @State(Scope.Thread)
 @Fork(1)
 @Threads(1)
-@Timeout(time = 5)
+@Timeout(time = 10)
 @Warmup(iterations = 20, time = 2)
 @Measurement(iterations = 100, time = 2)
 @OutputTimeUnit(TimeUnit.MILLISECONDS)
-public class ClassifyTableCreateBenchmark {
-    private static final Logger LOG = LoggerFactory.getLogger(ClassifyTableCreateBenchmark.class);
-
-    @Param( {"100"})
-    private int tableSetSize;
-
+public abstract class JVppBenchmark {
+    private static final Logger LOG = LoggerFactory.getLogger(JVppBenchmark.class);
     private JVppRegistryImpl registry;
-    private FutureJVppCoreFacade jvppCore;
-    private ClassifyTableProvider classifyTableProvider;
-
-    @Benchmark
-    public ClassifyAddDelTableReply testMethod() throws Exception {
-        // Caller may want to process reply, so return it to prevent JVM from dead code elimination
-        return jvppCore.classifyAddDelTable(classifyTableProvider.next()).toCompletableFuture().get();
-    }
 
     @Setup(Level.Iteration)
-    public void setup() throws Exception {
-        initProvider();
+    public final void setup() throws Exception {
         startVpp();
-        connect();
+        jVppConnect();
+        iterationSetup();
+    }
+
+    protected void iterationSetup() throws Exception {
+        // NOOP
     }
 
     @TearDown(Level.Iteration)
-    public void tearDown() throws Exception {
-        disconnect();
+    public final void tearDown() throws Exception {
+        iterationTearDown();
+        jVppDisconnect();
         stopVpp();
     }
 
-    private void initProvider() {
-        classifyTableProvider = new ClassifyTableProviderImpl(tableSetSize);
+    protected void iterationTearDown() throws Exception {
+        // NOOP
     }
 
     private void startVpp() throws Exception {
@@ -101,10 +97,11 @@ public class ClassifyTableCreateBenchmark {
         // Prevents VPP start failure: "vpp.service: Start request repeated too quickly".
         Thread.sleep(1500);
         LOG.info("VPP stopped successfully");
+
     }
 
     private static void exec(String[] command) throws IOException, InterruptedException {
-        Process process = Runtime.getRuntime().exec(command);
+        final Process process = Runtime.getRuntime().exec(command);
         process.waitFor();
         if (process.exitValue() != 0) {
             String error_msg = "Failed to execute " + Arrays.toString(command) + ": " +
@@ -113,17 +110,33 @@ public class ClassifyTableCreateBenchmark {
         }
     }
 
-    private void connect() throws IOException {
-        LOG.info("Connecting to JVPP ...");
+    private void jVppConnect() throws IOException {
+        LOG.info("Connecting JVpp ...");
         registry = new JVppRegistryImpl("ACLUpdateBenchmark");
-        jvppCore = new FutureJVppCoreFacade(registry, new JVppCoreImpl());
+        connect(registry);
         LOG.info("Successfully connected to JVPP");
     }
 
-    private void disconnect() throws Exception {
-        LOG.info("Disconnecting ...");
-        jvppCore.close();
+    /**
+     * Connects JVpp plugins.
+     * @param registry manages JVpp connection
+     */
+    protected abstract void connect(final JVppRegistry registry) throws IOException;
+
+    private void jVppDisconnect() throws Exception {
+        LOG.info("Disconnecting JVpp...");
+        disconnect();
         registry.close();
         LOG.info("Successfully disconnected ...");
     }
+
+    /**
+     * Disconnects JVpp plugins.
+     */
+    protected abstract void disconnect() throws Exception;
+
+    protected static <R extends JVppReply<?>> R invoke(final CompletionStage<R> completionStage)
+        throws ExecutionException, InterruptedException {
+        return completionStage.toCompletableFuture().get();
+    }
 }