Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
- ea
- develop
pull_request:
types: [opened, synchronize, reopened]
types: [ opened, synchronize, reopened ]
jobs:
build:
name: Build
Expand Down
11 changes: 6 additions & 5 deletions .mvn/wrapper/MavenWrapperDownloader.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.net.*;
import java.io.*;
import java.nio.channels.*;
Expand All @@ -25,7 +26,7 @@ public class MavenWrapperDownloader {
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";

/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
Expand Down Expand Up @@ -54,7 +55,7 @@ public static void main(String args[]) {
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
if (mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Expand All @@ -65,7 +66,7 @@ public static void main(String args[]) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
if (mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
Expand All @@ -76,8 +77,8 @@ public static void main(String args[]) {
System.out.println("- Downloading from: " + url);

File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
if (!outputFile.getParentFile().exists()) {
if (!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
Expand Down
20 changes: 10 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ jobs:
- arch: s390x
jdk: openjdk7 # target release on big-endian machine
install:
- wget -O ibmjdk7.bin -q -T 10 -t 5 https://public.dhe.ibm.com/ibmdl/export/pub/systems/cloud/runtimes/java/7.1.4.85/linux/s390x/ibm-java-sdk-7.1-4.85-s390x-archive.bin
- echo "6a901bc0b713582a323481d5b41d0c289cbd6fbb265eefb4962080240fe59ff2 ibmjdk7.bin" | sha256sum -c -
- chmod +x ibmjdk7.bin
- echo "INSTALLER_UI=silent" > response.properties
- echo "USER_INSTALL_DIR=$PWD/ibmjdk7" >> response.properties
- echo "LICENSE_ACCEPTED=TRUE" >> response.properties
- ./ibmjdk7.bin -i silent -f response.properties
- export PATH="$PWD/ibmjdk7/bin:$PATH"
- export JAVA_HOME="$PWD/ibmjdk7"
- java -version
- wget -O ibmjdk7.bin -q -T 10 -t 5 https://public.dhe.ibm.com/ibmdl/export/pub/systems/cloud/runtimes/java/7.1.4.85/linux/s390x/ibm-java-sdk-7.1-4.85-s390x-archive.bin
- echo "6a901bc0b713582a323481d5b41d0c289cbd6fbb265eefb4962080240fe59ff2 ibmjdk7.bin" | sha256sum -c -
- chmod +x ibmjdk7.bin
- echo "INSTALLER_UI=silent" > response.properties
- echo "USER_INSTALL_DIR=$PWD/ibmjdk7" >> response.properties
- echo "LICENSE_ACCEPTED=TRUE" >> response.properties
- ./ibmjdk7.bin -i silent -f response.properties
- export PATH="$PWD/ibmjdk7/bin:$PATH"
- export JAVA_HOME="$PWD/ibmjdk7"
- java -version

cache:
directories:
Expand Down
67 changes: 33 additions & 34 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
== Zero-Allocation Hashing

Chronicle Software

image:https://maven-badges.herokuapp.com/maven-central/net.openhft/zero-allocation-hashing/badge.svg[caption="",link=https://maven-badges.herokuapp.com/maven-central/net.openhft/zero-allocation-hashing]
Expand All @@ -12,38 +13,31 @@ toc::[]

== About

This project provides a Java API for hashing any sequence of bytes in Java, including all kinds of
primitive arrays, buffers, `CharSequence` and more.
This project provides a Java API for hashing any sequence of bytes in Java, including all kinds of primitive arrays, buffers, `CharSequence` and more.

Written for Java 7+ under Apache 2.0 license.

The key difference compared to other similar projects, e.g.
https://guava.dev/releases/28.1-jre/api/docs/com/google/common/hash/package-summary.html[Guava hashing],
is that this has no object allocation during the hash computation and does not use `ThreadLocal`.
https://guava.dev/releases/28.1-jre/api/docs/com/google/common/hash/package-summary.html[Guava hashing], is that this has no object allocation during the hash computation and does not use `ThreadLocal`.

The implementation utilises native access where possible, but is also platform-endianness-agnostic.
This provides consistent results whatever the byte order, while only moderately affecting
performance.
This provides consistent results whatever the byte order, while only moderately affecting performance.

Currently `long`-valued hash function interface is defined for 64-bit hash, and `long[]`-valued hash function interface for more than 64-bit hash, with the following implementations (in alphabetical order):

Currently `long`-valued hash function interface is defined for 64-bit hash, and `long[]`-valued hash
function interface for more than 64-bit hash, with the following implementations (in alphabetical
order):
- *https://github.com/google/cityhash[CityHash], version 1.1* (latest; 1.1.1 is a C++ language-specific maintenance release).

- *https://github.com/google/cityhash[CityHash], version 1.1* (latest; 1.1.1 is a C++
language-specific maintenance release).
- Two algorithms from *https://github.com/google/farmhash[FarmHash]*: `farmhashna` (introduced in FarmHash 1.0) and `farmhashuo` (introduced in FarmHash 1.1).

- Two algorithms from *https://github.com/google/farmhash[FarmHash]*: `farmhashna` (introduced
in FarmHash 1.0) and `farmhashuo` (introduced in FarmHash 1.1).
- *https://github.com/jandrewrogers/MetroHash[MetroHash]* (using the metrohash64_2 initialization vector).

- *https://github.com/jandrewrogers/MetroHash[MetroHash]* (using the metrohash64_2 initialization vector).
- *https://github.com/aappleby/smhasher/wiki/MurmurHash3[MurmurHash3]* 128-bit and low 64-bit.

- *https://github.com/aappleby/smhasher/wiki/MurmurHash3[MurmurHash3]* 128-bit and low 64-bit.
- *https://github.com/wangyi-fudan/wyhash[wyHash]*, version 3.

- *https://github.com/wangyi-fudan/wyhash[wyHash]*, version 3.
- *https://github.com/Cyan4973/xxHash[xxHash]*.

- *https://github.com/Cyan4973/xxHash[xxHash]*.

- *https://github.com/Cyan4973/xxHash[xxh3, xxh128]*, 128-bit and 64 bit.
- *https://github.com/Cyan4973/xxHash[xxh3, xxh128]*, 128-bit and 64 bit.

These are thoroughly tested with
*https://www.oracle.com/java/technologies/java-se-support-roadmap.html[LTS JDKs]*
Expand All @@ -53,6 +47,7 @@ Other non-LTS JDKs from 9 should also work, but they will not be tested from hal
==== Performance

Tested on Intel Core i7-4870HQ CPU @ 2.50GHz

|===
|Algorithm |Speed, GB/s |Bootstrap, ns

Expand All @@ -69,43 +64,47 @@ Tested on Intel Core i7-4870HQ CPU @ 2.50GHz
To sum up,

==== When to use Zero-Allocation Hashing
* You need to hash plain byte sequences, memory blocks or "flat" objects.
* You want zero-allocation and good performance (at Java scale).
* You need hashing to be agile with regards to byte ordering.

* You need to hash plain byte sequences, memory blocks or "flat" objects.
* You want zero-allocation and good performance (at Java scale).
* You need hashing to be agile with regards to byte ordering.

==== When _not_ to use Zero-Allocation Hashing
* You need to hash POJOs whose actual data is scattered in memory between managed objects.
There is no simple way to hash these using this project, for example, classes such as:

* You need to hash POJOs whose actual data is scattered in memory between managed objects.
There is no simple way to hash these using this project, for example, classes such as:
+
[source, Java]
[source,Java]
----
class Person {
String givenName, surName;
int salary;
}
----

* You need to hash byte sequences of unknown length, for the simpliest example,
`Iterator<Byte>`.
* You need to hash byte sequences of unknown length, for the simpliest example,
`Iterator<Byte>`.

* You need to transform the byte sequence (e.g. encode or decode it with a specific coding),
and hash the resulting byte sequence on the way without dumping it to memory.
* You need to transform the byte sequence (e.g. encode or decode it with a specific coding), and hash the resulting byte sequence on the way without dumping it to memory.

==== Java Doc

See http://javadoc.io/doc/net.openhft/zero-allocation-hashing/latest

== Quick start

Gradle:
[source, groovy]

[source,groovy]
----
dependencies {
implementation 'net.openhft:zero-allocation-hashing:0.16'
}
----

Or Maven:
[source, xml]

[source,xml]
----
<dependency>
<groupId>net.openhft</groupId>
Expand All @@ -115,13 +114,13 @@ Or Maven:
----

In Java:
[source, Java]

[source,Java]
----
long hash = LongHashFunction.wy_3().hashChars("hello");
----

See *http://javadoc.io/doc/net.openhft/zero-allocation-hashing/0.15[JavaDocs]* for more
information.
See *http://javadoc.io/doc/net.openhft/zero-allocation-hashing/0.15[JavaDocs]* for more information.

== Contributions are most welcome!

Expand Down
19 changes: 11 additions & 8 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,23 @@
~ 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">
<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">

<parent>
<parent>
<groupId>net.openhft</groupId>
<artifactId>java-parent-pom</artifactId>
<version>1.27ea1</version>
<relativePath />
<relativePath/>
</parent>

<modelVersion>4.0.0</modelVersion>
<artifactId>zero-allocation-hashing</artifactId>
<version>0.27ea2-SNAPSHOT</version>
<name>Zero-allocation Hashing</name>
<description>Zero-allocation implementations of fast non-cryptographic hash functions
for byte sequences or blocks of memory</description>
for byte sequences or blocks of memory
</description>
<inceptionYear>2014</inceptionYear>
<url>https://github.com/OpenHFT/Zero-Allocation-Hashing</url>
<packaging>bundle</packaging>
Expand Down Expand Up @@ -237,15 +239,16 @@
</executions>
</plugin>


<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>3.0.0-M4</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.scm</groupId>
<artifactId>maven-scm-provider-gitexe</artifactId>
<version>1.11.2</version> <!-- this version should be sync with the scmVersion of maven-release-plugin -->
<version>1.11.2
</version> <!-- this version should be sync with the scmVersion of maven-release-plugin -->
</dependency>
</dependencies>
</plugin>
Expand All @@ -264,7 +267,7 @@
</configuration>
</plugin>

<plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${maven.bundle.plugin.version}</version>
Expand Down Expand Up @@ -317,7 +320,7 @@
<properties>
<project.jdk.min-version>1.${project.target.release}</project.jdk.min-version>
<maven.bundle.plugin.version>3.5.1</maven.bundle.plugin.version>
<doclint />
<doclint/>
</properties>
</profile>
<profile>
Expand Down
8 changes: 5 additions & 3 deletions src/main/java-stub/java/lang/Math.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

/**
* Stub for JDK internal ckass java.lang.Math.
*
* <p>
* - When crossing compiling for Java SE 7 and 8, this stub class can be used for detecting
* Math#multiplyHigh() method at runtime.
* Math#multiplyHigh() method at runtime.
* - Only used methods are exported.
* - In test and production runtime, the real class is loaded from boot classpath.
*/

public class Math {
public static long multiplyHigh(long x, long y) { throw new UnsupportedOperationException(); }
public static long multiplyHigh(long x, long y) {
throw new UnsupportedOperationException();
}
}
23 changes: 15 additions & 8 deletions src/main/java-stub/sun/misc/Unsafe.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,29 @@

/**
* Stub for JDK internal ckass sun.misc.Unsafe.
*
* <p>
* - When crossing compiling for Java SE 7 and 8, this stub class can bypass compiler sun-api
* warnings.
* warnings.
* - Only used methods are exported.
* - In test and production runtime, the real class is loaded from boot classpath.
*/

public final class Unsafe {
public native Object getObject( Object o, long offset);
public native int getInt( Object o, long offset);
public native Object getObject(Object o, long offset);

public native int getInt(Object o, long offset);

public native boolean getBoolean(Object o, long offset);
public native byte getByte( Object o, long offset);
public native short getShort( Object o, long offset);
public native char getChar( Object o, long offset);
public native long getLong( Object o, long offset);

public native byte getByte(Object o, long offset);

public native short getShort(Object o, long offset);

public native char getChar(Object o, long offset);

public native long getLong(Object o, long offset);

public native long objectFieldOffset(java.lang.reflect.Field f);

public native int arrayBaseOffset(Class arrayClass);
}
Loading
Loading