Read multiple bytes in findMatchLengthWithLimit

Use 64- or 32-bit loads instead of reading a byte at a time. The
original C source did something like this, in a very C-ish way. It
needed to be simplified to translate it to Go. The exact way this works
was suggested by the assembly code in github.com/golang/snappy.
This commit is contained in:
Andy Balholm 2020-05-15 10:43:19 -07:00
parent a01a7b12c9
commit 8f8b18645c
2 changed files with 30 additions and 1 deletions

View File

@ -461,8 +461,9 @@ func BenchmarkEncodeLevelsReset(b *testing.B) {
w := NewWriterLevel(buf, level)
w.Write(opticks)
w.Close()
b.Run(fmt.Sprintf("%d(%.1f%%)", level, float64(buf.Len())/float64(len(opticks))*100), func(b *testing.B) {
b.Run(fmt.Sprintf("%d", level), func(b *testing.B) {
b.ReportAllocs()
b.ReportMetric(float64(len(opticks))/float64(buf.Len()), "ratio")
b.SetBytes(int64(len(opticks)))
for i := 0; i < b.N; i++ {
w.Reset(ioutil.Discard)

View File

@ -1,5 +1,11 @@
package brotli
import (
"encoding/binary"
"math/bits"
"runtime"
)
/* Copyright 2010 Google Inc. All Rights Reserved.
Distributed under MIT license.
@ -10,6 +16,28 @@ package brotli
func findMatchLengthWithLimit(s1 []byte, s2 []byte, limit uint) uint {
var matched uint = 0
_, _ = s1[limit-1], s2[limit-1] // bounds check
switch runtime.GOARCH {
case "amd64":
// Compare 8 bytes at at time.
for matched+8 <= limit {
w1 := binary.LittleEndian.Uint64(s1[matched:])
w2 := binary.LittleEndian.Uint64(s2[matched:])
if w1 != w2 {
return matched + uint(bits.TrailingZeros64(w1^w2)>>3)
}
matched += 8
}
case "386":
// Compare 4 bytes at at time.
for matched+4 <= limit {
w1 := binary.LittleEndian.Uint32(s1[matched:])
w2 := binary.LittleEndian.Uint32(s2[matched:])
if w1 != w2 {
return matched + uint(bits.TrailingZeros32(w1^w2)>>3)
}
matched += 4
}
}
for matched < limit && s1[matched] == s2[matched] {
matched++
}