From: Robert Griesemer Date: Fri, 17 Feb 2017 19:32:08 +0000 (-0800) Subject: math/bits: much faster ReverseBytes, added respective benchmarks X-Git-Tag: go1.9beta1~1518 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=ddb15cea4a02c403160c2d9772f85c122cbc8248;p=gostls13.git math/bits: much faster ReverseBytes, added respective benchmarks 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 Reviewed-by: Matthew Dempsky --- diff --git a/src/math/bits/bits.go b/src/math/bits/bits.go index ab3f3eaa1e..9bbc2c5883 100644 --- a/src/math/bits/bits.go +++ b/src/math/bits/bits.go @@ -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 --- diff --git a/src/math/bits/bits_impl.go b/src/math/bits/bits_impl.go index da38429fee..3a425e3b83 100644 --- a/src/math/bits/bits_impl.go +++ b/src/math/bits/bits_impl.go @@ -93,14 +93,6 @@ func rot(x uint64, size, k uint) uint64 { return x<>(size-k)&(1< 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 diff --git a/src/math/bits/bits_test.go b/src/math/bits/bits_test.go index bba35612fe..e1c7201daa 100644 --- a/src/math/bits/bits_test.go +++ b/src/math/bits/bits_test.go @@ -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<