diff --git a/pom.xml b/pom.xml index 1536b45a..4caea859 100644 --- a/pom.xml +++ b/pom.xml @@ -280,10 +280,10 @@ test - org.openjdk.jmh - jmh-generator-annprocess - 1.35 - test + org.openjdk.jmh + jmh-generator-annprocess + 1.35 + test @@ -407,12 +407,19 @@ -classpath - org.openjdk.jmh.Main] + org.openjdk.jmh.Main + ${benchmark} + ${benchmarkArgs} + + true + SingleInstanceBenchmarkRunner + + release diff --git a/src/test/java/io/tarantool/driver/benchmark/ClusterBenchmarkRunner.java b/src/test/java/io/tarantool/driver/benchmark/ClusterBenchmarkRunner.java new file mode 100644 index 00000000..4792b062 --- /dev/null +++ b/src/test/java/io/tarantool/driver/benchmark/ClusterBenchmarkRunner.java @@ -0,0 +1,134 @@ +package io.tarantool.driver.benchmark; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +import io.tarantool.driver.api.TarantoolResult; +import io.tarantool.driver.api.conditions.Conditions; +import io.tarantool.driver.api.space.TarantoolSpaceOperations; +import io.tarantool.driver.api.tuple.TarantoolTuple; + +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.OperationsPerInvocation; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 1, jvmArgsAppend = "-Xmx1G") +public class ClusterBenchmarkRunner { + private static final String TEST_SPACE = "test_space"; + private static final String TEST_PROFILE = "test__profile"; + + public static void main(String[] args) throws Exception { + org.openjdk.jmh.Main.main(args); + } + + @Benchmark + @Measurement(iterations = 10) + @OperationsPerInvocation(2) + public void getSpaceObject(ClusterTarantoolSetup plan, Blackhole bh) { + TarantoolSpaceOperations> testSpace = + plan.tarantoolClient.space(TEST_SPACE); + bh.consume(testSpace); + + TarantoolSpaceOperations> profileSpace = + plan.tarantoolClient.space(TEST_PROFILE); + bh.consume(profileSpace); + } + + @Benchmark + @BenchmarkMode(Mode.Throughput) + @Measurement(iterations = 10) + @OperationsPerInvocation(2000) + public void writeData(ClusterTarantoolSetup plan, FuturesHolder futuresHolder, Spaces spaces, Blackhole bh) { + // Fill 10000 rows into both spaces + TarantoolTuple tarantoolTuple; + String uuid; + int nextId = 0; + for (int i = 0; i < 1_000; i++) { + uuid = UUID.randomUUID().toString(); + nextId = plan.nextTestSpaceId + i; + tarantoolTuple = plan.tupleFactory.create(1_000_000 + nextId, null, uuid, 200_000 + nextId); + futuresHolder.allFutures.add(spaces.testSpace.insert(tarantoolTuple)); + tarantoolTuple = plan.tupleFactory.create(1_000_000 + nextId, null, uuid, 50_000 + nextId, 100_000 + i); + futuresHolder.allFutures.add(spaces.profileSpace.insert(tarantoolTuple)); + } + nextId++; + plan.nextTestSpaceId = nextId; + plan.nextProfileSpaceId = nextId; + } + + @Benchmark + @BenchmarkMode(Mode.Throughput) + @Measurement(iterations = 10) + @OperationsPerInvocation(1000) + public void readDataUsingCallAPI(ClusterTarantoolSetup plan, FuturesHolder futuresHolder, Blackhole bh) { + boolean coin = Math.random() - 0.5 > 0; + String spaceName = coin ? TEST_SPACE : TEST_PROFILE; + long nextId; + for (int i = 0; i < 1_000; i++) { + nextId = Math.round(Math.random() * 10_000) + 1_000_000; + futuresHolder.allFutures.add( + plan.tarantoolClient.callForSingleResult( + "custom_crud_get_one_record", Arrays.asList(spaceName, nextId), List.class) + ); + } + } + + @Benchmark + @BenchmarkMode(Mode.Throughput) + @Measurement(iterations = 10) + @OperationsPerInvocation(1000) + public void readDataUsingSpaceAPI( + ClusterTarantoolSetup plan, FuturesHolder futuresHolder, Spaces spaces, Blackhole bh) { + boolean coin = Math.random() - 0.5 > 0; + TarantoolSpaceOperations> space = coin ? + spaces.testSpace : spaces.profileSpace; + String pkFieldName = coin ? "id" : "profile_id"; + long nextId; + for (int i = 0; i < 1_000; i++) { + nextId = Math.round(Math.random() * 10_000) + 1_000_000; + futuresHolder.allFutures.add( + space.select(Conditions.indexEquals(pkFieldName, Collections.singletonList(nextId))) + ); + } + } + + @State(Scope.Thread) + public static class FuturesHolder { + final List> allFutures = new ArrayList<>(2_000); + + @Setup(Level.Invocation) + public void doSetup() { + allFutures.clear(); + } + + @TearDown(Level.Invocation) + public void doTeardown() { + allFutures.forEach(CompletableFuture::join); + } + } + + @State(Scope.Thread) + public static class Spaces { + TarantoolSpaceOperations> testSpace; + TarantoolSpaceOperations> profileSpace; + + @Setup(Level.Iteration) + public void doSetup(ClusterTarantoolSetup plan) { + testSpace = plan.tarantoolClient.space(TEST_SPACE); + profileSpace = plan.tarantoolClient.space(TEST_PROFILE); + } + } +} diff --git a/src/test/java/io/tarantool/driver/benchmark/ClusterTarantoolSetup.java b/src/test/java/io/tarantool/driver/benchmark/ClusterTarantoolSetup.java new file mode 100644 index 00000000..c1ce5310 --- /dev/null +++ b/src/test/java/io/tarantool/driver/benchmark/ClusterTarantoolSetup.java @@ -0,0 +1,80 @@ +package io.tarantool.driver.benchmark; + +import java.time.Duration; + +import io.tarantool.driver.api.TarantoolClient; +import io.tarantool.driver.api.TarantoolClientFactory; +import io.tarantool.driver.api.TarantoolResult; +import io.tarantool.driver.api.TarantoolServerAddress; +import io.tarantool.driver.api.tuple.DefaultTarantoolTupleFactory; +import io.tarantool.driver.api.tuple.TarantoolTuple; +import io.tarantool.driver.api.tuple.TarantoolTupleFactory; +import io.tarantool.driver.mappers.factories.DefaultMessagePackMapperFactory; +import io.tarantool.driver.mappers.MessagePackMapper; + +import org.openjdk.jmh.annotations.Level; +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.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.TarantoolCartridgeContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; + +@State(Scope.Benchmark) +public class ClusterTarantoolSetup { + public Logger logger = LoggerFactory.getLogger(ClusterTarantoolSetup.class); + + final MessagePackMapper defaultMapper = + DefaultMessagePackMapperFactory.getInstance().defaultComplexTypesMapper(); + final TarantoolTupleFactory tupleFactory = new DefaultTarantoolTupleFactory(defaultMapper); + + final TarantoolCartridgeContainer tarantoolContainer = + new TarantoolCartridgeContainer( + "Dockerfile", + "cartridge-java-test", + "cartridge/instances.yml", + "cartridge/topology.lua") + .withDirectoryBinding("cartridge") + .withLogConsumer(new Slf4jLogConsumer(logger)) + .waitingFor(Wait.forLogMessage(".*Listening HTTP on.*", 5)) + .withStartupTimeout(Duration.ofMinutes(2)); + + TarantoolClient> tarantoolClient; + + int nextTestSpaceId; + int nextProfileSpaceId; + + private void initClient() { + tarantoolClient = TarantoolClientFactory.createClient() + .withAddresses( + new TarantoolServerAddress(tarantoolContainer.getRouterHost(), tarantoolContainer.getMappedPort(3301)), + new TarantoolServerAddress(tarantoolContainer.getRouterHost(), tarantoolContainer.getMappedPort(3302)), + new TarantoolServerAddress(tarantoolContainer.getRouterHost(), tarantoolContainer.getMappedPort(3303)) + ) + .withCredentials(tarantoolContainer.getUsername(), tarantoolContainer.getPassword()) + .withConnections(10) + .withEventLoopThreadsNumber(10) + .withRequestTimeout(10000) + .withProxyMethodMapping() + .build(); + } + + @Setup(Level.Trial) + public void doSetup() { + System.out.println("Do Setup"); + if (!tarantoolContainer.isRunning()) { + tarantoolContainer.start(); + } + initClient(); + } + + @TearDown(Level.Trial) + public void doTearDown() throws Exception { + System.out.println("Do TearDown"); + tarantoolClient.close(); + tarantoolContainer.close(); + } +} diff --git a/src/test/java/io/tarantool/driver/benchmark/BenchmarkRunner.java b/src/test/java/io/tarantool/driver/benchmark/SingleInstanceBenchmarkRunner.java similarity index 91% rename from src/test/java/io/tarantool/driver/benchmark/BenchmarkRunner.java rename to src/test/java/io/tarantool/driver/benchmark/SingleInstanceBenchmarkRunner.java index 1a99ddcb..6fbdb371 100644 --- a/src/test/java/io/tarantool/driver/benchmark/BenchmarkRunner.java +++ b/src/test/java/io/tarantool/driver/benchmark/SingleInstanceBenchmarkRunner.java @@ -20,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; -public class BenchmarkRunner { +public class SingleInstanceBenchmarkRunner { public static void main(String[] args) throws Exception { org.openjdk.jmh.Main.main(args); } @@ -29,7 +29,7 @@ public static void main(String[] args) throws Exception { @Fork(1) @BenchmarkMode(Mode.Throughput) @OperationsPerInvocation(1000) - public void acceptingDiffTypes(TarantoolSetup plan, Blackhole bh) { + public void acceptingDiffTypes(SingleInstanceTarantoolSetup plan, Blackhole bh) { List result = plan.tarantoolClient.call( "return_arrays_with_different_types" ).join(); @@ -66,7 +66,7 @@ public void acceptingDiffTypes(TarantoolSetup plan, Blackhole bh) { @Fork(1) @BenchmarkMode(Mode.Throughput) @OperationsPerInvocation(1000) - public void acceptingDiffTypesAsTuplesAndUnpackIt(TarantoolSetup plan, Blackhole bh) { + public void acceptingDiffTypesAsTuplesAndUnpackIt(SingleInstanceTarantoolSetup plan, Blackhole bh) { TarantoolResult tuples = plan.tarantoolClient.call( "return_arrays_with_different_types", Collections.emptyList(), @@ -104,7 +104,7 @@ public void acceptingDiffTypesAsTuplesAndUnpackIt(TarantoolSetup plan, Blackhole @Fork(1) @BenchmarkMode(Mode.Throughput) @OperationsPerInvocation(1000) - public void acceptingDiffTypesAsTuplesAndUnpackItWithTargetType(TarantoolSetup plan, Blackhole bh) { + public void acceptingDiffTypesAsTuplesAndUnpackItWithTargetType(SingleInstanceTarantoolSetup plan, Blackhole bh) { TarantoolResult tuples = plan.tarantoolClient.call( "return_arrays_with_different_types", Collections.emptyList(), @@ -142,7 +142,7 @@ public void acceptingDiffTypesAsTuplesAndUnpackItWithTargetType(TarantoolSetup p @Fork(1) @BenchmarkMode(Mode.Throughput) @OperationsPerInvocation(1000) - public void passingArrayOfArraysWithDiffTypes(TarantoolSetup plan, Blackhole bh) { + public void passingArrayOfArraysWithDiffTypes(SingleInstanceTarantoolSetup plan, Blackhole bh) { bh.consume(plan.tarantoolClient.call( "empty_function", plan.arraysWithDiffElements).join()); } @@ -151,7 +151,7 @@ public void passingArrayOfArraysWithDiffTypes(TarantoolSetup plan, Blackhole bh) @Fork(1) @BenchmarkMode(Mode.Throughput) @OperationsPerInvocation(1000) - public void passingArrayOfArraysWithNestedArrays(TarantoolSetup plan, Blackhole bh) { + public void passingArrayOfArraysWithNestedArrays(SingleInstanceTarantoolSetup plan, Blackhole bh) { bh.consume(plan.tarantoolClient.call( "empty_function", plan.arraysWithNestedArrays).join()); } @@ -160,7 +160,7 @@ public void passingArrayOfArraysWithNestedArrays(TarantoolSetup plan, Blackhole @Fork(1) @BenchmarkMode(Mode.Throughput) @OperationsPerInvocation(1000) - public void passingArrayOfArraysWithNestedMaps(TarantoolSetup plan, Blackhole bh) { + public void passingArrayOfArraysWithNestedMaps(SingleInstanceTarantoolSetup plan, Blackhole bh) { bh.consume(plan.tarantoolClient.call( "empty_function", plan.arraysWithNestedMaps).join()); } @@ -168,7 +168,7 @@ public void passingArrayOfArraysWithNestedMaps(TarantoolSetup plan, Blackhole bh @Benchmark @Fork(1) @BenchmarkMode(Mode.Throughput) - public void spaceCall(TarantoolSetup plan, Blackhole bh) { + public void spaceCall(SingleInstanceTarantoolSetup plan, Blackhole bh) { bh.consume(plan.retryingTarantoolClient.space( "test_space")); } diff --git a/src/test/java/io/tarantool/driver/benchmark/TarantoolSetup.java b/src/test/java/io/tarantool/driver/benchmark/SingleInstanceTarantoolSetup.java similarity index 97% rename from src/test/java/io/tarantool/driver/benchmark/TarantoolSetup.java rename to src/test/java/io/tarantool/driver/benchmark/SingleInstanceTarantoolSetup.java index a105edce..d987071d 100644 --- a/src/test/java/io/tarantool/driver/benchmark/TarantoolSetup.java +++ b/src/test/java/io/tarantool/driver/benchmark/SingleInstanceTarantoolSetup.java @@ -28,8 +28,8 @@ import java.util.function.Supplier; @State(Scope.Benchmark) -public class TarantoolSetup { - public Logger log = LoggerFactory.getLogger(TarantoolSetup.class); +public class SingleInstanceTarantoolSetup { + public Logger log = LoggerFactory.getLogger(SingleInstanceTarantoolSetup.class); public TarantoolContainer tarantoolContainer = new TarantoolContainer() .withScriptFileName("org/testcontainers/containers/benchmark.lua")