]> Cypherpunks repositories - gostls13.git/commitdiff
math/bits: much faster ReverseBytes, added respective benchmarks
authorRobert Griesemer <gri@golang.org>
Fri, 17 Feb 2017 19:32:08 +0000 (11:32 -0800)
committerRobert Griesemer <gri@golang.org>
Fri, 17 Feb 2017 19:38:26 +0000 (19:38 +0000)
Measured on 2.3 GHz Intel Core i7, running maxOS 10.12.3.

benchmark                     old ns/op     new ns/op     delta
BenchmarkReverseBytes-8       11.4          3.51          -69.21%
BenchmarkReverseBytes16-8     6.87          0.64          -90.68%
BenchmarkReverseBytes32-8     7.79          0.65          -91.66%
BenchmarkReverseBytes64-8     11.6          0.64          -94.48%

name              old time/op  new time/op  delta
ReverseBytes-8    11.4ns ± 0%   3.5ns ± 0%   ~     (p=1.000 n=1+1)
ReverseBytes16-8  6.87ns ± 0%  0.64ns ± 0%   ~     (p=1.000 n=1+1)
ReverseBytes32-8  7.79ns ± 0%  0.65ns ± 0%   ~     (p=1.000 n=1+1)
ReverseBytes64-8  11.6ns ± 0%   0.6ns ± 0%   ~     (p=1.000 n=1+1)

Change-Id: I67b529652b3b613c61687e9e185e8d4ee40c51a2
Reviewed-on: https://go-review.googlesource.com/37211
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/math/bits/bits.go
src/math/bits/bits_impl.go
src/math/bits/bits_test.go

index ab3f3eaa1e943b19b904b59d920158c62bc7ba1f..9bbc2c58836406447176ef74b73cfc386c68534c 100644 (file)
@@ -113,7 +113,7 @@ func Reverse(x uint) uint {
 
 // Reverse8 returns the value of x with its bits in reversed order.
 func Reverse8(x uint8) uint8 {
-       const m = 0xff
+       const m = 1<<8 - 1
        x = x&(m0&m)>>1 | x&^(m0&m)<<1
        x = x&(m1&m)>>2 | x&^(m1&m)<<2
        x = x&(m2&m)>>4 | x&^(m2&m)<<4
@@ -122,7 +122,7 @@ func Reverse8(x uint8) uint8 {
 
 // Reverse16 returns the value of x with its bits in reversed order.
 func Reverse16(x uint16) uint16 {
-       const m = 0xffff
+       const m = 1<<16 - 1
        x = x&(m0&m)>>1 | x&^(m0&m)<<1
        x = x&(m1&m)>>2 | x&^(m1&m)<<2
        x = x&(m2&m)>>4 | x&^(m2&m)<<4
@@ -132,7 +132,7 @@ func Reverse16(x uint16) uint16 {
 
 // Reverse32 returns the value of x with its bits in reversed order.
 func Reverse32(x uint32) uint32 {
-       const m = 0xffffffff
+       const m = 1<<32 - 1
        x = x&(m0&m)>>1 | x&^(m0&m)<<1
        x = x&(m1&m)>>2 | x&^(m1&m)<<2
        x = x&(m2&m)>>4 | x&^(m2&m)<<4
@@ -143,7 +143,7 @@ func Reverse32(x uint32) uint32 {
 
 // Reverse64 returns the value of x with its bits in reversed order.
 func Reverse64(x uint64) uint64 {
-       const m = 0xffffffffffffffff
+       const m = 1<<64 - 1
        x = x&(m0&m)>>1 | x&^(m0&m)<<1
        x = x&(m1&m)>>2 | x&^(m1&m)<<2
        x = x&(m2&m)>>4 | x&^(m2&m)<<4
@@ -156,16 +156,36 @@ func Reverse64(x uint64) uint64 {
 // --- ReverseBytes ---
 
 // ReverseBytes returns the value of x with its bytes in reversed order.
-func ReverseBytes(x uint) uint { return uint(swap(uint64(x), UintSize)) }
+func ReverseBytes(x uint) uint {
+       if UintSize == 32 {
+               return uint(ReverseBytes32(uint32(x)))
+       }
+       return uint(ReverseBytes64(uint64(x)))
+}
 
 // ReverseBytes16 returns the value of x with its bytes in reversed order.
-func ReverseBytes16(x uint16) uint16 { return uint16(swap(uint64(x), 16)) }
+func ReverseBytes16(x uint16) uint16 {
+       const m = 1<<16 - 1
+       x = x&(m3&m)>>8 | x&^(m3&m)<<8
+       return x
+}
 
 // ReverseBytes32 returns the value of x with its bytes in reversed order.
-func ReverseBytes32(x uint32) uint32 { return uint32(swap(uint64(x), 32)) }
+func ReverseBytes32(x uint32) uint32 {
+       const m = 1<<32 - 1
+       x = x&(m3&m)>>8 | x&^(m3&m)<<8
+       x = x&(m4&m)>>16 | x&^(m4&m)<<16
+       return x
+}
 
 // ReverseBytes64 returns the value of x with its bytes in reversed order.
-func ReverseBytes64(x uint64) uint64 { return uint64(swap(uint64(x), 64)) }
+func ReverseBytes64(x uint64) uint64 {
+       const m = 1<<64 - 1
+       x = x&(m3&m)>>8 | x&^(m3&m)<<8
+       x = x&(m4&m)>>16 | x&^(m4&m)<<16
+       x = x&(m5&m)>>32 | x&^(m5&m)<<32
+       return x
+}
 
 // --- Len ---
 
index da38429fee1c5b4e64ca27ff53a51e59b78533e0..3a425e3b83c66d4a18c708cc7e4f453c5e4a821d 100644 (file)
@@ -93,14 +93,6 @@ func rot(x uint64, size, k uint) uint64 {
        return x<<k | x>>(size-k)&(1<<k-1)
 }
 
-func swap(x uint64, size uint) (r uint64) {
-       for i := size / 8; i > 0; i-- {
-               r = r<<8 | x&0xff
-               x >>= 8
-       }
-       return
-}
-
 func blen(x uint64) (i int) {
        for ; x >= 1<<(16-1); x >>= 16 {
                i += 16
index bba35612fe3cb130816aa40364d1496332f160cc..e1c7201daa47d835155f329a348711d3edc36f2c 100644 (file)
@@ -453,6 +453,30 @@ func testReverseBytes(t *testing.T, x64, want64 uint64) {
        }
 }
 
+func BenchmarkReverseBytes(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               ReverseBytes(deBruijn64 & (1<<UintSize - 1))
+       }
+}
+
+func BenchmarkReverseBytes16(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               ReverseBytes16(deBruijn64 & (1<<16 - 1))
+       }
+}
+
+func BenchmarkReverseBytes32(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               ReverseBytes32(deBruijn64 & (1<<32 - 1))
+       }
+}
+
+func BenchmarkReverseBytes64(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               ReverseBytes64(deBruijn64 & (1<<64 - 1))
+       }
+}
+
 func TestLen(t *testing.T) {
        for i := 0; i < 256; i++ {
                len := 8 - tab[i].nlz