Skip to content

Commit e283cac

Browse files
committed
Add various improvements and cleanup
Continuation of #783
1 parent 194a8db commit e283cac

File tree

1 file changed

+36
-67
lines changed

1 file changed

+36
-67
lines changed

zstd/enc_best.go

Lines changed: 36 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
)
1313

1414
const (
15-
bestLongTableBits = 22 // Bits used in the long match table
15+
bestLongTableBits = 23 // Bits used in the long match table
1616
bestLongTableSize = 1 << bestLongTableBits // Size of the table
1717
bestLongLen = 8 // Bytes used for table hash
1818

@@ -188,7 +188,7 @@ encodeLoop:
188188
panic("offset0 was 0")
189189
}
190190

191-
const goodEnough = 100
191+
const goodEnough = 250
192192

193193
nextHashL := hashLen(cv, bestLongTableBits, bestLongLen)
194194
nextHashS := hashLen(cv, bestShortTableBits, bestShortLen)
@@ -234,17 +234,29 @@ encodeLoop:
234234
improve(&best, candidateS.prev-e.cur, s, uint32(cv), -1)
235235

236236
if canRepeat && best.length < goodEnough {
237-
cv32 := uint32(cv >> 8)
238-
spp := s + 1
239-
improve(&best, spp-offset1, spp, cv32, 1)
240-
improve(&best, spp-offset2, spp, cv32, 2)
241-
improve(&best, spp-offset3, spp, cv32, 3)
242-
if best.length > 0 {
243-
cv32 = uint32(cv >> 24)
244-
spp += 2
237+
if s == nextEmit {
238+
// Check repeats straight after a match.
239+
improve(&best, s-offset2, s, uint32(cv), 1|4)
240+
improve(&best, s-offset3, s, uint32(cv), 2|4)
241+
if offset1 > 1 {
242+
improve(&best, s-(offset1-1), s, uint32(cv), 3|4)
243+
}
244+
}
245+
246+
// If either no match or a non-repeat match, check at + 1
247+
if best.rep <= 0 {
248+
cv32 := uint32(cv >> 8)
249+
spp := s + 1
245250
improve(&best, spp-offset1, spp, cv32, 1)
246251
improve(&best, spp-offset2, spp, cv32, 2)
247252
improve(&best, spp-offset3, spp, cv32, 3)
253+
if best.rep < 0 {
254+
cv32 = uint32(cv >> 24)
255+
spp += 2
256+
improve(&best, spp-offset1, spp, cv32, 1)
257+
improve(&best, spp-offset2, spp, cv32, 2)
258+
improve(&best, spp-offset3, spp, cv32, 3)
259+
}
248260
}
249261
}
250262
// Load next and check...
@@ -263,7 +275,7 @@ encodeLoop:
263275
continue
264276
}
265277

266-
s++
278+
s := s + 1
267279
candidateS = e.table[hashLen(cv>>8, bestShortTableBits, bestShortLen)]
268280
cv = load6432(src, s)
269281
cv2 := load6432(src, s+1)
@@ -307,23 +319,22 @@ encodeLoop:
307319

308320
// We have a match, we can store the forward value
309321
if best.rep > 0 {
310-
s = best.s
311322
var seq seq
312323
seq.matchLen = uint32(best.length - zstdMinMatch)
313324
if debugAsserts && s <= nextEmit {
314325
panic("s <= nextEmit")
315326
}
316-
addLiterals(&seq, s)
327+
addLiterals(&seq, best.s)
317328

318-
// rep 0
319-
seq.offset = uint32(best.rep)
329+
// Repeat. If bit 4 is set, this is a non-lit repeat.
330+
seq.offset = uint32(best.rep & 3)
320331
if debugSequences {
321332
println("repeat sequence", seq, "next s:", s)
322333
}
323334
blk.sequences = append(blk.sequences, seq)
324335

325-
// Index match start+1 (long) -> s - 1
326-
index0 := s
336+
// Index old s + 1 -> s - 1
337+
index0 := s + 1
327338
s = best.s + best.length
328339

329340
nextEmit = s
@@ -336,7 +347,7 @@ encodeLoop:
336347
}
337348
// Index skipped...
338349
off := index0 + e.cur
339-
for index0 < s-1 {
350+
for index0 < s {
340351
cv0 := load6432(src, index0)
341352
h0 := hashLen(cv0, bestLongTableBits, bestLongLen)
342353
h1 := hashLen(cv0, bestShortTableBits, bestShortLen)
@@ -346,17 +357,20 @@ encodeLoop:
346357
index0++
347358
}
348359
switch best.rep {
349-
case 2:
360+
case 2, 4 | 1:
350361
offset1, offset2 = offset2, offset1
351-
case 3:
362+
case 3, 4 | 2:
352363
offset1, offset2, offset3 = offset3, offset1, offset2
364+
case 4 | 3:
365+
offset1, offset2, offset3 = offset1-1, offset1, offset2
353366
}
354367
cv = load6432(src, s)
355368
continue
356369
}
357370

358371
// A 4-byte match has been found. Update recent offsets.
359372
// We'll later see if more than 4 bytes.
373+
index0 := s + 1
360374
s = best.s
361375
t := best.offset
362376
offset1, offset2, offset3 = s-t, offset1, offset2
@@ -388,10 +402,8 @@ encodeLoop:
388402
break encodeLoop
389403
}
390404

391-
// Index match start+1 (long) -> s - 1
392-
index0 := s - l + 1
393-
// every entry
394-
for index0 < s-1 {
405+
// Index old s + 1 -> s - 1
406+
for index0 < s {
395407
cv0 := load6432(src, index0)
396408
h0 := hashLen(cv0, bestLongTableBits, bestLongLen)
397409
h1 := hashLen(cv0, bestShortTableBits, bestShortLen)
@@ -400,50 +412,7 @@ encodeLoop:
400412
e.table[h1] = prevEntry{offset: off, prev: e.table[h1].offset}
401413
index0++
402414
}
403-
404415
cv = load6432(src, s)
405-
if !canRepeat {
406-
continue
407-
}
408-
409-
// Check offset 2
410-
for {
411-
o2 := s - offset2
412-
if load3232(src, o2) != uint32(cv) {
413-
// Do regular search
414-
break
415-
}
416-
417-
// Store this, since we have it.
418-
nextHashS := hashLen(cv, bestShortTableBits, bestShortLen)
419-
nextHashL := hashLen(cv, bestLongTableBits, bestLongLen)
420-
421-
// We have at least 4 byte match.
422-
// No need to check backwards. We come straight from a match
423-
l := 4 + e.matchlen(s+4, o2+4, src)
424-
425-
e.longTable[nextHashL] = prevEntry{offset: s + e.cur, prev: e.longTable[nextHashL].offset}
426-
e.table[nextHashS] = prevEntry{offset: s + e.cur, prev: e.table[nextHashS].offset}
427-
seq.matchLen = uint32(l) - zstdMinMatch
428-
seq.litLen = 0
429-
430-
// Since litlen is always 0, this is offset 1.
431-
seq.offset = 1
432-
s += l
433-
nextEmit = s
434-
if debugSequences {
435-
println("sequence", seq, "next s:", s)
436-
}
437-
blk.sequences = append(blk.sequences, seq)
438-
439-
// Swap offset 1 and 2.
440-
offset1, offset2 = offset2, offset1
441-
if s >= sLimit {
442-
// Finished
443-
break encodeLoop
444-
}
445-
cv = load6432(src, s)
446-
}
447416
}
448417

449418
if int(nextEmit) < len(src) {

0 commit comments

Comments
 (0)