diff --git a/exonum-java-binding/benchmarks/pom.xml b/exonum-java-binding/benchmarks/pom.xml index f20adbebb5..031339ce0a 100644 --- a/exonum-java-binding/benchmarks/pom.xml +++ b/exonum-java-binding/benchmarks/pom.xml @@ -66,6 +66,17 @@ THE POSSIBILITY OF SUCH DAMAGE. ${jmh.version} provided + + + com.google.guava + guava + + + + com.exonum.binding + exonum-java-binding-common + ${project.version} + @@ -91,6 +102,7 @@ THE POSSIBILITY OF SUCH DAMAGE. implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> org.openjdk.jmh.Main + diff --git a/exonum-java-binding/benchmarks/src/main/java/com/exonum/binding/bench/FlatListProofBenchmark.java b/exonum-java-binding/benchmarks/src/main/java/com/exonum/binding/bench/FlatListProofBenchmark.java new file mode 100644 index 0000000000..ea8f08ac4b --- /dev/null +++ b/exonum-java-binding/benchmarks/src/main/java/com/exonum/binding/bench/FlatListProofBenchmark.java @@ -0,0 +1,88 @@ +/* + * Copyright 2019 The Exonum Team + * + * 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 com.exonum.binding.bench; + +import static com.exonum.binding.common.hash.Hashing.sha256; +import static com.exonum.binding.common.proofs.list.ListProofEntry.checkHeight; +import static java.util.Collections.singletonList; + +import com.exonum.binding.common.hash.HashCode; +import com.exonum.binding.common.proofs.list.CheckedListProof; +import com.exonum.binding.common.proofs.list.FlatListProof; +import com.exonum.binding.common.proofs.list.ListProofElementEntry; +import com.exonum.binding.common.proofs.list.ListProofHashedEntry; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +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; + +@State(Scope.Benchmark) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +public class FlatListProofBenchmark { + + @Param({"10"}) + private int height; + + private FlatListProof proof; + + /** + * Creates a proof for a single element from a tree of the given height. + */ + @Setup(Level.Trial) + public void createProof() { + /* + o + / \ + h + / + o + / \ + o h + / \ + e h + */ + checkHeight(height); + long size = 1L << height; + // Create the element(s) + // The value size can also be made configurable, though it is not expected to have + // a large effect on anything but the first hashing step. + byte[] value = {1}; + List elements = singletonList( + ListProofElementEntry.newInstance(0L, value)); + // Create the hash nodes + List hashed = new ArrayList<>(height); + for (int h = 0; h < height; h++) { + HashCode hash = sha256().hashInt(h); + hashed.add(ListProofHashedEntry.newInstance(1L, h, hash)); + } + proof = new FlatListProof(elements, hashed, size); + } + + @Benchmark + public CheckedListProof verify() { + return proof.verify(); + } +} diff --git a/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/FlatListProof.java b/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/FlatListProof.java index 19b22e7762..4115031028 100644 --- a/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/FlatListProof.java +++ b/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/FlatListProof.java @@ -45,7 +45,7 @@ * A flat list proof. It proves that certain elements are present in a proof list * of a certain size. */ -class FlatListProof { +public class FlatListProof { /* Proof lists are represented as BSTs, where all leaf elements are at the same height. Here is a tree for a three-element proof list: @@ -95,14 +95,14 @@ class FlatListProof { private final List proof; private final long size; - FlatListProof(List elements, + public FlatListProof(List elements, List proof, long size) { this.elements = checkNotNull(elements); this.proof = checkNotNull(proof); this.size = size; } - CheckedListProof verify() { + public CheckedListProof verify() { // Check the size if (size < 0 || MAX_SIZE < size) { throw new InvalidProofException(String.format("Invalid size (%s), must be in range [0; 2^56]", diff --git a/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/ListProofElementEntry.java b/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/ListProofElementEntry.java index f62a952e81..be46a98011 100644 --- a/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/ListProofElementEntry.java +++ b/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/ListProofElementEntry.java @@ -22,14 +22,14 @@ * A value stored in the Merkle tree at its bottom level (at height 0). */ @AutoValue -abstract class ListProofElementEntry implements ListProofEntry { +public abstract class ListProofElementEntry implements ListProofEntry { /** * Returns a value of the element stored at this index in the list. */ abstract byte[] getElement(); - static ListProofElementEntry newInstance(long index, byte[] element) { + public static ListProofElementEntry newInstance(long index, byte[] element) { ListProofEntry.checkIndex(index); return new AutoValue_ListProofElementEntry(index, element); } diff --git a/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/ListProofEntry.java b/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/ListProofEntry.java index 8c462d4780..06770ad095 100644 --- a/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/ListProofEntry.java +++ b/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/ListProofEntry.java @@ -18,7 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument; -interface ListProofEntry { +public interface ListProofEntry { /** * The maximum height of a list proof tree. diff --git a/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/ListProofHashedEntry.java b/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/ListProofHashedEntry.java index 2e72bda0a3..a23a62f42e 100644 --- a/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/ListProofHashedEntry.java +++ b/exonum-java-binding/common/src/main/java/com/exonum/binding/common/proofs/list/ListProofHashedEntry.java @@ -23,7 +23,7 @@ * A hash of a sub-tree in a Merkle proof tree. */ @AutoValue -abstract class ListProofHashedEntry implements ListProofEntry { +public abstract class ListProofHashedEntry implements ListProofEntry { /** * Returns the height of the proof tree node corresponding to this entry. @@ -37,7 +37,7 @@ abstract class ListProofHashedEntry implements ListProofEntry { */ abstract HashCode getHash(); - static ListProofHashedEntry newInstance(long index, int height, HashCode nodeHash) { + public static ListProofHashedEntry newInstance(long index, int height, HashCode nodeHash) { ListProofEntry.checkIndex(index); ListProofEntry.checkHeight(height); return new AutoValue_ListProofHashedEntry(index, height, nodeHash);