This is an automated email from the ASF dual-hosted git repository.

kturner pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/accumulo-access.git


The following commit(s) were added to refs/heads/main by this push:
     new 8b86909  Adds a JMH Benchmark (#10)
8b86909 is described below

commit 8b8690923db7581317ed31b9790dedc4dea7cfbb
Author: Keith Turner <ktur...@apache.org>
AuthorDate: Wed Sep 20 10:45:49 2023 -0400

    Adds a JMH Benchmark (#10)
---
 pom.xml                                            |  13 ++
 .../accumulo/access/AccessEvaluatorTest.java       |   4 +-
 .../accumulo/access/AccessExpressionBenchmark.java | 187 +++++++++++++++++++++
 3 files changed, 202 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 006648d..6e1600a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,6 +19,7 @@
     <maven.compiler.source>11</maven.compiler.source>
     <maven.compiler.target>11</maven.compiler.target>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <version.jmh>1.36</version.jmh>
   </properties>
 
   <dependencies>
@@ -40,6 +41,18 @@
       <version>5.9.2</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.openjdk.jmh</groupId>
+      <artifactId>jmh-core</artifactId>
+      <version>${version.jmh}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.openjdk.jmh</groupId>
+      <artifactId>jmh-generator-annprocess</artifactId>
+      <version>${version.jmh}</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/src/test/java/org/apache/accumulo/access/AccessEvaluatorTest.java 
b/src/test/java/org/apache/accumulo/access/AccessEvaluatorTest.java
index 1afa67a..6133363 100644
--- a/src/test/java/org/apache/accumulo/access/AccessEvaluatorTest.java
+++ b/src/test/java/org/apache/accumulo/access/AccessEvaluatorTest.java
@@ -60,8 +60,8 @@ public class AccessEvaluatorTest {
 
   }
 
-  private List<TestDataSet> readTestData() throws IOException {
-    try (var input = 
getClass().getClassLoader().getResourceAsStream("testdata.json")) {
+  static List<TestDataSet> readTestData() throws IOException {
+    try (var input = 
AccessEvaluatorTest.class.getClassLoader().getResourceAsStream("testdata.json"))
 {
       if (input == null) {
         throw new IllegalStateException("could not find resource : 
testdata.json");
       }
diff --git 
a/src/test/java/org/apache/accumulo/access/AccessExpressionBenchmark.java 
b/src/test/java/org/apache/accumulo/access/AccessExpressionBenchmark.java
new file mode 100644
index 0000000..6cd4b91
--- /dev/null
+++ b/src/test/java/org/apache/accumulo/access/AccessExpressionBenchmark.java
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   https://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.accumulo.access;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+import org.openjdk.jmh.runner.options.TimeValue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/**
+ * Benchmarks Access Expressions using JMH.  To run, use the following 
commands.
+ *
+ * <p><blockquote><pre>
+ * mvn clean package
+ * mvn exec:exec -Dexec.executable="java" -Dexec.classpathScope=test 
-Dexec.args="-classpath %classpath 
org.apache.accumulo.access.AccessExpressionBenchmark"
+ * </code></blockquote>
+ * </pre>
+ */
+public class AccessExpressionBenchmark {
+
+
+    public static class EvaluatorTests {
+        AccessEvaluator evaluator;
+        List<AccessExpression> parsedExpressions;
+
+        List<byte[]> expressions;
+    }
+
+    @State(Scope.Benchmark)
+    public static class BenchmarkState {
+
+        private ArrayList<byte[]> allTestExpressions;
+
+        private ArrayList<String> allTestExpressionsStr;
+
+        private ArrayList<EvaluatorTests> evaluatorTests;
+
+        @Setup
+        public void loadData() throws IOException {
+            List<AccessEvaluatorTest.TestDataSet> testData = 
AccessEvaluatorTest.readTestData();
+            allTestExpressions = new ArrayList<>();
+            allTestExpressionsStr = new ArrayList<>();
+            evaluatorTests = new ArrayList<>();
+
+            for(var testDataSet : testData) {
+                EvaluatorTests et = new EvaluatorTests();
+                et.parsedExpressions = new ArrayList<>();
+                et.expressions = new ArrayList<>();
+
+                if(testDataSet.auths.length == 1) {
+                    et.evaluator = 
AccessEvaluator.builder().authorizations(testDataSet.auths[0]).build();
+                } else {
+                    var authSets =
+                            
Stream.of(testDataSet.auths).map(Authorizations::of).collect(Collectors.toList());
+                    et.evaluator = 
AccessEvaluator.builder().authorizations(authSets).build();
+                }
+
+                for(var tests : testDataSet.tests) {
+                    if(tests.expectedResult != 
AccessEvaluatorTest.ExpectedResult.ERROR) {
+                        for(var exp : tests.expressions) {
+                            allTestExpressionsStr.add(exp);
+                            byte[] byteExp = exp.getBytes(UTF_8);
+                            allTestExpressions.add(byteExp);
+                            et.expressions.add(byteExp);
+                            et.parsedExpressions.add(AccessExpression.of(exp));
+                        }
+                    }
+                }
+
+                evaluatorTests.add(et);
+            }
+        }
+
+        List<byte[]> getBytesExpressions(){
+            return allTestExpressions;
+        }
+
+        List<String> getStringExpressions(){
+            return allTestExpressionsStr;
+        }
+
+        public ArrayList<EvaluatorTests> getEvaluatorTests() {
+            return evaluatorTests;
+        }
+
+    }
+
+    /**
+     * Measures the time it takes to parse an expression stored in byte[] and 
produce a parse tree.
+     */
+    @Benchmark
+    public void measureBytesParsing(BenchmarkState state, Blackhole blackhole) 
{
+        for(byte[] accessExpression : state.getBytesExpressions()) {
+            blackhole.consume(AccessExpression.of(accessExpression));
+        }
+    }
+
+    /**
+     * Measures the time it takes to parse an expression stored in a String 
and produce a parse tree.
+     */
+    @Benchmark
+    public void measureStringParsing(BenchmarkState state, Blackhole 
blackhole) {
+        for(String accessExpression : state.getStringExpressions()) {
+            blackhole.consume(AccessExpression.of(accessExpression));
+        }
+    }
+
+    /**
+     * Measures the time it takes to evaluate a previously parsed expression.
+     */
+    @Benchmark
+    public void measureEvaluation(BenchmarkState state, Blackhole blackhole) {
+        for(EvaluatorTests evaluatorTests : state.getEvaluatorTests()) {
+            for(AccessExpression expression : 
evaluatorTests.parsedExpressions) {
+                
blackhole.consume(evaluatorTests.evaluator.canAccess(expression));
+            }
+        }
+    }
+
+    /**
+     * Measures the time it takes to parse and evaluate an expression.  This 
has to create the parse tree an operate on it.
+     */
+    @Benchmark
+    public void measureEvaluationAndParsing(BenchmarkState state, Blackhole 
blackhole) {
+        for(EvaluatorTests evaluatorTests : state.getEvaluatorTests()) {
+            for(byte[] expression : evaluatorTests.expressions) {
+                
blackhole.consume(evaluatorTests.evaluator.canAccess(expression));
+            }
+        }
+    }
+
+    public static void main(String[] args) throws RunnerException, IOException 
{
+
+        var state = new BenchmarkState();
+        state.loadData();
+
+        int numExpressions =state.getBytesExpressions().size();
+
+        System.out.println("Number of Expressions: " + numExpressions);
+
+        Options opt = new OptionsBuilder()
+                .include(AccessExpressionBenchmark.class.getSimpleName())
+                .mode(Mode.Throughput)
+                .operationsPerInvocation(numExpressions)
+                .timeUnit(TimeUnit.MICROSECONDS)
+                .warmupTime(TimeValue.seconds(5))
+                .warmupIterations(3)
+                .measurementIterations(4)
+                .forks(3)
+                .build();
+
+        new Runner(opt).run();
+    }
+
+}

Reply via email to