diff options
Diffstat (limited to 'src/arrow/java/performance')
22 files changed, 2994 insertions, 0 deletions
diff --git a/src/arrow/java/performance/pom.xml b/src/arrow/java/performance/pom.xml new file mode 100644 index 000000000..c2be88c8a --- /dev/null +++ b/src/arrow/java/performance/pom.xml @@ -0,0 +1,233 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- 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 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. --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>arrow-java-root</artifactId> + <groupId>org.apache.arrow</groupId> + <version>6.0.1</version> + </parent> + <artifactId>arrow-performance</artifactId> + <packaging>jar</packaging> + <name>Arrow Performance Benchmarks</name> + <description>JMH Performance benchmarks for other Arrow libraries.</description> + + <dependencies> + <dependency> + <groupId>org.openjdk.jmh</groupId> + <artifactId>jmh-core</artifactId> + <version>${jmh.version}</version> + </dependency> + <dependency> + <groupId>org.openjdk.jmh</groupId> + <artifactId>jmh-generator-annprocess</artifactId> + <version>${jmh.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-slf4j-impl</artifactId> + <version>2.1</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <version>2.1</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>org.apache.arrow</groupId> + <artifactId>arrow-vector</artifactId> + <version>${project.version}</version> + <classifier>${arrow.vector.classifier}</classifier> + </dependency> + <dependency> + <groupId>org.apache.arrow</groupId> + <artifactId>arrow-memory-core</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.arrow</groupId> + <artifactId>arrow-memory-netty</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.avro</groupId> + <artifactId>avro</artifactId> + <version>${dep.avro.version}</version> + </dependency> + <dependency> + <groupId>org.apache.arrow</groupId> + <artifactId>arrow-avro</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>com.h2database</groupId> + <artifactId>h2</artifactId> + <version>1.4.196</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.arrow</groupId> + <artifactId>arrow-jdbc</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.arrow</groupId> + <artifactId>arrow-algorithm</artifactId> + <version>6.0.1</version> + <scope>test</scope> + </dependency> + </dependencies> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <jmh.version>1.21</jmh.version> + <javac.target>1.8</javac.target> + <uberjar.name>benchmarks</uberjar.name> + <skip.perf.benchmarks>true</skip.perf.benchmarks> + <benchmark.filter>.*</benchmark.filter> + <benchmark.forks>1</benchmark.forks> + <benchmark.jvmargs> </benchmark.jvmargs> + <benchmark.warmups>5</benchmark.warmups> + <benchmark.runs>5</benchmark.runs> + <benchmark.list> </benchmark.list> + <benchmark.resultfile>jmh-result.json</benchmark.resultfile> + <benchmark.resultformat>json</benchmark.resultformat> + </properties> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration combine.self="override"> + <compilerVersion>${javac.target}</compilerVersion> + <source>${javac.target}</source> + <target>${javac.target}</target> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>2.2</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <finalName>${uberjar.name}</finalName> + <transformers> + <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <mainClass>org.openjdk.jmh.Main</mainClass> + </transformer> + </transformers> + <filters> + <filter> + <artifact>*:*</artifact> + <excludes> + <exclude>META-INF/*.SF</exclude> + <exclude>META-INF/*.DSA</exclude> + <exclude>META-INF/*.RSA</exclude> + </excludes> + </filter> + </filters> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.6.0</version> + <executions> + <execution> + <id>run-java-benchmarks</id> + <phase>integration-test</phase> + <goals> + <goal>exec</goal> + </goals> + </execution> + </executions> + <configuration> + <skip>${skip.perf.benchmarks}</skip> + <classpathScope>test</classpathScope> + <executable>java</executable> + <arguments> + <argument>-classpath</argument> + <classpath /> + <argument>org.openjdk.jmh.Main</argument> + <argument>${benchmark.filter}</argument> + <argument>-f</argument> + <argument>${benchmark.forks}</argument> + <argument>-jvmArgs</argument> + <argument>${benchmark.jvmargs}</argument> + <argument>-wi</argument> + <argument>${benchmark.warmups}</argument> + <argument>-i</argument> + <argument>${benchmark.runs}</argument> + <argument>${benchmark.list}</argument> + <argument>-rff</argument> + <argument>${benchmark.resultfile}</argument> + <argument>-rf</argument> + <argument>${benchmark.resultformat}</argument> + </arguments> + </configuration> + </plugin> + </plugins> + <pluginManagement> + <plugins> + <plugin> + <artifactId>maven-clean-plugin</artifactId> + <version>2.5</version> + </plugin> + <plugin> + <artifactId>maven-deploy-plugin</artifactId> + <version>2.8.1</version> + </plugin> + <plugin> + <artifactId>maven-install-plugin</artifactId> + <version>2.5.1</version> + </plugin> + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <version>2.4</version> + </plugin> + <plugin> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.9.1</version> + </plugin> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>2.6</version> + </plugin> + <plugin> + <artifactId>maven-site-plugin</artifactId> + <version>3.3</version> + </plugin> + <plugin> + <artifactId>maven-source-plugin</artifactId> + <version>2.2.1</version> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>3.0.0-M3</version> + </plugin> + </plugins> + </pluginManagement> + </build> + +</project> diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/adapter/AvroAdapterBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/adapter/AvroAdapterBenchmarks.java new file mode 100644 index 000000000..884647b5a --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/adapter/AvroAdapterBenchmarks.java @@ -0,0 +1,141 @@ +/* + * 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 + * + * 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.arrow.adapter; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.AvroToArrow; +import org.apache.arrow.AvroToArrowConfig; +import org.apache.arrow.AvroToArrowConfigBuilder; +import org.apache.arrow.AvroToArrowVectorIterator; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.IntVector; +import org.apache.arrow.vector.VectorSchemaRoot; +import org.apache.avro.Schema; +import org.apache.avro.generic.GenericData; +import org.apache.avro.generic.GenericDatumWriter; +import org.apache.avro.generic.GenericRecord; +import org.apache.avro.io.BinaryDecoder; +import org.apache.avro.io.BinaryEncoder; +import org.apache.avro.io.DatumWriter; +import org.apache.avro.io.Decoder; +import org.apache.avro.io.DecoderFactory; +import org.apache.avro.io.EncoderFactory; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Benchmarks for avro adapter. + */ +@State(Scope.Benchmark) +public class AvroAdapterBenchmarks { + + private final int valueCount = 3000; + + private AvroToArrowConfig config; + + private Schema schema; + private BinaryDecoder decoder; + + /** + * Setup benchmarks. + */ + @Setup + public void prepare() throws Exception { + BufferAllocator allocator = new RootAllocator(Integer.MAX_VALUE); + config = new AvroToArrowConfigBuilder(allocator).build(); + + String schemaStr = "{\n" + " \"namespace\": \"org.apache.arrow.avro\",\n" + + " \"type\": \"record\",\n" + " \"name\": \"testBenchmark\",\n" + " \"fields\": [\n" + + " {\"name\": \"f0\", \"type\": \"string\"},\n" + + " {\"name\": \"f1\", \"type\": \"int\"},\n" + + " {\"name\": \"f2\", \"type\": \"long\"},\n" + + " {\"name\": \"f3\", \"type\": \"boolean\"},\n" + + " {\"name\": \"f4\", \"type\": \"float\"}\n" + " ]\n" + "}"; + schema = new Schema.Parser().parse(schemaStr); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BinaryEncoder encoder = new EncoderFactory().directBinaryEncoder(out, null); + DatumWriter writer = new GenericDatumWriter(schema); + + for (int i = 0; i < valueCount; i++) { + GenericRecord record = new GenericData.Record(schema); + record.put(0, "test" + i); + record.put(1, i); + record.put(2, i + 1L); + record.put(3, i % 2 == 0); + record.put(4, i + 0.1f); + writer.write(record, encoder); + } + + decoder = new DecoderFactory().directBinaryDecoder(new ByteArrayInputStream(out.toByteArray()), null); + } + + /** + * Tear down benchmarks. + */ + @TearDown + public void tearDown() { + config.getAllocator().close(); + } + + /** + * Test {@link AvroToArrow#avroToArrowIterator(Schema, Decoder, AvroToArrowConfig)}. + * @return useless. To avoid DCE by JIT. + */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int testAvroToArrow() throws Exception { + decoder.inputStream().reset(); + int sum = 0; + try (AvroToArrowVectorIterator iter = AvroToArrow.avroToArrowIterator(schema, decoder, config)) { + while (iter.hasNext()) { + VectorSchemaRoot root = iter.next(); + IntVector intVector = (IntVector) root.getVector("f1"); + for (int i = 0; i < intVector.getValueCount(); i++) { + sum += intVector.get(i); + } + root.close(); + } + } + return sum; + } + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(AvroAdapterBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/adapter/jdbc/JdbcAdapterBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/adapter/jdbc/JdbcAdapterBenchmarks.java new file mode 100644 index 000000000..fd3940b4c --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/adapter/jdbc/JdbcAdapterBenchmarks.java @@ -0,0 +1,359 @@ +/* + * 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 + * + * 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.arrow.adapter.jdbc; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.adapter.jdbc.consumer.BigIntConsumer; +import org.apache.arrow.adapter.jdbc.consumer.BitConsumer; +import org.apache.arrow.adapter.jdbc.consumer.IntConsumer; +import org.apache.arrow.adapter.jdbc.consumer.JdbcConsumer; +import org.apache.arrow.adapter.jdbc.consumer.VarCharConsumer; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.BigIntVector; +import org.apache.arrow.vector.BitVector; +import org.apache.arrow.vector.IntVector; +import org.apache.arrow.vector.VarCharVector; +import org.apache.arrow.vector.VectorSchemaRoot; +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.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +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; + +/** + * Benchmarks for Jdbc adapter. + */ +public class JdbcAdapterBenchmarks { + + private static final int VALUE_COUNT = 3000; + + private static final String CREATE_STATEMENT = + "CREATE TABLE test_table (f0 INT, f1 LONG, f2 VARCHAR, f3 BOOLEAN);"; + private static final String INSERT_STATEMENT = + "INSERT INTO test_table (f0, f1, f2, f3) VALUES (?, ?, ?, ?);"; + private static final String QUERY = "SELECT f0, f1, f2, f3 FROM test_table;"; + private static final String DROP_STATEMENT = "DROP TABLE test_table;"; + + private static final String URL = "jdbc:h2:mem:JdbcAdapterBenchmarks"; + private static final String DRIVER = "org.h2.Driver"; + + /** + * State object for the jdbc e2e benchmark. + */ + @State(Scope.Benchmark) + public static class JdbcState { + + private Connection conn = null; + + private ResultSet resultSet = null; + + private BufferAllocator allocator; + + private Statement statement; + + private JdbcToArrowConfig config; + + @Setup(Level.Trial) + public void prepareState() throws Exception { + allocator = new RootAllocator(Integer.MAX_VALUE); + config = new JdbcToArrowConfigBuilder().setAllocator(allocator).setTargetBatchSize(1024).build(); + Class.forName(DRIVER); + conn = DriverManager.getConnection(URL); + + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate(CREATE_STATEMENT); + } + + for (int i = 0; i < VALUE_COUNT; i++) { + // Insert data + try (PreparedStatement stmt = conn.prepareStatement(INSERT_STATEMENT)) { + + stmt.setInt(1, i); + stmt.setLong(2, i); + stmt.setString(3, "test" + i); + stmt.setBoolean(4, i % 2 == 0); + stmt.executeUpdate(); + } + } + } + + @Setup(Level.Invocation) + public void prepareInvoke() throws Exception { + statement = conn.createStatement(); + resultSet = statement.executeQuery(QUERY); + } + + @TearDown(Level.Invocation) + public void tearDownInvoke() throws Exception { + resultSet.close(); + statement.close(); + } + + @TearDown(Level.Trial) + public void tearDownState() throws Exception { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate(DROP_STATEMENT); + } + allocator.close(); + } + } + + /** + * State object for the consume benchmark. + */ + @State(Scope.Benchmark) + public static class ConsumeState { + + private static final boolean NULLABLE = true; + + private Connection conn = null; + + private ResultSet resultSet = null; + + private BufferAllocator allocator; + + private Statement statement; + + private IntVector intVector; + + private BigIntVector longVector; + + private VarCharVector varCharVector; + + private BitVector bitVector; + + private JdbcConsumer<IntVector> intConsumer; + + private JdbcConsumer<BigIntVector> longConsumer; + + private JdbcConsumer<VarCharVector> varCharConsumer; + + private JdbcConsumer<BitVector> bitConsumer; + + private JdbcToArrowConfig config; + + @Setup(Level.Trial) + public void prepare() throws Exception { + allocator = new RootAllocator(Integer.MAX_VALUE); + config = new JdbcToArrowConfigBuilder().setAllocator(allocator).setTargetBatchSize(1024).build(); + + Class.forName(DRIVER); + conn = DriverManager.getConnection(URL); + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate(CREATE_STATEMENT); + } + + for (int i = 0; i < VALUE_COUNT; i++) { + // Insert data + try (PreparedStatement stmt = conn.prepareStatement(INSERT_STATEMENT)) { + + stmt.setInt(1, i); + stmt.setLong(2, i); + stmt.setString(3, "test" + i); + stmt.setBoolean(4, i % 2 == 0); + stmt.executeUpdate(); + } + } + + statement = conn.createStatement(); + resultSet = statement.executeQuery(QUERY); + resultSet.next(); + + intVector = new IntVector("", allocator); + intVector.allocateNew(VALUE_COUNT); + intConsumer = IntConsumer.createConsumer(intVector, 1, NULLABLE); + + longVector = new BigIntVector("", allocator); + longVector.allocateNew(VALUE_COUNT); + longConsumer = BigIntConsumer.createConsumer(longVector, 2, NULLABLE); + + varCharVector = new VarCharVector("", allocator); + varCharVector.allocateNew(VALUE_COUNT); + varCharConsumer = VarCharConsumer.createConsumer(varCharVector, 3, NULLABLE); + + bitVector = new BitVector("", allocator); + bitVector.allocateNew(VALUE_COUNT); + bitConsumer = BitConsumer.createConsumer(bitVector, 4, NULLABLE); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate(DROP_STATEMENT); + } + + resultSet.close(); + statement.close(); + conn.close(); + + intVector.close(); + intConsumer.close(); + + longVector.close(); + longConsumer.close(); + + varCharVector.close(); + varCharConsumer.close(); + + bitVector.close(); + bitConsumer.close(); + + allocator.close(); + } + } + + /** + * State object for the jdbc row consume benchmark. + */ + @State(Scope.Benchmark) + public static class RowConsumeState { + + private Connection conn = null; + + private ResultSet resultSet = null; + + private BufferAllocator allocator; + + private Statement statement; + + private JdbcToArrowConfig config; + + private ArrowVectorIterator iter; + + private VectorSchemaRoot root; + + @Setup(Level.Trial) + public void prepareState() throws Exception { + allocator = new RootAllocator(Integer.MAX_VALUE); + config = new JdbcToArrowConfigBuilder().setAllocator(allocator).setTargetBatchSize(VALUE_COUNT).build(); + Class.forName(DRIVER); + conn = DriverManager.getConnection(URL); + + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate(CREATE_STATEMENT); + } + + for (int i = 0; i < VALUE_COUNT; i++) { + // Insert data + try (PreparedStatement stmt = conn.prepareStatement(INSERT_STATEMENT)) { + + stmt.setInt(1, i); + stmt.setLong(2, i); + stmt.setString(3, "test" + i); + stmt.setBoolean(4, i % 2 == 0); + stmt.executeUpdate(); + } + } + } + + @Setup(Level.Invocation) + public void prepareInvoke() throws Exception { + statement = conn.createStatement(); + resultSet = statement.executeQuery(QUERY); + + iter = JdbcToArrow.sqlToArrowVectorIterator(resultSet, config); + root = iter.next(); + iter.compositeConsumer.resetVectorSchemaRoot(root); + } + + @TearDown(Level.Invocation) + public void tearDownInvoke() throws Exception { + resultSet.close(); + statement.close(); + iter.close(); + } + + @TearDown(Level.Trial) + public void tearDownState() throws Exception { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate(DROP_STATEMENT); + } + allocator.close(); + } + } + + /** + * Test {@link JdbcToArrow#sqlToArrowVectorIterator(ResultSet, JdbcToArrowConfig)}. + * @return useless. To avoid DCE by JIT. + */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public int testJdbcToArrow(JdbcState state) throws Exception { + int valueCount = 0; + try (ArrowVectorIterator iter = JdbcToArrow.sqlToArrowVectorIterator(state.resultSet, state.config)) { + while (iter.hasNext()) { + VectorSchemaRoot root = iter.next(); + IntVector intVector = (IntVector) root.getFieldVectors().get(0); + valueCount += intVector.getValueCount(); + root.close(); + } + } + return valueCount; + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void consumeBenchmark(ConsumeState state) throws Exception { + state.intConsumer.resetValueVector(state.intVector); + state.longConsumer.resetValueVector(state.longVector); + state.varCharConsumer.resetValueVector(state.varCharVector); + state.bitConsumer.resetValueVector(state.bitVector); + for (int i = 0; i < VALUE_COUNT; i++) { + state.intConsumer.consume(state.resultSet); + state.longConsumer.consume(state.resultSet); + state.varCharConsumer.consume(state.resultSet); + state.bitConsumer.consume(state.resultSet); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void consumeRowsBenchmark(RowConsumeState state) throws Exception { + for (int i = 0; i < VALUE_COUNT; i++) { + state.iter.compositeConsumer.consume(state.resultSet); + } + } + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(JdbcAdapterBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} + diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/algorithm/search/ParallelSearcherBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/algorithm/search/ParallelSearcherBenchmarks.java new file mode 100644 index 000000000..1c3af77e7 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/algorithm/search/ParallelSearcherBenchmarks.java @@ -0,0 +1,115 @@ +/* + * 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 + * + * 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.arrow.algorithm.search; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.IntVector; +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; +import org.openjdk.jmh.annotations.TearDown; +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; + +/** + * Benchmarks for {@link ParallelSearcher}. + */ +public class ParallelSearcherBenchmarks { + + private static final int VECTOR_LENGTH = 1024 * 1024; + + /** + * State object for the benchmarks. + */ + @State(Scope.Benchmark) + public static class SearchState { + + @Param({"1", "2", "5", "10", "20", "50", "100"}) + int numThreads; + + BufferAllocator allocator; + + ExecutorService threadPool; + + IntVector targetVector; + + IntVector keyVector; + + ParallelSearcher<IntVector> searcher; + + @Setup(Level.Trial) + public void prepare() { + allocator = new RootAllocator(Integer.MAX_VALUE); + targetVector = new IntVector("target vector", allocator); + targetVector.allocateNew(VECTOR_LENGTH); + keyVector = new IntVector("key vector", allocator); + keyVector.allocateNew(1); + threadPool = Executors.newFixedThreadPool(numThreads); + + for (int i = 0; i < VECTOR_LENGTH; i++) { + targetVector.set(i, i); + } + targetVector.setValueCount(VECTOR_LENGTH); + + keyVector.set(0, VECTOR_LENGTH / 3); + keyVector.setValueCount(1); + } + + @Setup(Level.Invocation) + public void prepareInvoke() { + searcher = new ParallelSearcher<>(targetVector, threadPool, numThreads); + } + + @TearDown(Level.Trial) + public void tearDownState() { + targetVector.close(); + keyVector.close(); + allocator.close(); + threadPool.shutdown(); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void searchBenchmark(SearchState state) throws Exception { + state.searcher.search(state.keyVector, 0); + } + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(ParallelSearcherBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/memory/AllocatorBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/memory/AllocatorBenchmarks.java new file mode 100644 index 000000000..88fcf73f0 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/memory/AllocatorBenchmarks.java @@ -0,0 +1,95 @@ +/* + * 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 + * + * 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.arrow.memory; + +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.ArrowBuf; +import org.apache.arrow.memory.rounding.RoundingPolicy; +import org.apache.arrow.memory.rounding.SegmentRoundingPolicy; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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; + +/** + * Benchmarks for allocators. + */ +public class AllocatorBenchmarks { + + /** + * Benchmark for the default allocator. + */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void defaultAllocatorBenchmark() { + final int bufferSize = 1024; + final int numBuffers = 1024; + + try (RootAllocator allocator = new RootAllocator(numBuffers * bufferSize)) { + ArrowBuf[] buffers = new ArrowBuf[numBuffers]; + + for (int i = 0; i < numBuffers; i++) { + buffers[i] = allocator.buffer(bufferSize); + } + + for (int i = 0; i < numBuffers; i++) { + buffers[i].close(); + } + } + } + + /** + * Benchmark for allocator with segment rounding policy. + */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void segmentRoundingPolicyBenchmark() { + final int bufferSize = 1024; + final int numBuffers = 1024; + final int segmentSize = 1024; + + RoundingPolicy policy = new SegmentRoundingPolicy(segmentSize); + try (RootAllocator allocator = new RootAllocator(AllocationListener.NOOP, bufferSize * numBuffers, policy)) { + ArrowBuf[] buffers = new ArrowBuf[numBuffers]; + + for (int i = 0; i < numBuffers; i++) { + buffers[i] = allocator.buffer(bufferSize); + } + + for (int i = 0; i < numBuffers; i++) { + buffers[i].close(); + } + } + } + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(AllocatorBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/memory/ArrowBufBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/memory/ArrowBufBenchmarks.java new file mode 100644 index 000000000..ef4da5828 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/memory/ArrowBufBenchmarks.java @@ -0,0 +1,82 @@ +/* + * 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 + * + * 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.arrow.memory; + +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Benchmarks for {@link ArrowBuf}. + */ +@State(Scope.Benchmark) +public class ArrowBufBenchmarks { + + private static final int BUFFER_CAPACITY = 1024 * 1024; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private BufferAllocator allocator; + + private ArrowBuf buffer; + + /** + * Setup benchmarks. + */ + @Setup + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + buffer = allocator.buffer(BUFFER_CAPACITY); + } + + /** + * Tear down benchmarks. + */ + @TearDown + public void tearDown() { + buffer.close(); + allocator.close(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void setZero() { + buffer.setZero(0, BUFFER_CAPACITY); + } + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(ArrowBufBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/memory/util/ArrowBufPointerBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/memory/util/ArrowBufPointerBenchmarks.java new file mode 100644 index 000000000..8e2c9cc51 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/memory/util/ArrowBufPointerBenchmarks.java @@ -0,0 +1,107 @@ +/* + * 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 + * + * 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.arrow.memory.util; + +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.ArrowBuf; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Benchmarks for {@link ArrowBufPointer}. + */ +@State(Scope.Benchmark) +public class ArrowBufPointerBenchmarks { + + private static final int BUFFER_CAPACITY = 1000; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private BufferAllocator allocator; + + private ArrowBuf buffer1; + + private ArrowBuf buffer2; + + private ArrowBufPointer pointer1; + + private ArrowBufPointer pointer2; + + /** + * Setup benchmarks. + */ + @Setup + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + buffer1 = allocator.buffer(BUFFER_CAPACITY); + buffer2 = allocator.buffer(BUFFER_CAPACITY); + + for (int i = 0; i < BUFFER_CAPACITY; i++) { + buffer1.setByte(i, i); + buffer2.setByte(i, i); + } + + // make the last bytes different + buffer1.setByte(BUFFER_CAPACITY - 1, 12); + buffer1.setByte(BUFFER_CAPACITY - 1, 123); + + pointer1 = new ArrowBufPointer(buffer1, 0, BUFFER_CAPACITY); + pointer2 = new ArrowBufPointer(buffer2, 0, BUFFER_CAPACITY); + } + + /** + * Tear down benchmarks. + */ + @TearDown + public void tearDown() { + buffer1.close(); + buffer2.close(); + allocator.close(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int compareBenchmark() { + return pointer1.compareTo(pointer2); + } + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(ArrowBufPointerBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} + + diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/memory/util/ByteFunctionHelpersBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/memory/util/ByteFunctionHelpersBenchmarks.java new file mode 100644 index 000000000..4d0dfcb5d --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/memory/util/ByteFunctionHelpersBenchmarks.java @@ -0,0 +1,138 @@ +/* + * 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 + * + * 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.arrow.memory.util; + +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.ArrowBuf; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +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.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +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; + +/** + * Benchmarks for {@link ByteFunctionHelpers}. + */ +public class ByteFunctionHelpersBenchmarks { + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + /** + * State object for the {@link ByteFunctionHelpersBenchmarks#arrowBufEquals(ArrowEqualState)} benchmark. + */ + @State(Scope.Benchmark) + public static class ArrowEqualState { + + private static final int BUFFER_CAPACITY = 7; + + private BufferAllocator allocator; + + private ArrowBuf buffer1; + + private ArrowBuf buffer2; + + @Setup(Level.Trial) + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + buffer1 = allocator.buffer(BUFFER_CAPACITY); + buffer2 = allocator.buffer(BUFFER_CAPACITY); + + for (int i = 0; i < BUFFER_CAPACITY; i++) { + buffer1.setByte(i, i); + buffer2.setByte(i, i); + } + } + + @TearDown(Level.Trial) + public void tearDown() { + buffer1.close(); + buffer2.close(); + allocator.close(); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void arrowBufEquals(ArrowEqualState state) { + ByteFunctionHelpers.equal(state.buffer1, 0, ArrowEqualState.BUFFER_CAPACITY - 1, + state.buffer2, 0, ArrowEqualState.BUFFER_CAPACITY - 1); + } + + /** + * State object for the {@link ByteFunctionHelpersBenchmarks#arrowBufArrayEquals(ArrowArrayEqualState)} benchmark. + */ + @State(Scope.Benchmark) + public static class ArrowArrayEqualState { + + private static final int BUFFER_CAPACITY = 1024; + + private BufferAllocator allocator; + + private ArrowBuf buffer1; + + private byte[] buffer2; + + @Setup(Level.Trial) + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + buffer1 = allocator.buffer(BUFFER_CAPACITY); + buffer2 = new byte[BUFFER_CAPACITY]; + + for (int i = 0; i < BUFFER_CAPACITY; i++) { + buffer1.setByte(i, i); + buffer2[i] = (byte) i; + } + } + + @TearDown(Level.Trial) + public void tearDown() { + buffer1.close(); + allocator.close(); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int arrowBufArrayEquals(ArrowArrayEqualState state) { + return ByteFunctionHelpers.compare( + state.buffer1, 0, ArrowArrayEqualState.BUFFER_CAPACITY, + state.buffer2, 0, ArrowArrayEqualState.BUFFER_CAPACITY); + } + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(ByteFunctionHelpersBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/BaseValueVectorBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/BaseValueVectorBenchmarks.java new file mode 100644 index 000000000..5d6441cd5 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/BaseValueVectorBenchmarks.java @@ -0,0 +1,95 @@ +/* + * 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 + * + * 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.arrow.vector; + +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Benchmarks for {@link BaseValueVector}. + */ +@State(Scope.Benchmark) +public class BaseValueVectorBenchmarks { + + private static final int VECTOR_LENGTH = 1024; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private BufferAllocator allocator; + + private IntVector vector; + + /** + * Setup benchmarks. + */ + @Setup + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + vector = new IntVector("vector", allocator); + vector.allocateNew(VECTOR_LENGTH); + } + + /** + * Tear down benchmarks. + */ + @TearDown + public void tearDown() { + vector.close(); + allocator.close(); + } + + /** + * Test {@link BaseValueVector#computeCombinedBufferSize(int, int)}. + * @return useless. To avoid DCE by JIT. + */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int testComputeCombinedBufferSize() { + int totalSize = 0; + for (int i = 0; i < VECTOR_LENGTH; i++) { + totalSize += vector.computeCombinedBufferSize(i, 4); + } + return totalSize; + } + + public static void main(String [] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(BaseValueVectorBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } + + +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/BitVectorHelperBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/BitVectorHelperBenchmarks.java new file mode 100644 index 000000000..5f6e5ca28 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/BitVectorHelperBenchmarks.java @@ -0,0 +1,229 @@ +/* + * 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 + * + * 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.arrow.vector; + +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.ArrowBuf; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.ipc.message.ArrowFieldNode; +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.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +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; + +/** + * Benchmarks for {@link BitVectorHelper}. + */ +public class BitVectorHelperBenchmarks { + + /** + * State object for general benchmarks. + */ + @State(Scope.Benchmark) + public static class BenchmarkState { + + private static final int VALIDITY_BUFFER_CAPACITY = 1024; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private BufferAllocator allocator; + + private ArrowBuf validityBuffer; + + private ArrowBuf oneBitValidityBuffer; + + /** + * Setup benchmarks. + */ + @Setup(Level.Trial) + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + validityBuffer = allocator.buffer(VALIDITY_BUFFER_CAPACITY / 8); + + for (int i = 0; i < VALIDITY_BUFFER_CAPACITY; i++) { + if (i % 7 == 0) { + BitVectorHelper.setBit(validityBuffer, i); + } else { + BitVectorHelper.unsetBit(validityBuffer, i); + } + } + + // only one 1 bit in the middle of the buffer + oneBitValidityBuffer = allocator.buffer(VALIDITY_BUFFER_CAPACITY / 8); + oneBitValidityBuffer.setZero(0, VALIDITY_BUFFER_CAPACITY / 8); + BitVectorHelper.setBit(oneBitValidityBuffer, VALIDITY_BUFFER_CAPACITY / 2); + } + + /** + * Tear down benchmarks. + */ + @TearDown(Level.Trial) + public void tearDown() { + validityBuffer.close(); + oneBitValidityBuffer.close(); + allocator.close(); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int getNullCountBenchmark(BenchmarkState state) { + return BitVectorHelper.getNullCount(state.validityBuffer, BenchmarkState.VALIDITY_BUFFER_CAPACITY); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public boolean allBitsNullBenchmark(BenchmarkState state) { + return BitVectorHelper.checkAllBitsEqualTo( + state.oneBitValidityBuffer, BenchmarkState.VALIDITY_BUFFER_CAPACITY, true); + } + + /** + * State object for {@link #loadValidityBufferAllOne(NonNullableValidityBufferState)}.. + */ + @State(Scope.Benchmark) + public static class NonNullableValidityBufferState { + + private static final int VALIDITY_BUFFER_CAPACITY = 1024; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private BufferAllocator allocator; + + private ArrowBuf validityBuffer; + + private ArrowBuf loadResult; + + private ArrowFieldNode fieldNode; + + /** + * Setup benchmarks. + */ + @Setup(Level.Trial) + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + validityBuffer = allocator.buffer(VALIDITY_BUFFER_CAPACITY / 8); + + for (int i = 0; i < VALIDITY_BUFFER_CAPACITY; i++) { + BitVectorHelper.setBit(validityBuffer, i); + } + + fieldNode = new ArrowFieldNode(VALIDITY_BUFFER_CAPACITY, 0); + } + + @TearDown(Level.Invocation) + public void tearDownInvoke() { + loadResult.close(); + } + + /** + * Tear down benchmarks. + */ + @TearDown(Level.Trial) + public void tearDown() { + validityBuffer.close(); + allocator.close(); + } + } + + /** + * Benchmark for {@link BitVectorHelper#loadValidityBuffer(ArrowFieldNode, ArrowBuf, BufferAllocator)} + * when all elements are not null. + */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void loadValidityBufferAllOne(NonNullableValidityBufferState state) { + state.loadResult = BitVectorHelper.loadValidityBuffer(state.fieldNode, state.validityBuffer, state.allocator); + } + + /** + * State object for {@link #setValidityBitBenchmark(ClearBitStateState)}. + */ + @State(Scope.Benchmark) + public static class ClearBitStateState { + + private static final int VALIDITY_BUFFER_CAPACITY = 1024; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private BufferAllocator allocator; + + private ArrowBuf validityBuffer; + + private int bitToSet = 0; + + /** + * Setup benchmarks. + */ + @Setup(Level.Trial) + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + validityBuffer = allocator.buffer(VALIDITY_BUFFER_CAPACITY / 8); + } + + /** + * Tear down benchmarks. + */ + @TearDown(Level.Trial) + public void tearDown() { + validityBuffer.close(); + allocator.close(); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void setValidityBitBenchmark(ClearBitStateState state) { + for (int i = 0; i < ClearBitStateState.VALIDITY_BUFFER_CAPACITY; i++) { + BitVectorHelper.setValidityBit(state.validityBuffer, i, state.bitToSet); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void setValidityBitToZeroBenchmark(ClearBitStateState state) { + for (int i = 0; i < ClearBitStateState.VALIDITY_BUFFER_CAPACITY; i++) { + BitVectorHelper.unsetBit(state.validityBuffer, i); + } + } + + public static void main(String [] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(BitVectorHelperBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/DecimalVectorBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/DecimalVectorBenchmarks.java new file mode 100644 index 000000000..72f565990 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/DecimalVectorBenchmarks.java @@ -0,0 +1,121 @@ +/* + * 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 + * + * 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.arrow.vector; + +import java.math.BigDecimal; +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.ArrowBuf; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Benchmarks for {@link DecimalVector}. + */ +@State(Scope.Benchmark) +public class DecimalVectorBenchmarks { + + private static final int VECTOR_LENGTH = 1024; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private BufferAllocator allocator; + + private DecimalVector vector; + + private ArrowBuf fromBuf; + + byte[] fromByteArray; + + /** + * Setup benchmarks. + */ + @Setup + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + vector = new DecimalVector("vector", allocator, 38, 16); + vector.allocateNew(VECTOR_LENGTH); + + fromBuf = allocator.buffer(VECTOR_LENGTH * DecimalVector.TYPE_WIDTH); + for (int i = 0; i < VECTOR_LENGTH; i++) { + byte[] bytes = BigDecimal.valueOf(i).unscaledValue().toByteArray(); + fromBuf.setBytes(i * DecimalVector.TYPE_WIDTH, bytes); + } + + fromByteArray = new byte[DecimalVector.TYPE_WIDTH]; + fromBuf.getBytes(0, fromByteArray); + } + + /** + * Tear down benchmarks. + */ + @TearDown + public void tearDown() { + fromBuf.close(); + vector.close(); + allocator.close(); + } + + /** + * Test writing on {@link DecimalVector} from arrow buf. + */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void setBigEndianArrowBufBenchmark() { + int offset = 0; + + for (int i = 0; i < VECTOR_LENGTH; i++) { + vector.setBigEndianSafe(i, offset, fromBuf, DecimalVector.TYPE_WIDTH); + offset += 8; + } + } + + /** + * Test writing on {@link DecimalVector} from byte array. + */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void setBigEndianByteArrayBenchmark() { + for (int i = 0; i < VECTOR_LENGTH; i++) { + vector.setBigEndian(i, fromByteArray); + } + } + + public static void main(String [] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(DecimalVectorBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/Float8Benchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/Float8Benchmarks.java new file mode 100644 index 000000000..874e0d9f8 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/Float8Benchmarks.java @@ -0,0 +1,122 @@ +/* + * 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 + * + * 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.arrow.vector; + +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.BoundsChecking; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Benchmarks for {@link Float8Vector}. + */ +@State(Scope.Benchmark) +public class Float8Benchmarks { + + private static final int VECTOR_LENGTH = 1024; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private BufferAllocator allocator; + + private Float8Vector vector; + + private Float8Vector fromVector; + + /** + * Setup benchmarks. + */ + @Setup + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + vector = new Float8Vector("vector", allocator); + vector.allocateNew(VECTOR_LENGTH); + + fromVector = new Float8Vector("vector", allocator); + fromVector.allocateNew(VECTOR_LENGTH); + + for (int i = 0; i < VECTOR_LENGTH; i++) { + if (i % 3 == 0) { + fromVector.setNull(i); + } else { + fromVector.set(i, i * i); + } + } + fromVector.setValueCount(VECTOR_LENGTH); + } + + /** + * Tear down benchmarks. + */ + @TearDown + public void tearDown() { + vector.close(); + fromVector.close(); + allocator.close(); + } + + /** + * Test reading/writing on {@link Float8Vector}. + * The performance of this benchmark is influenced by the states of two flags: + * 1. The flag for boundary checking. For details, please see {@link BoundsChecking}. + * 2. The flag for null checking in get methods. For details, please see {@link NullCheckingForGet}. + * @return useless. To avoid DCE by JIT. + */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public double readWriteBenchmark() { + double sum = 0; + for (int i = 0; i < VECTOR_LENGTH; i++) { + vector.set(i, i + 10.0); + sum += vector.get(i); + } + return sum; + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void copyFromBenchmark() { + for (int i = 0; i < VECTOR_LENGTH; i++) { + vector.copyFrom(i, i, (Float8Vector) fromVector); + } + } + + public static void main(String [] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(Float8Benchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/FloatingPointBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/FloatingPointBenchmarks.java new file mode 100644 index 000000000..079672e9f --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/FloatingPointBenchmarks.java @@ -0,0 +1,134 @@ +/* + * 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 + * + * 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.arrow.vector; + +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.compare.ApproxEqualsVisitor; +import org.apache.arrow.vector.compare.Range; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Benchmarks for floating point vectors. + */ +@State(Scope.Benchmark) +public class FloatingPointBenchmarks { + + private static final int VECTOR_LENGTH = 1024; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private BufferAllocator allocator; + + private Float4Vector floatVector1; + + private Float4Vector floatVector2; + + private Float8Vector doubleVector1; + + private Float8Vector doubleVector2; + + private ApproxEqualsVisitor floatVisitor; + + private ApproxEqualsVisitor doubleVisitor; + + private Range range; + + /** + * Setup benchmarks. + */ + @Setup + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + floatVector1 = new Float4Vector("vector", allocator); + floatVector2 = new Float4Vector("vector", allocator); + doubleVector1 = new Float8Vector("vector", allocator); + doubleVector2 = new Float8Vector("vector", allocator); + + floatVector1.allocateNew(VECTOR_LENGTH); + floatVector2.allocateNew(VECTOR_LENGTH); + doubleVector1.allocateNew(VECTOR_LENGTH); + doubleVector2.allocateNew(VECTOR_LENGTH); + + for (int i = 0; i < VECTOR_LENGTH; i++) { + if (i % 3 == 0) { + floatVector1.setNull(i); + floatVector2.setNull(i); + doubleVector1.setNull(i); + doubleVector2.setNull(i); + } else { + floatVector1.set(i, i * i); + floatVector2.set(i, i * i); + doubleVector1.set(i, i * i); + doubleVector2.set(i, i * i); + } + } + floatVector1.setValueCount(VECTOR_LENGTH); + floatVector2.setValueCount(VECTOR_LENGTH); + doubleVector1.setValueCount(VECTOR_LENGTH); + doubleVector2.setValueCount(VECTOR_LENGTH); + + floatVisitor = new ApproxEqualsVisitor(floatVector1, floatVector2, 0.01f, 0.01); + doubleVisitor = new ApproxEqualsVisitor(doubleVector1, doubleVector2, 0.01f, 0.01); + range = new Range(0, 0, VECTOR_LENGTH); + } + + /** + * Tear down benchmarks. + */ + @TearDown + public void tearDown() { + floatVector1.close(); + floatVector2.close(); + doubleVector1.close(); + doubleVector2.close(); + allocator.close(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public int approxEqualsBenchmark() { + boolean floatResult = floatVisitor.visit(floatVector1, range); + boolean doubleResult = doubleVisitor.visit(doubleVector1, range); + return (floatResult ? 1 : 0) + (doubleResult ? 1 : 0); + } + + public static void main(String [] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(FloatingPointBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} + diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/IntBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/IntBenchmarks.java new file mode 100644 index 000000000..036768d44 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/IntBenchmarks.java @@ -0,0 +1,110 @@ +/* + * 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 + * + * 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.arrow.vector; + +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.complex.impl.IntWriterImpl; +import org.apache.arrow.vector.holders.NullableIntHolder; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Benchmarks for {@link IntVector}. + */ +@State(Scope.Benchmark) +public class IntBenchmarks { + + private static final int VECTOR_LENGTH = 1024; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private BufferAllocator allocator; + + private IntVector vector; + + @Setup + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + vector = new IntVector("vector", allocator); + vector.allocateNew(VECTOR_LENGTH); + vector.setValueCount(VECTOR_LENGTH); + } + + @TearDown + public void tearDown() { + vector.close(); + allocator.close(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void setWithValueHolder() { + for (int i = 0; i < VECTOR_LENGTH; i++) { + NullableIntHolder holder = new NullableIntHolder(); + holder.isSet = i % 3 == 0 ? 0 : 1; + if (holder.isSet == 1) { + holder.value = i; + } + vector.setSafe(i, holder); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void setIntDirectly() { + for (int i = 0; i < VECTOR_LENGTH; i++) { + vector.setSafe(i, i % 3 == 0 ? 0 : 1, i); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void setWithWriter() { + IntWriterImpl writer = new IntWriterImpl(vector); + for (int i = 0; i < VECTOR_LENGTH; i++) { + if (i % 3 != 0) { + writer.writeInt(i); + } + } + } + + public static void main(String [] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(IntBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/VarCharBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/VarCharBenchmarks.java new file mode 100644 index 000000000..1ab4b7bc2 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/VarCharBenchmarks.java @@ -0,0 +1,102 @@ +/* + * 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 + * + * 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.arrow.vector; + +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Benchmarks for {@link VarCharVector}. + */ +@State(Scope.Benchmark) +public class VarCharBenchmarks { + + private static final int VECTOR_LENGTH = 1024; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private BufferAllocator allocator; + + private VarCharVector vector; + + private VarCharVector fromVector; + + /** + * Setup benchmarks. + */ + @Setup + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + vector = new VarCharVector("vector", allocator); + vector.allocateNew(ALLOCATOR_CAPACITY / 4, VECTOR_LENGTH); + + fromVector = new VarCharVector("vector", allocator); + fromVector.allocateNew(ALLOCATOR_CAPACITY / 4, VECTOR_LENGTH); + + for (int i = 0; i < VECTOR_LENGTH; i++) { + if (i % 3 == 0) { + fromVector.setNull(i); + } else { + fromVector.set(i, String.valueOf(i * 1000).getBytes()); + } + } + fromVector.setValueCount(VECTOR_LENGTH); + } + + /** + * Tear down benchmarks. + */ + @TearDown + public void tearDown() { + vector.close(); + fromVector.close(); + allocator.close(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void copyFromBenchmark() { + for (int i = 0; i < VECTOR_LENGTH; i++) { + vector.copyFrom(i, i, fromVector); + } + } + + public static void main(String [] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(VarCharBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/VariableWidthVectorBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/VariableWidthVectorBenchmarks.java new file mode 100644 index 000000000..7eee981f1 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/VariableWidthVectorBenchmarks.java @@ -0,0 +1,130 @@ +/* + * 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 + * + * 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.arrow.vector; + +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.ArrowBuf; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.holders.NullableVarCharHolder; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Benchmarks for {@link BaseVariableWidthVector}. + */ +@State(Scope.Benchmark) +public class VariableWidthVectorBenchmarks { + + private static final int VECTOR_CAPACITY = 16 * 1024; + + private static final int VECTOR_LENGTH = 1024; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private static byte[] bytes = VariableWidthVectorBenchmarks.class.getName().getBytes(); + private ArrowBuf arrowBuff; + + private BufferAllocator allocator; + + private VarCharVector vector; + + /** + * Setup benchmarks. + */ + @Setup + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + vector = new VarCharVector("vector", allocator); + vector.allocateNew(VECTOR_CAPACITY, VECTOR_LENGTH); + arrowBuff = allocator.buffer(VECTOR_LENGTH); + arrowBuff.setBytes(0, bytes, 0, bytes.length); + } + + /** + * Tear down benchmarks. + */ + @TearDown + public void tearDown() { + arrowBuff.close(); + vector.close(); + allocator.close(); + } + + /** + * Test {@link BaseVariableWidthVector#getValueCapacity()}. + * @return useless. To avoid DCE by JIT. + */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int getValueCapacity() { + return vector.getValueCapacity(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MILLISECONDS) + public int setSafeFromArray() { + for (int i = 0; i < 500; ++i) { + vector.setSafe(i * 40, bytes); + } + return vector.getBufferSize(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MILLISECONDS) + public int setSafeFromNullableVarcharHolder() { + NullableVarCharHolder nvch = new NullableVarCharHolder(); + nvch.buffer = arrowBuff; + nvch.start = 0; + nvch.end = bytes.length; + for (int i = 0; i < 50; ++i) { + nvch.isSet = 0; + for (int j = 0; j < 9; ++j) { + int idx = 10 * i + j; + vector.setSafe(idx, nvch); + } + nvch.isSet = 1; + vector.setSafe(10 * (i + 1), nvch); + } + return vector.getBufferSize(); + } + + + public static void main(String [] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(VariableWidthVectorBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/VectorLoaderBenchmark.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/VectorLoaderBenchmark.java new file mode 100644 index 000000000..416d12641 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/VectorLoaderBenchmark.java @@ -0,0 +1,117 @@ +/* + * 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 + * + * 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.arrow.vector; + +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.ipc.message.ArrowRecordBatch; +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.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +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; + +/** + * Benchmarks for {@link VectorLoader}. + */ +public class VectorLoaderBenchmark { + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private static final int VECTOR_COUNT = 10; + + /** + * State for vector load benchmark. + */ + @State(Scope.Benchmark) + public static class LoadState { + + private BufferAllocator allocator; + + private VarCharVector[] vectors; + + private ArrowRecordBatch recordBatch; + + private VectorSchemaRoot root; + + private VectorLoader loader; + + /** + * Setup benchmarks. + */ + @Setup(Level.Trial) + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + } + + @Setup(Level.Invocation) + public void prepareInvoke() { + vectors = new VarCharVector[VECTOR_COUNT]; + for (int i = 0; i < VECTOR_COUNT; i++) { + vectors[i] = new VarCharVector("vector", allocator); + vectors[i].allocateNew(100, 10); + } + + root = VectorSchemaRoot.of(vectors); + VectorUnloader unloader = new VectorUnloader(root); + recordBatch = unloader.getRecordBatch(); + + loader = new VectorLoader(root); + } + + @TearDown(Level.Invocation) + public void tearDownInvoke() { + recordBatch.close(); + root.close(); + } + + /** + * Tear down benchmarks. + */ + @TearDown(Level.Trial) + public void tearDown() { + allocator.close(); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void loadBenchmark(LoadState state) { + state.loader.load(state.recordBatch); + } + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(VectorLoaderBenchmark.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/VectorUnloaderBenchmark.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/VectorUnloaderBenchmark.java new file mode 100644 index 000000000..d12517245 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/VectorUnloaderBenchmark.java @@ -0,0 +1,109 @@ +/* + * 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 + * + * 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.arrow.vector; + +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.ipc.message.ArrowRecordBatch; +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.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +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; + +/** + * Benchmarks for {@link VectorUnloader}. + */ +@State(Scope.Benchmark) +public class VectorUnloaderBenchmark { + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private static final int VECTOR_COUNT = 10; + + private BufferAllocator allocator; + + private VarCharVector [] vectors; + + private VectorUnloader unloader; + + private ArrowRecordBatch recordBatch; + + /** + * Setup benchmarks. + */ + @Setup(Level.Trial) + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + } + + @Setup(Level.Invocation) + public void prepareInvoke() { + vectors = new VarCharVector[VECTOR_COUNT]; + for (int i = 0; i < VECTOR_COUNT; i++) { + vectors[i] = new VarCharVector("vector", allocator); + vectors[i].allocateNew(100, 10); + } + + unloader = new VectorUnloader(VectorSchemaRoot.of(vectors)); + } + + @TearDown(Level.Invocation) + public void tearDownInvoke() { + if (recordBatch != null) { + recordBatch.close(); + } + for (int i = 0; i < VECTOR_COUNT; i++) { + vectors[i].close(); + } + } + + /** + * Tear down benchmarks. + */ + @TearDown(Level.Trial) + public void tearDown() { + allocator.close(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void unloadBenchmark() { + recordBatch = unloader.getRecordBatch(); + } + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(VectorUnloaderBenchmark.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/dictionary/DictionaryEncoderBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/dictionary/DictionaryEncoderBenchmarks.java new file mode 100644 index 000000000..6dd887a32 --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/dictionary/DictionaryEncoderBenchmarks.java @@ -0,0 +1,147 @@ +/* + * 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 + * + * 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.arrow.vector.dictionary; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.ValueVector; +import org.apache.arrow.vector.VarCharVector; +import org.apache.arrow.vector.types.pojo.DictionaryEncoding; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Benchmarks for {@link DictionaryEncoder}. + */ +@State(Scope.Benchmark) +public class DictionaryEncoderBenchmarks { + + private BufferAllocator allocator; + + private static final int DATA_SIZE = 1000; + private static final int KEY_SIZE = 100; + + + private static final int KEY_LENGTH = 10; + + private List<String> keys = new ArrayList<>(); + + private VarCharVector vector; + + private VarCharVector dictionaryVector; + + /** + * Setup benchmarks. + */ + @Setup + public void prepare() { + + for (int i = 0; i < KEY_SIZE; i++) { + keys.add(generateUniqueKey(KEY_LENGTH)); + } + + allocator = new RootAllocator(10 * 1024 * 1024); + + vector = new VarCharVector("vector", allocator); + dictionaryVector = new VarCharVector("dict", allocator); + + vector.allocateNew(10240, DATA_SIZE); + vector.setValueCount(DATA_SIZE); + for (int i = 0; i < DATA_SIZE; i++) { + byte[] value = keys.get(generateRandomIndex(KEY_SIZE)).getBytes(StandardCharsets.UTF_8); + vector.setSafe(i, value, 0, value.length); + } + + dictionaryVector.allocateNew(1024, 100); + dictionaryVector.setValueCount(100); + for (int i = 0; i < KEY_SIZE; i++) { + byte[] value = keys.get(i).getBytes(StandardCharsets.UTF_8); + dictionaryVector.setSafe(i, value, 0, value.length); + } + + } + + /** + * Tear down benchmarks. + */ + @TearDown + public void tearDown() { + vector.close(); + dictionaryVector.close(); + keys.clear(); + allocator.close(); + } + + /** + * Test encode for {@link DictionaryEncoder}. + * @return useless. To avoid DCE by JIT. + */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int testEncode() { + Dictionary dictionary = new Dictionary(dictionaryVector, new DictionaryEncoding(1L, false, null)); + final ValueVector encoded = DictionaryEncoder.encode(vector, dictionary); + encoded.close(); + return 0; + } + + private int generateRandomIndex(int max) { + Random random = new Random(); + return random.nextInt(max); + } + + private String generateUniqueKey(int length) { + String str = "abcdefghijklmnopqrstuvwxyz"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; i++) { + int number = random.nextInt(26); + sb.append(str.charAt(number)); + } + if (keys.contains(sb.toString())) { + return generateUniqueKey(length); + } + return sb.toString(); + } + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(DictionaryEncoderBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/ipc/WriteChannelBenchmark.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/ipc/WriteChannelBenchmark.java new file mode 100644 index 000000000..7a2537cbb --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/ipc/WriteChannelBenchmark.java @@ -0,0 +1,87 @@ +/* + * 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 + * + * 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.arrow.vector.ipc; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.channels.Channels; +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; +import org.openjdk.jmh.annotations.TearDown; +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; + +/** + * Benchmarks for {@link WriteChannel}. + */ +public class WriteChannelBenchmark { + + /** + * State object for align benchmark. + */ + @State(Scope.Benchmark) + public static class AlignState { + + private ByteArrayOutputStream baos; + + private WriteChannel writeChannel; + + @Param({"1", "2", "3", "4", "5", "6", "7"}) + public int alignSize; + + @Setup(Level.Invocation) + public void prepareInvoke() throws IOException { + baos = new ByteArrayOutputStream(8); + writeChannel = new WriteChannel(Channels.newChannel(baos)); + writeChannel.write(new byte[8 - alignSize]); + } + + @TearDown(Level.Invocation) + public void tearDownInvoke() throws IOException { + writeChannel.close(); + baos.close(); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void alignBenchmark(AlignState state) throws IOException { + state.writeChannel.align(); + } + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(WriteChannelBenchmark.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/ipc/message/ArrowRecordBatchBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/ipc/message/ArrowRecordBatchBenchmarks.java new file mode 100644 index 000000000..c0882821e --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/ipc/message/ArrowRecordBatchBenchmarks.java @@ -0,0 +1,98 @@ +/* + * 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 + * + * 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.arrow.vector.ipc.message; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.VarCharVector; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Benchmarks for {@link ArrowRecordBatch}. + */ +@State(Scope.Benchmark) +public class ArrowRecordBatchBenchmarks { + + private static final int VECTOR_CAPACITY = 16 * 1024; + + private static final int VECTOR_LENGTH = 1024; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private BufferAllocator allocator; + + private VarCharVector vector; + + private List<ArrowFieldNode> nodes; + + /** + * Setup benchmarks. + */ + @Setup + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + vector = new VarCharVector("vector", allocator); + vector.allocateNew(VECTOR_CAPACITY, VECTOR_LENGTH); + + nodes = new ArrayList<>(); + nodes.add(new ArrowFieldNode(VECTOR_LENGTH, 0)); + nodes.add(new ArrowFieldNode(VECTOR_LENGTH, 0)); + } + + /** + * Tear down benchmarks. + */ + @TearDown + public void tearDown() { + vector.close(); + allocator.close(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public long createAndGetLength() { + try (ArrowRecordBatch batch = new ArrowRecordBatch(VECTOR_LENGTH, nodes, vector.getFieldBuffers())) { + return batch.computeBodyLength(); + } + } + + public static void main(String [] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(ArrowRecordBatchBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/util/TransferPairBenchmarks.java b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/util/TransferPairBenchmarks.java new file mode 100644 index 000000000..235eca53c --- /dev/null +++ b/src/arrow/java/performance/src/test/java/org/apache/arrow/vector/util/TransferPairBenchmarks.java @@ -0,0 +1,123 @@ +/* + * 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 + * + * 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.arrow.vector.util; + +import java.nio.charset.StandardCharsets; +import java.util.concurrent.TimeUnit; + +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.IntVector; +import org.apache.arrow.vector.VarCharVector; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +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.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * Benchmarks for {@link TransferPair}. + */ +@State(Scope.Benchmark) +public class TransferPairBenchmarks { + + private static final int VECTOR_LENGTH = 1024; + + private static final int ALLOCATOR_CAPACITY = 1024 * 1024; + + private BufferAllocator allocator; + + private IntVector intVector; + + private VarCharVector varCharVector; + + /** + * Setup benchmarks. + */ + @Setup + public void prepare() { + allocator = new RootAllocator(ALLOCATOR_CAPACITY); + intVector = new IntVector("intVector", allocator); + varCharVector = new VarCharVector("varcharVector", allocator); + + intVector.allocateNew(VECTOR_LENGTH); + varCharVector.allocateNew(VECTOR_LENGTH); + + for (int i = 0; i < VECTOR_LENGTH; i++) { + if (i % 3 == 0) { + intVector.setNull(i); + varCharVector.setNull(i); + } else { + intVector.setSafe(i, i * i); + varCharVector.setSafe(i, ("teststring" + i).getBytes(StandardCharsets.UTF_8)); + } + } + intVector.setValueCount(VECTOR_LENGTH); + varCharVector.setValueCount(VECTOR_LENGTH); + } + + /** + * Tear down benchmarks. + */ + @TearDown + public void tearDown() { + intVector.close(); + varCharVector.close();; + allocator.close(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public int splitAndTransferIntVector() { + IntVector toVector = new IntVector("intVector", allocator); + toVector.setValueCount(VECTOR_LENGTH); + TransferPair transferPair = intVector.makeTransferPair(toVector); + transferPair.splitAndTransfer(0, VECTOR_LENGTH); + toVector.close(); + return 0; + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public int splitAndTransferVarcharVector() { + VarCharVector toVector = new VarCharVector("varcharVector", allocator); + toVector.setValueCount(VECTOR_LENGTH); + TransferPair transferPair = varCharVector.makeTransferPair(toVector); + transferPair.splitAndTransfer(0, VECTOR_LENGTH); + toVector.close(); + return 0; + } + + public static void main(String [] args) throws RunnerException { + Options opt = new OptionsBuilder() + .include(TransferPairBenchmarks.class.getSimpleName()) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} |