Skip to content

Commit

Permalink
Merge pull request #9 from ewdurbin/pypy_go_faster
Browse files Browse the repository at this point in the history
fallback to pure python implementation for non CPython interpreters
  • Loading branch information
ewdurbin committed Jun 30, 2015
2 parents 457ce0a + 570dcbe commit 4375b94
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 55 deletions.
4 changes: 2 additions & 2 deletions clandestined/clandestined.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

from collections import defaultdict

from . import _murmur3
from . import murmur3


class RendezvousHash(object):
Expand All @@ -11,7 +11,7 @@ def __init__(self, nodes=None, seed=0):
self.seed = seed
if nodes is not None:
self.nodes = nodes
self.hash_function = lambda x: _murmur3.murmur3_32(x, seed)
self.hash_function = lambda x: murmur3.murmur3_32(x, seed)

def add_node(self, node):
if node not in self.nodes:
Expand Down
119 changes: 69 additions & 50 deletions clandestined/murmur3.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,69 @@
## MurmurHash3 was written by Austin Appleby, and is placed in the public
## domain. The author hereby disclaims copyright to this source code.

def murmur3_x86_32(data, seed = 0):
c1 = 0xcc9e2d51
c2 = 0x1b873593

length = len(data)
h1 = seed
roundedEnd = (length & 0xfffffffc) # round down to 4 byte block
for i in range(0, roundedEnd, 4):
# little endian load order
k1 = (ord(data[i]) & 0xff) | ((ord(data[i + 1]) & 0xff) << 8) | \
((ord(data[i + 2]) & 0xff) << 16) | (ord(data[i + 3]) << 24)
k1 *= c1
k1 = (k1 << 15) | ((k1 & 0xffffffff) >> 17) # ROTL32(k1,15)
k1 *= c2

h1 ^= k1
h1 = (h1 << 13) | ((h1 & 0xffffffff) >> 19) # ROTL32(h1,13)
h1 = h1 * 5 + 0xe6546b64

# tail
k1 = 0

val = length & 0x03
if val == 3:
k1 = (ord(data[roundedEnd + 2]) & 0xff) << 16
# fallthrough
if val in [2, 3]:
k1 |= (ord(data[roundedEnd + 1]) & 0xff) << 8
# fallthrough
if val in [1, 2, 3]:
k1 |= ord(data[roundedEnd]) & 0xff
k1 *= c1
k1 = (k1 << 15) | ((k1 & 0xffffffff) >> 17) # ROTL32(k1,15)
k1 *= c2
h1 ^= k1

# finalization
h1 ^= length

# fmix(h1)
h1 ^= ((h1 & 0xffffffff) >> 16)
h1 *= 0x85ebca6b
h1 ^= ((h1 & 0xffffffff) >> 13)
h1 *= 0xc2b2ae35
h1 ^= ((h1 & 0xffffffff) >> 16)

return h1 & 0xffffffff

try:
import __pypy__
MURMUR3_IS_PYPY = True
except ImportError:
MURMUR3_IS_PYPY = False

try:
from . import _murmur3
MURMUR3_FALLBACK = False
except ImportError:
MURMUR3_FALLBACK = True


if MURMUR3_IS_PYPY or MURMUR3_FALLBACK:
def murmur3_32(data, seed = 0):
"""MurmurHash3 was written by Austin Appleby, and is placed in the
public domain. The author hereby disclaims copyright to this source
code."""

c1 = 0xcc9e2d51
c2 = 0x1b873593

length = len(data)
h1 = seed
roundedEnd = (length & 0xfffffffc) # round down to 4 byte block
for i in range(0, roundedEnd, 4):
# little endian load order
k1 = (ord(data[i]) & 0xff) | ((ord(data[i + 1]) & 0xff) << 8) | \
((ord(data[i + 2]) & 0xff) << 16) | (ord(data[i + 3]) << 24)
k1 *= c1
k1 = (k1 << 15) | ((k1 & 0xffffffff) >> 17) # ROTL32(k1,15)
k1 *= c2

h1 ^= k1
h1 = (h1 << 13) | ((h1 & 0xffffffff) >> 19) # ROTL32(h1,13)
h1 = h1 * 5 + 0xe6546b64

# tail
k1 = 0

val = length & 0x03
if val == 3:
k1 = (ord(data[roundedEnd + 2]) & 0xff) << 16
# fallthrough
if val in [2, 3]:
k1 |= (ord(data[roundedEnd + 1]) & 0xff) << 8
# fallthrough
if val in [1, 2, 3]:
k1 |= ord(data[roundedEnd]) & 0xff
k1 *= c1
k1 = (k1 << 15) | ((k1 & 0xffffffff) >> 17) # ROTL32(k1,15)
k1 *= c2
h1 ^= k1

# finalization
h1 ^= length

# fmix(h1)
h1 ^= ((h1 & 0xffffffff) >> 16)
h1 *= 0x85ebca6b
h1 ^= ((h1 & 0xffffffff) >> 13)
h1 *= 0xc2b2ae35
h1 ^= ((h1 & 0xffffffff) >> 16)

return h1 & 0xffffffff

else:
murmur3_32 = _murmur3.murmur3_32
6 changes: 3 additions & 3 deletions clandestined/test/test_collision.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ def mock_murmur3_32(key, seed=0):
class CollisionTestCase(unittest.TestCase):

def setUp(self):
self.original_murmur3_32 = clandestined._murmur3.murmur3_32
clandestined._murmur3.murmur3_32 = mock_murmur3_32
self.original_murmur3_32 = clandestined.murmur3.murmur3_32
clandestined.murmur3.murmur3_32 = mock_murmur3_32

def tearDown(self):
clandestined._murmur3.murmur3_32 = self.original_murmur3_32
clandestined.murmur3.murmur3_32 = self.original_murmur3_32

def test_monkey_patch(self):
rendezvous = RendezvousHash()
Expand Down

0 comments on commit 4375b94

Please sign in to comment.