@@ -12,7 +12,7 @@ import (
12
12
)
13
13
14
14
const (
15
- bestLongTableBits = 22 // Bits used in the long match table
15
+ bestLongTableBits = 23 // Bits used in the long match table
16
16
bestLongTableSize = 1 << bestLongTableBits // Size of the table
17
17
bestLongLen = 8 // Bytes used for table hash
18
18
@@ -188,7 +188,7 @@ encodeLoop:
188
188
panic ("offset0 was 0" )
189
189
}
190
190
191
- const goodEnough = 100
191
+ const goodEnough = 250
192
192
193
193
nextHashL := hashLen (cv , bestLongTableBits , bestLongLen )
194
194
nextHashS := hashLen (cv , bestShortTableBits , bestShortLen )
@@ -205,7 +205,37 @@ encodeLoop:
205
205
panic (fmt .Sprintf ("first match mismatch: %v != %v, first: %08x" , src [s :s + 4 ], src [offset :offset + 4 ], first ))
206
206
}
207
207
}
208
- cand := match {offset : offset , s : s , length : 4 + e .matchlen (s + 4 , offset + 4 , src ), rep : rep }
208
+ // Try to quick reject if we already have a long match.
209
+ if m .length > 16 {
210
+ left := len (src ) - int (m .s + m .length )
211
+ // If we are too close to the end, keep as is.
212
+ if left <= 0 {
213
+ return
214
+ }
215
+ if left > 2 {
216
+ // Check 4 bytes, 4 bytes from the end of the current match.
217
+ a := load3232 (src , offset + m .length - 8 )
218
+ b := load3232 (src , s + m .length - 8 )
219
+ if a != b {
220
+ return
221
+ }
222
+ }
223
+ }
224
+ l := 4 + e .matchlen (s + 4 , offset + 4 , src )
225
+ if rep < 0 {
226
+ // Extend candidate match backwards as far as possible.
227
+ tMin := s - e .maxMatchOff
228
+ if tMin < 0 {
229
+ tMin = 0
230
+ }
231
+ for offset > tMin && s > nextEmit && src [offset - 1 ] == src [s - 1 ] && l < maxMatchLength {
232
+ s --
233
+ offset --
234
+ l ++
235
+ }
236
+ }
237
+
238
+ cand := match {offset : offset , s : s , length : l , rep : rep }
209
239
cand .estBits (bitsPerByte )
210
240
if m .est >= highScore || cand .est - m .est + (cand .s - m .s )* bitsPerByte >> 10 < 0 {
211
241
* m = cand
@@ -219,17 +249,29 @@ encodeLoop:
219
249
improve (& best , candidateS .prev - e .cur , s , uint32 (cv ), - 1 )
220
250
221
251
if canRepeat && best .length < goodEnough {
222
- cv32 := uint32 (cv >> 8 )
223
- spp := s + 1
224
- improve (& best , spp - offset1 , spp , cv32 , 1 )
225
- improve (& best , spp - offset2 , spp , cv32 , 2 )
226
- improve (& best , spp - offset3 , spp , cv32 , 3 )
227
- if best .length > 0 {
228
- cv32 = uint32 (cv >> 24 )
229
- spp += 2
252
+ if s == nextEmit {
253
+ // Check repeats straight after a match.
254
+ improve (& best , s - offset2 , s , uint32 (cv ), 1 | 4 )
255
+ improve (& best , s - offset3 , s , uint32 (cv ), 2 | 4 )
256
+ if offset1 > 1 {
257
+ improve (& best , s - (offset1 - 1 ), s , uint32 (cv ), 3 | 4 )
258
+ }
259
+ }
260
+
261
+ // If either no match or a non-repeat match, check at + 1
262
+ if best .rep <= 0 {
263
+ cv32 := uint32 (cv >> 8 )
264
+ spp := s + 1
230
265
improve (& best , spp - offset1 , spp , cv32 , 1 )
231
266
improve (& best , spp - offset2 , spp , cv32 , 2 )
232
267
improve (& best , spp - offset3 , spp , cv32 , 3 )
268
+ if best .rep < 0 {
269
+ cv32 = uint32 (cv >> 24 )
270
+ spp += 2
271
+ improve (& best , spp - offset1 , spp , cv32 , 1 )
272
+ improve (& best , spp - offset2 , spp , cv32 , 2 )
273
+ improve (& best , spp - offset3 , spp , cv32 , 3 )
274
+ }
233
275
}
234
276
}
235
277
// Load next and check...
@@ -248,7 +290,7 @@ encodeLoop:
248
290
continue
249
291
}
250
292
251
- s ++
293
+ s := s + 1
252
294
candidateS = e .table [hashLen (cv >> 8 , bestShortTableBits , bestShortLen )]
253
295
cv = load6432 (src , s )
254
296
cv2 := load6432 (src , s + 1 )
@@ -292,38 +334,22 @@ encodeLoop:
292
334
293
335
// We have a match, we can store the forward value
294
336
if best .rep > 0 {
295
- s = best .s
296
337
var seq seq
297
338
seq .matchLen = uint32 (best .length - zstdMinMatch )
298
-
299
- // We might be able to match backwards.
300
- // Extend as long as we can.
301
- start := best .s
302
- // We end the search early, so we don't risk 0 literals
303
- // and have to do special offset treatment.
304
- startLimit := nextEmit + 1
305
-
306
- tMin := s - e .maxMatchOff
307
- if tMin < 0 {
308
- tMin = 0
309
- }
310
- repIndex := best .offset
311
- for repIndex > tMin && start > startLimit && src [repIndex - 1 ] == src [start - 1 ] && seq .matchLen < maxMatchLength - zstdMinMatch - 1 {
312
- repIndex --
313
- start --
314
- seq .matchLen ++
339
+ if debugAsserts && s <= nextEmit {
340
+ panic ("s <= nextEmit" )
315
341
}
316
- addLiterals (& seq , start )
342
+ addLiterals (& seq , best . s )
317
343
318
- // rep 0
319
- seq .offset = uint32 (best .rep )
344
+ // Repeat. If bit 4 is set, this is a non-lit repeat.
345
+ seq .offset = uint32 (best .rep & 3 )
320
346
if debugSequences {
321
347
println ("repeat sequence" , seq , "next s:" , s )
322
348
}
323
349
blk .sequences = append (blk .sequences , seq )
324
350
325
- // Index match start+1 (long) -> s - 1
326
- index0 := s
351
+ // Index old s + 1 -> s - 1
352
+ index0 := s + 1
327
353
s = best .s + best .length
328
354
329
355
nextEmit = s
@@ -336,7 +362,7 @@ encodeLoop:
336
362
}
337
363
// Index skipped...
338
364
off := index0 + e .cur
339
- for index0 < s - 1 {
365
+ for index0 < s {
340
366
cv0 := load6432 (src , index0 )
341
367
h0 := hashLen (cv0 , bestLongTableBits , bestLongLen )
342
368
h1 := hashLen (cv0 , bestShortTableBits , bestShortLen )
@@ -346,17 +372,20 @@ encodeLoop:
346
372
index0 ++
347
373
}
348
374
switch best .rep {
349
- case 2 :
375
+ case 2 , 4 | 1 :
350
376
offset1 , offset2 = offset2 , offset1
351
- case 3 :
377
+ case 3 , 4 | 2 :
352
378
offset1 , offset2 , offset3 = offset3 , offset1 , offset2
379
+ case 4 | 3 :
380
+ offset1 , offset2 , offset3 = offset1 - 1 , offset1 , offset2
353
381
}
354
382
cv = load6432 (src , s )
355
383
continue
356
384
}
357
385
358
386
// A 4-byte match has been found. Update recent offsets.
359
387
// We'll later see if more than 4 bytes.
388
+ index0 := s + 1
360
389
s = best .s
361
390
t := best .offset
362
391
offset1 , offset2 , offset3 = s - t , offset1 , offset2
@@ -369,22 +398,9 @@ encodeLoop:
369
398
panic ("invalid offset" )
370
399
}
371
400
372
- // Extend the n-byte match as long as possible.
373
- l := best .length
374
-
375
- // Extend backwards
376
- tMin := s - e .maxMatchOff
377
- if tMin < 0 {
378
- tMin = 0
379
- }
380
- for t > tMin && s > nextEmit && src [t - 1 ] == src [s - 1 ] && l < maxMatchLength {
381
- s --
382
- t --
383
- l ++
384
- }
385
-
386
401
// Write our sequence
387
402
var seq seq
403
+ l := best .length
388
404
seq .litLen = uint32 (s - nextEmit )
389
405
seq .matchLen = uint32 (l - zstdMinMatch )
390
406
if seq .litLen > 0 {
@@ -401,10 +417,8 @@ encodeLoop:
401
417
break encodeLoop
402
418
}
403
419
404
- // Index match start+1 (long) -> s - 1
405
- index0 := s - l + 1
406
- // every entry
407
- for index0 < s - 1 {
420
+ // Index old s + 1 -> s - 1
421
+ for index0 < s {
408
422
cv0 := load6432 (src , index0 )
409
423
h0 := hashLen (cv0 , bestLongTableBits , bestLongLen )
410
424
h1 := hashLen (cv0 , bestShortTableBits , bestShortLen )
@@ -413,50 +427,7 @@ encodeLoop:
413
427
e .table [h1 ] = prevEntry {offset : off , prev : e .table [h1 ].offset }
414
428
index0 ++
415
429
}
416
-
417
430
cv = load6432 (src , s )
418
- if ! canRepeat {
419
- continue
420
- }
421
-
422
- // Check offset 2
423
- for {
424
- o2 := s - offset2
425
- if load3232 (src , o2 ) != uint32 (cv ) {
426
- // Do regular search
427
- break
428
- }
429
-
430
- // Store this, since we have it.
431
- nextHashS := hashLen (cv , bestShortTableBits , bestShortLen )
432
- nextHashL := hashLen (cv , bestLongTableBits , bestLongLen )
433
-
434
- // We have at least 4 byte match.
435
- // No need to check backwards. We come straight from a match
436
- l := 4 + e .matchlen (s + 4 , o2 + 4 , src )
437
-
438
- e .longTable [nextHashL ] = prevEntry {offset : s + e .cur , prev : e .longTable [nextHashL ].offset }
439
- e .table [nextHashS ] = prevEntry {offset : s + e .cur , prev : e .table [nextHashS ].offset }
440
- seq .matchLen = uint32 (l ) - zstdMinMatch
441
- seq .litLen = 0
442
-
443
- // Since litlen is always 0, this is offset 1.
444
- seq .offset = 1
445
- s += l
446
- nextEmit = s
447
- if debugSequences {
448
- println ("sequence" , seq , "next s:" , s )
449
- }
450
- blk .sequences = append (blk .sequences , seq )
451
-
452
- // Swap offset 1 and 2.
453
- offset1 , offset2 = offset2 , offset1
454
- if s >= sLimit {
455
- // Finished
456
- break encodeLoop
457
- }
458
- cv = load6432 (src , s )
459
- }
460
431
}
461
432
462
433
if int (nextEmit ) < len (src ) {
0 commit comments