ccitt: speed up the highBits function
Also fix s/PackBits/HighBits/ typos in reader_test.go.
name old time/op new time/op delta
HighBits-4 34.8µs ± 2% 11.0µs ± 1% -68.45% (p=0.008 n=5+5)
Change-Id: Id5af14536edb66c5313b6fcf711872e5025cb503
Reviewed-on: https://go-review.googlesource.com/c/image/+/191941
Run-TryBot: Nigel Tao <nigeltao@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Horst Rutter <hhrutter@gmail.com>
Reviewed-by: Benny Siegert <bsiegert@gmail.com>
diff --git a/ccitt/reader.go b/ccitt/reader.go
index 792a9ce..df14833 100644
--- a/ccitt/reader.go
+++ b/ccitt/reader.go
@@ -88,24 +88,37 @@
// are typically temporary, e.g. they will be flipped back to 0s by an
// invertBytes call in the highBits caller, reader.Read.
func highBits(dst []byte, src []byte, invert bool) (d int, s int) {
- for d < len(dst) {
- numToPack := len(src) - s
- if numToPack <= 0 {
- break
- } else if numToPack > 8 {
- numToPack = 8
- }
+ // Pack as many complete groups of 8 src bytes as we can.
+ n := len(src) / 8
+ if n > len(dst) {
+ n = len(dst)
+ }
+ dstN := dst[:n]
+ for i := range dstN {
+ src8 := src[i*8 : i*8+8]
+ dstN[i] = ((src8[0] & 0x80) >> 0) |
+ ((src8[1] & 0x80) >> 1) |
+ ((src8[2] & 0x80) >> 2) |
+ ((src8[3] & 0x80) >> 3) |
+ ((src8[4] & 0x80) >> 4) |
+ ((src8[5] & 0x80) >> 5) |
+ ((src8[6] & 0x80) >> 6) |
+ ((src8[7] & 0x80) >> 7)
+ }
+ d, s = n, 8*n
+ dst, src = dst[d:], src[s:]
- byteValue := byte(0)
+ // Pack up to 7 remaining src bytes, if there's room in dst.
+ if (len(dst) > 0) && (len(src) > 0) {
+ dstByte := byte(0)
if invert {
- byteValue = 0xFF >> uint(numToPack)
+ dstByte = 0xFF >> uint(len(src))
}
- for n := 0; n < numToPack; n++ {
- byteValue |= (src[s] & 0x80) >> uint(n)
- s++
+ for n, srcByte := range src {
+ dstByte |= (srcByte & 0x80) >> uint(n)
}
- dst[d] = byteValue
- d++
+ dst[0] = dstByte
+ d, s = d+1, s+len(src)
}
return d, s
}
diff --git a/ccitt/reader_test.go b/ccitt/reader_test.go
index 80c0e9f..01fcff0 100644
--- a/ccitt/reader_test.go
+++ b/ccitt/reader_test.go
@@ -73,7 +73,7 @@
return d, s
}
-func TestPackBits(t *testing.T) {
+func TestHighBits(t *testing.T) {
rng := rand.New(rand.NewSource(1))
dst0 := make([]byte, 3)
dst1 := make([]byte, 3)
@@ -114,7 +114,7 @@
}
}
-func BenchmarkPackBits(b *testing.B) {
+func BenchmarkHighBits(b *testing.B) {
rng := rand.New(rand.NewSource(1))
dst := make([]byte, 1024)
src := make([]byte, 7777)