Skip to content

Commit

Permalink
flate: Inline literal emission (#509)
Browse files Browse the repository at this point in the history
~2% faster.

Emit long matches as length 255, since it saves bits.
  • Loading branch information
klauspost committed Mar 1, 2022
1 parent bf9102c commit 84e0164
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 15 deletions.
4 changes: 3 additions & 1 deletion flate/deflate_test.go
Expand Up @@ -157,7 +157,8 @@ func TestVeryLongSparseChunk(t *testing.T) {
if testing.Short() {
t.Skip("skipping sparse chunk during short test")
}
w, err := NewWriter(ioutil.Discard, 1)
var buf bytes.Buffer
w, err := NewWriter(&buf, 1)
if err != nil {
t.Errorf("NewWriter: %v", err)
return
Expand All @@ -166,6 +167,7 @@ func TestVeryLongSparseChunk(t *testing.T) {
t.Errorf("Compress failed: %v", err)
return
}
t.Log("Length:", buf.Len())
}

type syncBuffer struct {
Expand Down
17 changes: 14 additions & 3 deletions flate/level1.go
Expand Up @@ -154,7 +154,15 @@ func (e *fastEncL1) Encode(dst *tokens, src []byte) {
l++
}
if nextEmit < s {
emitLiteral(dst, src[nextEmit:s])
if false {
emitLiteral(dst, src[nextEmit:s])
} else {
for _, v := range src[nextEmit:s] {
dst.tokens[dst.n] = token(v)
dst.litHist[v]++
dst.n++
}
}
}

// Save the match found
Expand All @@ -169,8 +177,11 @@ func (e *fastEncL1) Encode(dst *tokens, src []byte) {
for xlength > 0 {
xl := xlength
if xl > 258 {
// We need to have at least baseMatchLength left over for next loop.
xl = 258 - baseMatchLength
if xl > 258+baseMatchLength {
xl = 258
} else {
xl = 258 - baseMatchLength
}
}
xlength -= xl
xl -= baseMatchLength
Expand Down
10 changes: 9 additions & 1 deletion flate/level2.go
Expand Up @@ -134,7 +134,15 @@ func (e *fastEncL2) Encode(dst *tokens, src []byte) {
l++
}
if nextEmit < s {
emitLiteral(dst, src[nextEmit:s])
if false {
emitLiteral(dst, src[nextEmit:s])
} else {
for _, v := range src[nextEmit:s] {
dst.tokens[dst.n] = token(v)
dst.litHist[v]++
dst.n++
}
}
}

dst.AddMatchLong(l, uint32(s-t-baseMatchOffset))
Expand Down
10 changes: 9 additions & 1 deletion flate/level3.go
Expand Up @@ -143,7 +143,15 @@ func (e *fastEncL3) Encode(dst *tokens, src []byte) {
l++
}
if nextEmit < s {
emitLiteral(dst, src[nextEmit:s])
if false {
emitLiteral(dst, src[nextEmit:s])
} else {
for _, v := range src[nextEmit:s] {
dst.tokens[dst.n] = token(v)
dst.litHist[v]++
dst.n++
}
}
}

dst.AddMatchLong(l, uint32(s-t-baseMatchOffset))
Expand Down
10 changes: 9 additions & 1 deletion flate/level4.go
Expand Up @@ -135,7 +135,15 @@ func (e *fastEncL4) Encode(dst *tokens, src []byte) {
l++
}
if nextEmit < s {
emitLiteral(dst, src[nextEmit:s])
if false {
emitLiteral(dst, src[nextEmit:s])
} else {
for _, v := range src[nextEmit:s] {
dst.tokens[dst.n] = token(v)
dst.litHist[v]++
dst.n++
}
}
}
if debugDeflate {
if t >= s {
Expand Down
10 changes: 9 additions & 1 deletion flate/level5.go
Expand Up @@ -210,7 +210,15 @@ func (e *fastEncL5) Encode(dst *tokens, src []byte) {
l++
}
if nextEmit < s {
emitLiteral(dst, src[nextEmit:s])
if false {
emitLiteral(dst, src[nextEmit:s])
} else {
for _, v := range src[nextEmit:s] {
dst.tokens[dst.n] = token(v)
dst.litHist[v]++
dst.n++
}
}
}
if debugDeflate {
if t >= s {
Expand Down
10 changes: 9 additions & 1 deletion flate/level6.go
Expand Up @@ -243,7 +243,15 @@ func (e *fastEncL6) Encode(dst *tokens, src []byte) {
l++
}
if nextEmit < s {
emitLiteral(dst, src[nextEmit:s])
if false {
emitLiteral(dst, src[nextEmit:s])
} else {
for _, v := range src[nextEmit:s] {
dst.tokens[dst.n] = token(v)
dst.litHist[v]++
dst.n++
}
}
}
if false {
if t >= s {
Expand Down
10 changes: 9 additions & 1 deletion flate/stateless.go
Expand Up @@ -249,7 +249,15 @@ func statelessEnc(dst *tokens, src []byte, startAt int16) {
l++
}
if nextEmit < s {
emitLiteral(dst, src[nextEmit:s])
if false {
emitLiteral(dst, src[nextEmit:s])
} else {
for _, v := range src[nextEmit:s] {
dst.tokens[dst.n] = token(v)
dst.litHist[v]++
dst.n++
}
}
}

// Save the match found
Expand Down
13 changes: 8 additions & 5 deletions flate/token.go
Expand Up @@ -195,12 +195,11 @@ func (t *tokens) indexTokens(in []token) {

// emitLiteral writes a literal chunk and returns the number of bytes written.
func emitLiteral(dst *tokens, lit []byte) {
ol := int(dst.n)
for i, v := range lit {
dst.tokens[(i+ol)&maxStoreBlockSize] = token(v)
for _, v := range lit {
dst.tokens[dst.n] = token(v)
dst.litHist[v]++
dst.n++
}
dst.n += uint16(len(lit))
}

func (t *tokens) AddLiteral(lit byte) {
Expand Down Expand Up @@ -294,7 +293,11 @@ func (t *tokens) AddMatchLong(xlength int32, xoffset uint32) {
xl := xlength
if xl > 258 {
// We need to have at least baseMatchLength left over for next loop.
xl = 258 - baseMatchLength
if xl > 258+baseMatchLength {
xl = 258
} else {
xl = 258 - baseMatchLength
}
}
xlength -= xl
xl -= baseMatchLength
Expand Down

0 comments on commit 84e0164

Please sign in to comment.