Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions benchmarks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Microbenchmarks

This maven project provides microbenchmarks for `cuvs-lucene` using JMH.

To run do (if on current directory):

```sh
cd .. && mvn clean install -DskipTests && cd benchmarks && mvn clean install && java -jar target/benchmarks.jar
```
183 changes: 183 additions & 0 deletions benchmarks/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
<!--
/*
* SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
-->

<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>

<groupId>com.nvidia.cuvs.lucene.benchmarks</groupId>
<artifactId>cuvs-lucene-benchmarks</artifactId>
<!--CUVS_JAVA#VERSION_UPDATE_MARKER_START--><version>26.02.0</version><!--CUVS_JAVA#VERSION_UPDATE_MARKER_END-->
<packaging>jar</packaging>

<name>cuvs-lucene-benchmarks</name>

<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>com.nvidia.cuvs.lucene</groupId>
<artifactId>cuvs-lucene</artifactId>
<!--CUVS_LUCENE#VERSION_UPDATE_MARKER_START--><version>26.02.0</version><!--CUVS_LUCENE#VERSION_UPDATE_MARKER_END-->
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.18.0</version>
</dependency>
</dependencies>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jmh.version>1.37</jmh.version>
<javac.target>22</javac.target>
<maven.compiler.target>22</maven.compiler.target>
<maven.compiler.source>22</maven.compiler.source>
<uberjar.name>benchmarks</uberjar.name>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
<manifestEntries>
<Multi-Release>true</Multi-Release>
<addClasspath>true</addClasspath>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>2.44.5</version>
<executions>
<execution>
<goals>
<goal>apply</goal>
</goals>
<phase>validate</phase>
</execution>
</executions>
<configuration>
<java>
<includes>
<include>src/**/*.java</include>
</includes>
<googleJavaFormat>
<version>1.27.0</version>
<style>GOOGLE</style>
<reflowLongStrings>true</reflowLongStrings>
<formatJavadoc>false</formatJavadoc>
</googleJavaFormat>
<licenseHeader>
<file>../license-header.txt</file>
</licenseHeader>
</java>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<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>3.2.1</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>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</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>
</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>3.4.2</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>2.17</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
package com.nvidia.cuvs.lucene.benchmarks;

import static com.nvidia.cuvs.lucene.benchmarks.Utils.cleanup;
import static com.nvidia.cuvs.lucene.benchmarks.Utils.generateDataset;
import static com.nvidia.cuvs.lucene.benchmarks.Utils.index;

import com.nvidia.cuvs.lucene.Lucene101AcceleratedHNSWCodec;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.apache.lucene.codecs.Codec;
import org.apache.lucene.index.IndexWriterConfig;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;

@BenchmarkMode(Mode.All)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
@Fork(value = 1)
@Warmup(iterations = 0, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS)
public class AcceleratedHnswIndexingBenchmarks {

@SuppressWarnings("unused")
private static Logger log = Logger.getLogger(AcceleratedHnswIndexingBenchmarks.class.getName());

private static Random random;
private static Path indexDirPath;
private static Codec codec;

private final int COMMIT_FREQ = 100;
private final String ID_FIELD = "id";
private final String VECTOR_FIELD = "vector_field";

private int numDocs;
private int dimension;
private float[][] dataset;

@Setup(Level.Trial)
public void setup() throws Exception {
random = new Random(222);
indexDirPath = Paths.get(UUID.randomUUID().toString());
codec = new Lucene101AcceleratedHNSWCodec(32, 128, 64, 3, 16, 100);
numDocs = 1000;
dimension = 128;
dataset = generateDataset(random, numDocs, dimension);
}

@Benchmark
public void benchmarkAcceleratedHnswIndexing(Blackhole blackhole) throws Exception {
IndexWriterConfig config = new IndexWriterConfig().setCodec(codec).setUseCompoundFile(false);
index(indexDirPath, config, dataset, numDocs, VECTOR_FIELD, ID_FIELD, COMMIT_FREQ);
}

@TearDown(Level.Trial)
public void tearDown() throws IOException {
cleanup(indexDirPath);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
package com.nvidia.cuvs.lucene.benchmarks;

import static com.nvidia.cuvs.lucene.benchmarks.Utils.cleanup;
import static com.nvidia.cuvs.lucene.benchmarks.Utils.generateDataset;
import static com.nvidia.cuvs.lucene.benchmarks.Utils.index;
import static com.nvidia.cuvs.lucene.benchmarks.Utils.search;

import com.nvidia.cuvs.lucene.Lucene101AcceleratedHNSWCodec;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.apache.lucene.codecs.Codec;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.KnnFloatVectorQuery;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;

@BenchmarkMode(Mode.All)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
@Fork(value = 1)
@Warmup(iterations = 0, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS)
public class AcceleratedHnswSearchBenchmarks {

@SuppressWarnings("unused")
private static Logger log = Logger.getLogger(AcceleratedHnswSearchBenchmarks.class.getName());

private static Random random;
private static Path indexDirPath;
private static Codec codec;

private final int COMMIT_FREQ = 100;
private final String ID_FIELD = "id";
private final String VECTOR_FIELD = "vector_field";

private int numDocs;
private int dimension;
private int topK;
private float[][] dataset;
private float[] queryVector;

@Setup(Level.Trial)
public void setup() throws Exception {
random = new Random(222);
indexDirPath = Paths.get(UUID.randomUUID().toString());
codec = new Lucene101AcceleratedHNSWCodec(32, 128, 64, 3, 16, 100);
numDocs = 1000;
dimension = 128;
topK = 5;
dataset = generateDataset(random, numDocs, dimension);
queryVector = generateDataset(random, 1, dimension)[0];
IndexWriterConfig config = new IndexWriterConfig().setCodec(codec).setUseCompoundFile(false);
index(indexDirPath, config, dataset, numDocs, VECTOR_FIELD, ID_FIELD, COMMIT_FREQ);
}

@Benchmark
public void benchmarkAcceleratedHnswSearch(Blackhole blackhole) throws Exception {
KnnFloatVectorQuery query = new KnnFloatVectorQuery(VECTOR_FIELD, queryVector, topK);
search(indexDirPath, VECTOR_FIELD, queryVector, topK, query);
}

@TearDown(Level.Trial)
public void tearDown() throws IOException {
cleanup(indexDirPath);
}
}
Loading