Skip to content

Commit

Permalink
Use encoding/binary instead of unsafe (fixes spaolacci#29)
Browse files Browse the repository at this point in the history
This removes the incorrect unsafe usage, instead using the marshalling
operations from encoding/binary.

Obviously, it's a bit slower:

	benchmark                    old ns/op     new ns/op     delta
	Benchmark32/1-8              4.68          5.02          +7.26%
	Benchmark32/2-8              5.15          5.16          +0.19%
	Benchmark32/4-8              5.05          5.56          +10.10%
	Benchmark32/8-8              6.10          6.95          +13.93%
	Benchmark32/16-8             8.18          9.94          +21.52%
	Benchmark32/32-8             12.5          15.4          +23.20%
	Benchmark32/64-8             20.7          26.7          +28.99%
	Benchmark32/128-8            38.3          55.9          +45.95%
	Benchmark32/256-8            75.8          94.1          +24.14%
	Benchmark32/512-8            150           191           +27.33%
	Benchmark32/1024-8           299           375           +25.42%
	Benchmark32/2048-8           586           730           +24.57%
	Benchmark32/4096-8           1170          1450          +23.93%
	Benchmark32/8192-8           2347          2888          +23.05%
	BenchmarkPartial32/8-8       157           155           -1.27%
	BenchmarkPartial32/16-8      185           184           -0.54%
	BenchmarkPartial32/32-8      243           240           -1.23%
	BenchmarkPartial32/64-8      201           206           +2.49%
	BenchmarkPartial32/128-8     223           240           +7.62%
	Benchmark64/1-8              12.3          12.2          -0.81%
	Benchmark64/2-8              12.8          12.9          +0.78%
	Benchmark64/4-8              14.2          13.9          -2.11%
	Benchmark64/8-8              16.1          15.5          -3.73%
	Benchmark64/16-8             13.7          15.3          +11.68%
	Benchmark64/32-8             16.2          19.2          +18.52%
	Benchmark64/64-8             20.3          26.4          +30.05%
	Benchmark64/128-8            28.8          40.8          +41.67%
	Benchmark64/256-8            47.3          68.8          +45.45%
	Benchmark64/512-8            81.8          126           +54.03%
	Benchmark64/1024-8           151           242           +60.26%
	Benchmark64/2048-8           291           477           +63.92%
	Benchmark64/4096-8           566           948           +67.49%
	Benchmark64/8192-8           1115          1873          +67.98%
	Benchmark128/1-8             12.9          12.9          +0.00%
	Benchmark128/2-8             13.2          13.5          +2.27%
	Benchmark128/4-8             14.3          14.2          -0.70%
	Benchmark128/8-8             15.9          16.1          +1.26%
	Benchmark128/16-8            13.6          16.0          +17.65%
	Benchmark128/32-8            15.9          20.0          +25.79%
	Benchmark128/64-8            20.5          26.9          +31.22%
	Benchmark128/128-8           29.1          41.2          +41.58%
	Benchmark128/256-8           46.5          69.6          +49.68%
	Benchmark128/512-8           81.0          126           +55.56%
	Benchmark128/1024-8          150           244           +62.67%
	Benchmark128/2048-8          292           471           +61.30%
	Benchmark128/4096-8          566           921           +62.72%
	Benchmark128/8192-8          1115          1868          +67.53%

Nonetheless, it's correct and doesn't crash.
  • Loading branch information
calmh committed Feb 26, 2020
1 parent 539464a commit 74e9af8
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 12 deletions.
6 changes: 3 additions & 3 deletions murmur128.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package murmur3

import (
//"encoding/binary"
"encoding/binary"
"hash"
"math/bits"
"unsafe"
)

const (
Expand Down Expand Up @@ -65,8 +65,8 @@ func (d *digest128) bmix(p []byte) (tail []byte) {

nblocks := len(p) / 16
for i := 0; i < nblocks; i++ {
t := (*[2]uint64)(unsafe.Pointer(&p[i*16]))
k1, k2 := t[0], t[1]
k1 := binary.LittleEndian.Uint64(p[i*16:])
k2 := binary.LittleEndian.Uint64(p[i*16+8:])

k1 *= c1_128
k1 = bits.RotateLeft64(k1, 31)
Expand Down
13 changes: 4 additions & 9 deletions murmur32.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package murmur3
// http://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/hash/Murmur3_32HashFunction.java

import (
"encoding/binary"
"hash"
"math/bits"
"unsafe"
)

// Make sure interfaces are correctly implemented.
Expand Down Expand Up @@ -53,7 +53,7 @@ func (d *digest32) bmix(p []byte) (tail []byte) {

nblocks := len(p) / 4
for i := 0; i < nblocks; i++ {
k1 := *(*uint32)(unsafe.Pointer(&p[i*4]))
k1 := binary.LittleEndian.Uint32(p[i*4:])

k1 *= c1_32
k1 = bits.RotateLeft32(k1, 15)
Expand Down Expand Up @@ -115,13 +115,8 @@ func Sum32WithSeed(data []byte, seed uint32) uint32 {
h1 := seed

nblocks := len(data) / 4
var p uintptr
if len(data) > 0 {
p = uintptr(unsafe.Pointer(&data[0]))
}
p1 := p + uintptr(4*nblocks)
for ; p < p1; p += 4 {
k1 := *(*uint32)(unsafe.Pointer(p))
for i := 0; i < nblocks; i++ {
k1 := binary.LittleEndian.Uint32(data[i*4:])

k1 *= c1_32
k1 = bits.RotateLeft32(k1, 15)
Expand Down
11 changes: 11 additions & 0 deletions murmur_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,14 @@ func Benchmark128(b *testing.B) {
})
}
}

func TestUnalignedWrite(t *testing.T) {
// Causes "fatal error: checkptr: unsafe pointer conversion" for unsafe
// pointer conversions in Go 1.14+
b := make([]byte, 128)
for i := 0; i < 16; i++ {
Sum32(b[i:])
Sum64(b[i:])
Sum128(b[i:])
}
}

0 comments on commit 74e9af8

Please sign in to comment.