@@ -431,65 +431,7 @@ func (pc *pickedCompaction) setupInputs(
431
431
// Grow the sstables in startLevel.level as long as it doesn't affect the number
432
432
// of sstables included from pc.outputLevel.level.
433
433
if pc .lcf != nil && startLevel .level == 0 && pc .outputLevel .level != 0 {
434
- // Call the L0-specific compaction extension method. Similar logic as
435
- // pc.grow. Additional L0 files are optionally added to the compaction at
436
- // this step. Note that the bounds passed in are not the bounds of the
437
- // compaction, but rather the smallest and largest internal keys that
438
- // the compaction cannot include from L0 without pulling in more Lbase
439
- // files. Consider this example:
440
- //
441
- // L0: c-d e+f g-h
442
- // Lbase: a-b e+f i-j
443
- // a b c d e f g h i j
444
- //
445
- // The e-f files have already been chosen in the compaction. As pulling
446
- // in more LBase files is undesirable, the logic below will pass in
447
- // smallest = b and largest = i to ExtendL0ForBaseCompactionTo, which
448
- // will expand the compaction to include c-d and g-h from L0. The
449
- // bounds passed in are exclusive; the compaction cannot be expanded
450
- // to include files that "touch" it.
451
- smallestBaseKey := base .InvalidInternalKey
452
- largestBaseKey := base .InvalidInternalKey
453
- if pc .outputLevel .files .Empty () {
454
- baseIter := pc .version .Levels [pc .outputLevel .level ].Iter ()
455
- if sm := baseIter .SeekLT (pc .cmp , pc .smallest .UserKey ); sm != nil {
456
- smallestBaseKey = sm .Largest ()
457
- }
458
- if la := baseIter .SeekGE (pc .cmp , pc .largest .UserKey ); la != nil {
459
- largestBaseKey = la .Smallest ()
460
- }
461
- } else {
462
- // NB: We use Reslice to access the underlying level's files, but
463
- // we discard the returned slice. The pc.outputLevel.files slice
464
- // is not modified.
465
- _ = pc .outputLevel .files .Reslice (func (start , end * manifest.LevelIterator ) {
466
- if sm := start .Prev (); sm != nil {
467
- smallestBaseKey = sm .Largest ()
468
- }
469
- if la := end .Next (); la != nil {
470
- largestBaseKey = la .Smallest ()
471
- }
472
- })
473
- }
474
- oldLcf := pc .lcf .Clone ()
475
- if pc .l0Organizer .ExtendL0ForBaseCompactionTo (smallestBaseKey , largestBaseKey , pc .lcf ) {
476
- var newStartLevelFiles []* manifest.TableMetadata
477
- iter := pc .version .Levels [0 ].Iter ()
478
- var sizeSum uint64
479
- for j , f := 0 , iter .First (); f != nil ; j , f = j + 1 , iter .Next () {
480
- if pc .lcf .FilesIncluded [f .L0Index ] {
481
- newStartLevelFiles = append (newStartLevelFiles , f )
482
- sizeSum += f .Size
483
- }
484
- }
485
- if sizeSum + pc .outputLevel .files .AggregateSizeSum () < maxExpandedBytes {
486
- startLevel .files = manifest .NewLevelSliceSeqSorted (newStartLevelFiles )
487
- pc .smallest , pc .largest = manifest .KeyRange (pc .cmp ,
488
- startLevel .files .All (), pc .outputLevel .files .All ())
489
- } else {
490
- * pc .lcf = * oldLcf
491
- }
492
- }
434
+ pc .growL0ForBase (maxExpandedBytes )
493
435
} else if pc .grow (pc .smallest , pc .largest , maxExpandedBytes , startLevel , problemSpans ) {
494
436
pc .maybeExpandBounds (manifest .KeyRange (pc .cmp ,
495
437
startLevel .files .All (), pc .outputLevel .files .All ()))
@@ -540,6 +482,78 @@ func (pc *pickedCompaction) grow(
540
482
return true
541
483
}
542
484
485
+ // Similar logic as pc.grow. Additional L0 files are optionally added to the
486
+ // compaction at this step. Note that the bounds passed in are not the bounds
487
+ // of the compaction, but rather the smallest and largest internal keys that
488
+ // the compaction cannot include from L0 without pulling in more Lbase
489
+ // files. Consider this example:
490
+ //
491
+ // L0: c-d e+f g-h
492
+ // Lbase: a-b e+f i-j
493
+ //
494
+ // a b c d e f g h i j
495
+ //
496
+ // The e-f files have already been chosen in the compaction. As pulling
497
+ // in more LBase files is undesirable, the logic below will pass in
498
+ // smallest = b and largest = i to ExtendL0ForBaseCompactionTo, which
499
+ // will expand the compaction to include c-d and g-h from L0. The
500
+ // bounds passed in are exclusive; the compaction cannot be expanded
501
+ // to include files that "touch" it.
502
+ func (pc * pickedCompaction ) growL0ForBase (maxExpandedBytes uint64 ) bool {
503
+ if invariants .Enabled {
504
+ if pc .startLevel .level != 0 {
505
+ panic (fmt .Sprintf ("pc.startLevel.level is %d, expected 0" , pc .startLevel .level ))
506
+ }
507
+ }
508
+ smallestBaseKey := base .InvalidInternalKey
509
+ largestBaseKey := base .InvalidInternalKey
510
+ if pc .outputLevel .files .Empty () {
511
+ baseIter := pc .version .Levels [pc .outputLevel .level ].Iter ()
512
+ if sm := baseIter .SeekLT (pc .cmp , pc .smallest .UserKey ); sm != nil {
513
+ smallestBaseKey = sm .Largest ()
514
+ }
515
+ if la := baseIter .SeekGE (pc .cmp , pc .largest .UserKey ); la != nil {
516
+ largestBaseKey = la .Smallest ()
517
+ }
518
+ } else {
519
+ // NB: We use Reslice to access the underlying level's files, but
520
+ // we discard the returned slice. The pc.outputLevel.files slice
521
+ // is not modified.
522
+ _ = pc .outputLevel .files .Reslice (func (start , end * manifest.LevelIterator ) {
523
+ if sm := start .Prev (); sm != nil {
524
+ smallestBaseKey = sm .Largest ()
525
+ }
526
+ if la := end .Next (); la != nil {
527
+ largestBaseKey = la .Smallest ()
528
+ }
529
+ })
530
+ }
531
+ oldLcf := pc .lcf .Clone ()
532
+ if ! pc .l0Organizer .ExtendL0ForBaseCompactionTo (smallestBaseKey , largestBaseKey , pc .lcf ) {
533
+ return false
534
+ }
535
+
536
+ var newStartLevelFiles []* manifest.TableMetadata
537
+ iter := pc .version .Levels [0 ].Iter ()
538
+ var sizeSum uint64
539
+ for j , f := 0 , iter .First (); f != nil ; j , f = j + 1 , iter .Next () {
540
+ if pc .lcf .FilesIncluded [f .L0Index ] {
541
+ newStartLevelFiles = append (newStartLevelFiles , f )
542
+ sizeSum += f .Size
543
+ }
544
+ }
545
+
546
+ if sizeSum + pc .outputLevel .files .AggregateSizeSum () >= maxExpandedBytes {
547
+ * pc .lcf = * oldLcf
548
+ return false
549
+ }
550
+
551
+ pc .startLevel .files = manifest .NewLevelSliceSeqSorted (newStartLevelFiles )
552
+ pc .smallest , pc .largest = manifest .KeyRange (pc .cmp ,
553
+ pc .startLevel .files .All (), pc .outputLevel .files .All ())
554
+ return true
555
+ }
556
+
543
557
// estimatedInputSize returns an estimate of the size of the compaction's
544
558
// inputs, including the estimated physical size of input tables' blob
545
559
// references.
@@ -1714,7 +1728,7 @@ func pickAutoLPositive(
1714
1728
func (pc * pickedCompaction ) maybeAddLevel (opts * Options , diskAvailBytes uint64 ) * pickedCompaction {
1715
1729
pc .pickerMetrics .singleLevelOverlappingRatio = pc .overlappingRatio ()
1716
1730
if pc .outputLevel .level == numLevels - 1 {
1717
- // Don't add a level if the current output level is in L6
1731
+ // Don't add a level if the current output level is in L6.
1718
1732
return pc
1719
1733
}
1720
1734
if ! opts .Experimental .MultiLevelCompactionHeuristic .allowL0 () && pc .startLevel .level == 0 {
0 commit comments