Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
plog-common, with netty-friendly murmurhash3
plog-common should include code that doesn't fit in the API or distribution, but benefits from being shared between many components. As getting out of ByteBufs for checksumming turns out expensive, but Guava doesn't expose any API allowing us to checksum Netty buffers, get started with a naive implementation (hopefully not too naive).
- Loading branch information
Pierre Carrier
committed
May 7, 2014
1 parent
18f8db5
commit 90e6c82
Showing
8 changed files
with
115 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
dependencies { | ||
compile project(':plog-api') | ||
compile project(':plog-common') | ||
|
||
testCompile project(':plog-server') | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
plog-common/src/main/java/com/airbnb/plog/common/Murmur3.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package com.airbnb.plog.common; | ||
|
||
import io.netty.buffer.ByteBuf; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
import java.nio.ByteOrder; | ||
|
||
@Slf4j | ||
public class Murmur3 { | ||
private static final int C1 = 0xcc9e2d51; | ||
private static final int C2 = 0x1b873593; | ||
|
||
public static int hash32(ByteBuf data) { | ||
return hash32(data, data.readerIndex(), data.readableBytes(), 0); | ||
} | ||
|
||
public static int hash32(ByteBuf data, final int offset, final int length) { | ||
return hash32(data, offset, length, 0); | ||
} | ||
|
||
public static int hash32(ByteBuf data, final int offset, final int length, final int seed) { | ||
final ByteBuf ordered = data.order(ByteOrder.LITTLE_ENDIAN); | ||
|
||
int h = seed; | ||
|
||
final int len4 = length >>> 2; | ||
final int end4 = offset + (len4 << 2); | ||
|
||
for (int i = offset; i < end4; i += 4) { | ||
int k = ordered.getInt(i); | ||
|
||
k *= C1; | ||
k = k << 15 | k >>> 17; | ||
k *= C2; | ||
|
||
h ^= k; | ||
h = h << 13 | h >>> 19; | ||
h = h * 5 + 0xe6546b64; | ||
} | ||
|
||
int k = 0; | ||
switch (length & 3) { | ||
case 3: | ||
k = ordered.getByte(end4 + 2) << 16; | ||
case 2: | ||
k |= ordered.getByte(end4 + 1) << 8; | ||
case 1: | ||
k |= ordered.getByte(end4); | ||
|
||
k *= C1; | ||
k = (k << 15) | (k >>> 17); | ||
k *= C2; | ||
h ^= k; | ||
} | ||
|
||
h ^= length; | ||
h ^= h >>> 16; | ||
h *= 0x85ebca6b; | ||
h ^= h >>> 13; | ||
h *= 0xc2b2ae35; | ||
h ^= h >>> 16; | ||
|
||
return h; | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
plog-common/src/test/groovy/com/airbnb/plog/common/Murmur3Test.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.airbnb.plog.common | ||
|
||
import com.google.common.hash.Hashing | ||
import io.netty.buffer.Unpooled | ||
|
||
class Murmur3Test extends GroovyTestCase { | ||
void testGuavaCompat() { | ||
final raw = 'abcdefghijklmnopqrstuvwxyz'.bytes | ||
|
||
for (seed in [0, 1, 10]) | ||
for (len in 0..20) { | ||
final model = Arrays.copyOf(raw, len) | ||
final guavaHash = Hashing.murmur3_32(seed).hashBytes(model).asInt() | ||
final plogHash = Murmur3.hash32(Unpooled.wrappedBuffer(model), 0, len, seed) | ||
assert plogHash == guavaHash | ||
} | ||
} | ||
|
||
void testOffsetsAndLength() { | ||
final raw = 'abcdef'.bytes | ||
final bb = Unpooled.wrappedBuffer(raw) | ||
|
||
for (from in 0..raw.length) | ||
for (to in from..raw.length) { | ||
final model = Arrays.copyOfRange(raw, from, to) | ||
final guavaHash = Hashing.murmur3_32().hashBytes(model).asInt() | ||
final plogHash = Murmur3.hash32(bb, from, to - from, 0) | ||
assert plogHash == guavaHash | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters