Skip to content

Commit

Permalink
Use bits.OnesCount64 when available
Browse files Browse the repository at this point in the history
Benchmark on i7-2600k, which has the POPCNT instruction:

name                 old time/op  new time/op  delta
DistanceIdentical-8  5.08ns ± 0%  1.01ns ± 1%  -80.07%  (p=0.008 n=5+5)
DistanceDifferent-8  81.5ns ± 2%   1.0ns ± 0%  -98.76%  (p=0.016 n=5+4)

Benchmark on Cavium Octeon, a MIPS64 platform with no dedicated
instruction:

name                 old time/op  new time/op  delta
DistanceIdentical-2   120ns ± 6%   144ns ± 5%  +19.93%  (p=0.008 n=5+5)
DistanceDifferent-2   656ns ± 4%   144ns ± 4%  -78.09%  (p=0.008 n=5+5)
  • Loading branch information
dominikh authored and corona10 committed May 2, 2018
1 parent 7f23d56 commit ad2b6de
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 7 deletions.
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
## AUTHORS
- [Dominik Honnef](https://github.com/dominikh) dominik@honnef.co
- [Dong-hee Na](https://github.com/corona10/) donghee.na92@gmail.com
- [Gustavo Brunoro](https://github.com/brunoro/) git@hitnail.net
18 changes: 18 additions & 0 deletions hashcompute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,21 @@ func TestHashCompute(t *testing.T) {
}
}
}

func BenchmarkDistanceIdentical(b *testing.B) {
h1 := &ImageHash{hash: 0xe48ae53c05e502f7}
h2 := &ImageHash{hash: 0xe48ae53c05e502f7}

for i := 0; i < b.N; i++ {
h1.Distance(h2)
}
}

func BenchmarkDistanceDifferent(b *testing.B) {
h1 := &ImageHash{hash: 0xe48ae53c05e502f7}
h2 := &ImageHash{hash: 0x678be53815e510f7} // 8 bits flipped

for i := 0; i < b.N; i++ {
h1.Distance(h2)
}
}
8 changes: 1 addition & 7 deletions imagehash.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,11 @@ func (h *ImageHash) Distance(other *ImageHash) (int, error) {
return -1, errors.New("Image hashes's kind should be identical")
}

diff := 0
lhash := h.GetHash()
rhash := other.GetHash()

hamming := lhash ^ rhash
for hamming != 0 {
diff += int(hamming & 1)
hamming >>= 1
}

return diff, nil
return popcnt(hamming), nil
}

// GetHash method returns a 64bits hash value.
Expand Down
13 changes: 13 additions & 0 deletions imagehash18.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// +build !go1.9

package goimagehash

func popcnt(x uint64) int {
diff := 0
for x != 0 {
diff += int(x & 1)
x >>= 1
}

return diff
}
9 changes: 9 additions & 0 deletions imagehash19.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// +build go1.9

package goimagehash

import (
"math/bits"
)

func popcnt(x uint64) int { return bits.OnesCount64(x) }

0 comments on commit ad2b6de

Please sign in to comment.