Skip to content

Commit

Permalink
s2: Better should not search repeat value (#325)
Browse files Browse the repository at this point in the history
* s2: No repeat checks

Remove repeat checks in better mode since they are no often than not stealing better matches.

Instead check if matches are repeats when emitting.
```
nyc-taxi:
Compressing... 3325605752 -> 954776589 [28.71%]; 492ms, 6445.5MB/s
Compressing... 3325605752 -> 935022950 [28.12%]; 489ms, 6485.8MB/s
Decompressing. 954776589 -> 3325605752 [348.31%]; 2.434s, 1302.9MB/s
Decompressing. 935022950 -> 3325605752 [355.67%]; 2.297s, 1381.0MB/s

enwik9:
Compressing... 1000000000 -> 426854233 [42.69%]; 213ms, 4477.3MB/s
Compressing... 1000000000 -> 426242923 [42.62%]; 219ms, 4354.7MB/s
Decompressing. 426242923 -> 1000000000 [234.61%]; 996ms, 957.0MB/s
Decompressing. 426854233 -> 1000000000 [234.27%]; 1.009s, 945.2MB/s
```
  • Loading branch information
klauspost committed Feb 26, 2021
1 parent 68c9310 commit 005d22e
Show file tree
Hide file tree
Showing 3 changed files with 1,935 additions and 2,854 deletions.
85 changes: 51 additions & 34 deletions s2/_generate/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -869,8 +869,8 @@ func (o options) genEncodeBetterBlockAsm(name string, lTableBits, skipLog, lHash
// s = 1
s := GP32()
MOVL(U32(1), s)
// repeatL = 1
MOVL(s, repeatL)
// repeatL = 0
MOVL(U32(0), repeatL)

src := GP64()
Load(Param("src").Base(), src)
Expand Down Expand Up @@ -938,7 +938,7 @@ func (o options) genEncodeBetterBlockAsm(name string, lTableBits, skipLog, lHash
}

// En/disable repeat matching.
if true {
if false {
// Check repeat at offset checkRep
const checkRep = 1
{
Expand Down Expand Up @@ -1203,40 +1203,57 @@ func (o options) genEncodeBetterBlockAsm(name string, lTableBits, skipLog, lHash
})
a, b, srcLeft = nil, nil, nil

// Update repeat
offset := GP64()
offset32 := offset.As32()
{
// repeat = base - candidate
repeatVal := GP64().As32()
MOVL(s, repeatVal)
SUBL(candidate, repeatVal)
// Check if match is better..
if o.maxLen > 65535 {
CMPL(length.As32(), U8(1))
JG(LabelRef("match_length_ok_" + name))
CMPL(repeatVal, U32(65535))
JLE(LabelRef("match_length_ok_" + name))
// Match is equal or worse to the encoding.
MOVL(nextSTempL, s)
INCL(s)
JMP(LabelRef("search_loop_" + name))
Label("match_length_ok_" + name)
// offset = base - candidate
MOVL(s, offset32)
SUBL(candidate, offset32)
Comment("Check if repeat")
CMPL(repeatL, offset32)
JEQ(LabelRef("match_is_repeat_" + name))

// NOT REPEAT
{
// Check if match is better..
if o.maxLen > 65535 {
CMPL(length.As32(), U8(1))
JG(LabelRef("match_length_ok_" + name))
CMPL(offset32, U32(65535))
JLE(LabelRef("match_length_ok_" + name))
// Match is equal or worse to the encoding.
MOVL(nextSTempL, s)
INCL(s)
JMP(LabelRef("search_loop_" + name))
Label("match_length_ok_" + name)
}
// Store updated repeat
MOVL(offset32, repeatL)
// Emit....
o.emitLiteralsDstP(nextEmitL, base, src, dst, "match_emit_"+name)
// s += length (length is destroyed, use it now)
ADDL(length.As32(), s)

// length += 4
ADDL(U8(4), length.As32())
MOVL(s, nextEmitL) // nextEmit = s
o.emitCopy("match_nolit_"+name, length, offset, nil, dst, LabelRef("match_nolit_emitcopy_end_"+name))
// Jumps at end
}
// REPEAT
{
Label("match_is_repeat_" + name)
// Emit....
o.emitLiteralsDstP(nextEmitL, base, src, dst, "match_emit_repeat_"+name)
// s += length (length is destroyed, use it now)
ADDL(length.As32(), s)

// length += 4
ADDL(U8(4), length.As32())
MOVL(s, nextEmitL) // nextEmit = s
o.emitRepeat("match_nolit_repeat_"+name, length, offset, nil, dst, LabelRef("match_nolit_emitcopy_end_"+name))
}
// Store updated repeat
MOVL(repeatVal, repeatL)
}
// Emit....
o.emitLiteralsDstP(nextEmitL, base, src, dst, "match_emit_"+name)
// s += length (length is destroyed, use it now)
ADDL(length.As32(), s)

// Load offset from repeat value.
offset := GP64()
MOVL(repeatL, offset.As32())

// length += 4
ADDL(U8(4), length.As32())
MOVL(s, nextEmitL) // nextEmit = s
o.emitCopy("match_nolit_"+name, length, offset, nil, dst, LabelRef("match_nolit_emitcopy_end_"+name))
Label("match_nolit_emitcopy_end_" + name)

// if s >= sLimit { end }
Expand Down
16 changes: 10 additions & 6 deletions s2/encode_better.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ func encodeBlockBetterGo(dst, src []byte) (d int) {
s := 1
cv := load64(src, s)

// We search for a repeat at -1, but don't output repeats when nextEmit == 0
repeat := 1
// We initialize repeat to 0, so we never match on first attempt
repeat := 0

for {
candidateL := 0
Expand All @@ -99,7 +99,7 @@ func encodeBlockBetterGo(dst, src []byte) (d int) {

// Check repeat at offset checkRep.
const checkRep = 1
if uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) {
if false && uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) {
base := s + checkRep
// Extend back
for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; {
Expand Down Expand Up @@ -184,7 +184,7 @@ func encodeBlockBetterGo(dst, src []byte) (d int) {
candidateL += 8
}

if offset > 65535 && s-base <= 5 {
if offset > 65535 && s-base <= 5 && repeat != offset {
// Bail if the match is equal or worse to the encoding.
s = nextS + 1
if s >= sLimit {
Expand All @@ -193,9 +193,13 @@ func encodeBlockBetterGo(dst, src []byte) (d int) {
cv = load64(src, s)
continue
}
repeat = offset
d += emitLiteral(dst[d:], src[nextEmit:base])
d += emitCopy(dst[d:], offset, s-base)
if repeat == offset {
d += emitRepeat(dst[d:], offset, s-base)
} else {
d += emitCopy(dst[d:], offset, s-base)
repeat = offset
}

nextEmit = s
if s >= sLimit {
Expand Down
Loading

0 comments on commit 005d22e

Please sign in to comment.