Skip to content

Instantly share code, notes, and snippets.

@rzwitserloot
Created December 17, 2019 11:44
Show Gist options
  • Save rzwitserloot/ecc249e8391d0699ca6a4c6904ddd585 to your computer and use it in GitHub Desktop.
Save rzwitserloot/ecc249e8391d0699ca6a4c6904ddd585 to your computer and use it in GitHub Desktop.
create via:
mvn archetype:generate -DinteractiveMode=false -DarchetypeGroupId=org.openjdk.jmh -DarchetypeArtifactId=jmh-java-benchmark-archetype -DgroupId=com.zwitserloot -DartifactId=boyermoore -Dversion=1.0
package com.zwitserloot;
import org.openjdk.jmh.annotations.*;
import java.nio.charset.*;
import java.util.Arrays;
public class MyBenchmark {
private static final int HAYSTACK_SIZE = 100;
public static void main(String[] args) {
MyState s = new MyState();
s.setup();
MyBenchmark b = new MyBenchmark();
int idx1 = b.java(s);
int idx2 = b.boyerMoore(s);
int w = s.HAYSTACK.length() - s.NEEDLE.length();
if (idx1 != w) System.out.println("java code broken");
if (idx2 != w) System.out.println("B-M code broken");
}
@State(Scope.Benchmark)
public static class MyState {
public String NEEDLE, HAYSTACK;
public byte[] _NEEDLE, _HAYSTACK;
@Setup(Level.Trial)
public void setup() {
Charset cs = StandardCharsets.US_ASCII;
byte[] base = "Hello, world! I am a string; perhaps I can ananate how, for ananananananars, and more!".getBytes(cs);
byte[] answer = "ananas".getBytes(cs);
_HAYSTACK = new byte[base.length * HAYSTACK_SIZE + answer.length];
_NEEDLE = answer;
NEEDLE = new String(_NEEDLE, cs);
for (int i = 0; i < HAYSTACK_SIZE; i++) System.arraycopy(base, 0, _HAYSTACK, base.length * i, base.length);
System.arraycopy(answer, 0, _HAYSTACK, base.length * HAYSTACK_SIZE, answer.length);
HAYSTACK = new String(_HAYSTACK, cs);
}
}
@Benchmark
public int java(MyState state) {
return state.HAYSTACK.indexOf(state.NEEDLE);
}
@Benchmark
public int boyerMoore(MyState state) {
byte[] NEEDLE = state._NEEDLE, HAYSTACK = state._HAYSTACK;
if (NEEDLE.length == 0) return 0;
int[] ct = makeCharTable(NEEDLE);
int[] ot = makeOffsetTable(NEEDLE);
for (int i = NEEDLE.length - 1, j; i < HAYSTACK.length;) {
for (j = NEEDLE.length - 1; NEEDLE[j] == HAYSTACK[i]; --i, --j) {
if (j == 0) return i;
}
i += Math.max(ot[NEEDLE.length - 1 - j], ct[HAYSTACK[i]]);
}
return -1;
}
private static int[] makeCharTable(byte[] needle) {
final int A = 128, len = needle.length;
int[] t = new int[A];
Arrays.fill(t, len);
for (int i = 0; i < len - 2; i++) t[needle[i]] = len - 1 - i;
return t;
}
private static int[] makeOffsetTable(byte[] needle) {
int len = needle.length;
int[] t = new int[len];
int lastPrefixPosition = len;
for (int i = len; i > 0; --i) {
if (isPrefix(needle, i)) lastPrefixPosition = i;
t[len - i] = lastPrefixPosition - i + len;
}
for (int i = 0; i < len - 1; i++) {
int sLen = suffixLength(needle, i);
t[sLen] = len - 1 - i + sLen;
}
return t;
}
private static boolean isPrefix(byte[] needle, int p) {
for (int i = p, j = 0; i < needle.length; ++i, ++j) if (needle[i] != needle[j]) return false;
return true;
}
private static int suffixLength(byte[] needle, int p) {
int len = 0;
for (int i = p, j = needle.length - 1; i >= 0 && needle[i] == needle[j]; --i, --j) len++;
return len;
}
}
<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.zwitserloot</groupId>
<artifactId>boyermoore</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>JMH benchmark sample: Java</name>
<!--
This is the demo/sample template build script for building Java benchmarks with JMH.
Edit as needed.
-->
<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>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--
JMH version to use with this project.
-->
<jmh.version>1.22</jmh.version>
<!--
Java source/target to use for compilation.
-->
<javac.target>1.8</javac.target>
<!--
Name of the benchmark Uber-JAR to generate.
-->
<uberjar.name>benchmarks</uberjar.name>
</properties>
<build>
<plugins>
<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>
<!--
Shading signed JARs will fail without this.
http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar
-->
<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>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>2.17</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment