@ -162,7 +162,13 @@ bool UniversalCompactionPicker::IsInputFilesNonOverlapping(Compaction* c) {
bool UniversalCompactionPicker : : NeedsCompaction (
const VersionStorageInfo * vstorage ) const {
const int kLevel0 = 0 ;
return vstorage - > CompactionScore ( kLevel0 ) > = 1 ;
if ( vstorage - > CompactionScore ( kLevel0 ) > = 1 ) {
return true ;
}
if ( ! vstorage - > FilesMarkedForCompaction ( ) . empty ( ) ) {
return true ;
}
return false ;
}
void UniversalCompactionPicker : : SortedRun : : Dump ( char * out_buf ,
@ -257,8 +263,9 @@ Compaction* UniversalCompactionPicker::PickCompaction(
CalculateSortedRuns ( * vstorage , ioptions_ , mutable_cf_options ) ;
if ( sorted_runs . size ( ) = = 0 | |
sorted_runs . size ( ) <
( unsigned int ) mutable_cf_options . level0_file_num_compaction_trigger ) {
( vstorage - > FilesMarkedForCompaction ( ) . empty ( ) & &
sorted_runs . size ( ) < ( unsigned int ) mutable_cf_options
. level0_file_num_compaction_trigger ) ) {
ROCKS_LOG_BUFFER ( log_buffer , " [%s] Universal: nothing to do \n " ,
cf_name . c_str ( ) ) ;
TEST_SYNC_POINT_CALLBACK ( " UniversalCompactionPicker::PickCompaction:Return " ,
@ -272,58 +279,73 @@ Compaction* UniversalCompactionPicker::PickCompaction(
cf_name . c_str ( ) , sorted_runs . size ( ) , vstorage - > LevelSummary ( & tmp ) ) ;
// Check for size amplification first.
Compaction * c ;
if ( ( c = PickCompactionToReduceSizeAmp ( cf_name , mutable_cf_options , vstorage ,
score , sorted_runs , log_buffer ) ) ! =
nullptr ) {
ROCKS_LOG_BUFFER ( log_buffer , " [%s] Universal: compacting for size amp \n " ,
cf_name . c_str ( ) ) ;
} else {
// Size amplification is within limits. Try reducing read
// amplification while maintaining file size ratios.
unsigned int ratio =
mutable_cf_options . compaction_options_universal . size_ratio ;
if ( ( c = PickCompactionToReduceSortedRuns (
cf_name , mutable_cf_options , vstorage , score , ratio , UINT_MAX ,
sorted_runs , log_buffer ) ) ! = nullptr ) {
ROCKS_LOG_BUFFER ( log_buffer ,
" [%s] Universal: compacting for size ratio \n " ,
Compaction * c = nullptr ;
if ( sorted_runs . size ( ) > =
static_cast < size_t > (
mutable_cf_options . level0_file_num_compaction_trigger ) ) {
if ( ( c = PickCompactionToReduceSizeAmp ( cf_name , mutable_cf_options ,
vstorage , score , sorted_runs ,
log_buffer ) ) ! = nullptr ) {
ROCKS_LOG_BUFFER ( log_buffer , " [%s] Universal: compacting for size amp \n " ,
cf_name . c_str ( ) ) ;
} else {
// Size amplification and file size ratios are within configured limits.
// If max read amplification is exceeding configured limits, then force
// compaction without looking at filesize ratios and try to reduce
// the number of files to fewer than level0_file_num_compaction_trigger.
// This is guaranteed by NeedsCompaction()
assert ( sorted_runs . size ( ) > =
static_cast < size_t > (
mutable_cf_options . level0_file_num_compaction_trigger ) ) ;
// Get the total number of sorted runs that are not being compacted
int num_sr_not_compacted = 0 ;
for ( size_t i = 0 ; i < sorted_runs . size ( ) ; i + + ) {
if ( sorted_runs [ i ] . being_compacted = = false ) {
num_sr_not_compacted + + ;
// Size amplification is within limits. Try reducing read
// amplification while maintaining file size ratios.
unsigned int ratio =
mutable_cf_options . compaction_options_universal . size_ratio ;
if ( ( c = PickCompactionToReduceSortedRuns (
cf_name , mutable_cf_options , vstorage , score , ratio , UINT_MAX ,
sorted_runs , log_buffer ) ) ! = nullptr ) {
ROCKS_LOG_BUFFER ( log_buffer ,
" [%s] Universal: compacting for size ratio \n " ,
cf_name . c_str ( ) ) ;
} else {
// Size amplification and file size ratios are within configured limits.
// If max read amplification is exceeding configured limits, then force
// compaction without looking at filesize ratios and try to reduce
// the number of files to fewer than level0_file_num_compaction_trigger.
// This is guaranteed by NeedsCompaction()
assert ( sorted_runs . size ( ) > =
static_cast < size_t > (
mutable_cf_options . level0_file_num_compaction_trigger ) ) ;
// Get the total number of sorted runs that are not being compacted
int num_sr_not_compacted = 0 ;
for ( size_t i = 0 ; i < sorted_runs . size ( ) ; i + + ) {
if ( sorted_runs [ i ] . being_compacted = = false ) {
num_sr_not_compacted + + ;
}
}
}
// The number of sorted runs that are not being compacted is greater than
// the maximum allowed number of sorted runs
if ( num_sr_not_compacted >
mutable_cf_options . level0_file_num_compaction_trigger ) {
unsigned int num_files =
num_sr_not_compacted -
mutable_cf_options . level0_file_num_compaction_trigger + 1 ;
if ( ( c = PickCompactionToReduceSortedRuns (
cf_name , mutable_cf_options , vstorage , score , UINT_MAX ,
num_files , sorted_runs , log_buffer ) ) ! = nullptr ) {
ROCKS_LOG_BUFFER ( log_buffer ,
" [%s] Universal: compacting for file num -- %u \n " ,
cf_name . c_str ( ) , num_files ) ;
// The number of sorted runs that are not being compacted is greater
// than the maximum allowed number of sorted runs
if ( num_sr_not_compacted >
mutable_cf_options . level0_file_num_compaction_trigger ) {
unsigned int num_files =
num_sr_not_compacted -
mutable_cf_options . level0_file_num_compaction_trigger + 1 ;
if ( ( c = PickCompactionToReduceSortedRuns (
cf_name , mutable_cf_options , vstorage , score , UINT_MAX ,
num_files , sorted_runs , log_buffer ) ) ! = nullptr ) {
ROCKS_LOG_BUFFER ( log_buffer ,
" [%s] Universal: compacting for file num -- %u \n " ,
cf_name . c_str ( ) , num_files ) ;
}
}
}
}
}
if ( c = = nullptr ) {
if ( ( c = PickDeleteTriggeredCompaction ( cf_name , mutable_cf_options ,
vstorage , score , sorted_runs ,
log_buffer ) ) ! = nullptr ) {
ROCKS_LOG_BUFFER ( log_buffer ,
" [%s] Universal: delete triggered compaction \n " ,
cf_name . c_str ( ) ) ;
}
}
if ( c = = nullptr ) {
TEST_SYNC_POINT_CALLBACK ( " UniversalCompactionPicker::PickCompaction:Return " ,
nullptr ) ;
@ -753,6 +775,125 @@ Compaction* UniversalCompactionPicker::PickCompactionToReduceSizeAmp(
score , false /* deletion_compaction */ ,
CompactionReason : : kUniversalSizeAmplification ) ;
}
// Pick files marked for compaction. Typically, files are marked by
// CompactOnDeleteCollector due to the presence of tombstones.
Compaction * UniversalCompactionPicker : : PickDeleteTriggeredCompaction (
const std : : string & cf_name , const MutableCFOptions & mutable_cf_options ,
VersionStorageInfo * vstorage , double score ,
const std : : vector < SortedRun > & /*sorted_runs*/ , LogBuffer * /*log_buffer*/ ) {
CompactionInputFiles start_level_inputs ;
int output_level ;
std : : vector < CompactionInputFiles > inputs ;
if ( vstorage - > num_levels ( ) = = 1 ) {
// This is single level universal. Since we're basically trying to reclaim
// space by processing files marked for compaction due to high tombstone
// density, let's do the same thing as compaction to reduce size amp which
// has the same goals.
bool compact = false ;
start_level_inputs . level = 0 ;
start_level_inputs . files . clear ( ) ;
output_level = 0 ;
for ( FileMetaData * f : vstorage - > LevelFiles ( 0 ) ) {
if ( f - > marked_for_compaction ) {
compact = true ;
}
if ( compact ) {
start_level_inputs . files . push_back ( f ) ;
}
}
if ( start_level_inputs . size ( ) < = 1 ) {
// If only the last file in L0 is marked for compaction, ignore it
return nullptr ;
}
inputs . push_back ( start_level_inputs ) ;
} else {
int start_level ;
// For multi-level universal, the strategy is to make this look more like
// leveled. We pick one of the files marked for compaction and compact with
// overlapping files in the adjacent level.
PickFilesMarkedForCompaction ( cf_name , vstorage , & start_level , & output_level ,
& start_level_inputs ) ;
if ( start_level_inputs . empty ( ) ) {
return nullptr ;
}
// Pick the first non-empty level after the start_level
for ( output_level = start_level + 1 ; output_level < vstorage - > num_levels ( ) ;
output_level + + ) {
if ( vstorage - > NumLevelFiles ( output_level ) ! = 0 ) {
break ;
}
}
// If all higher levels are empty, pick the highest level as output level
if ( output_level = = vstorage - > num_levels ( ) ) {
if ( start_level = = 0 ) {
output_level = vstorage - > num_levels ( ) - 1 ;
} else {
// If start level is non-zero and all higher levels are empty, this
// compaction will translate into a trivial move. Since the idea is
// to reclaim space and trivial move doesn't help with that, we
// skip compaction in this case and return nullptr
return nullptr ;
}
}
if ( ioptions_ . allow_ingest_behind & &
output_level = = vstorage - > num_levels ( ) - 1 ) {
assert ( output_level > 1 ) ;
output_level - - ;
}
if ( output_level ! = 0 ) {
if ( start_level = = 0 ) {
if ( ! GetOverlappingL0Files ( vstorage , & start_level_inputs , output_level ,
nullptr ) ) {
return nullptr ;
}
}
CompactionInputFiles output_level_inputs ;
int parent_index = - 1 ;
output_level_inputs . level = output_level ;
if ( ! SetupOtherInputs ( cf_name , mutable_cf_options , vstorage ,
& start_level_inputs , & output_level_inputs ,
& parent_index , - 1 ) ) {
return nullptr ;
}
inputs . push_back ( start_level_inputs ) ;
if ( ! output_level_inputs . empty ( ) ) {
inputs . push_back ( output_level_inputs ) ;
}
if ( FilesRangeOverlapWithCompaction ( inputs , output_level ) ) {
return nullptr ;
}
} else {
inputs . push_back ( start_level_inputs ) ;
}
}
uint64_t estimated_total_size = 0 ;
// Use size of the output level as estimated file size
for ( FileMetaData * f : vstorage - > LevelFiles ( output_level ) ) {
estimated_total_size + = f - > fd . GetFileSize ( ) ;
}
uint32_t path_id =
GetPathId ( ioptions_ , mutable_cf_options , estimated_total_size ) ;
return new Compaction (
vstorage , ioptions_ , mutable_cf_options , std : : move ( inputs ) , output_level ,
MaxFileSizeForLevel ( mutable_cf_options , output_level ,
kCompactionStyleUniversal ) ,
/* max_grandparent_overlap_bytes */ LLONG_MAX , path_id ,
GetCompressionType ( ioptions_ , vstorage , mutable_cf_options , output_level ,
1 ) ,
/* max_subcompactions */ 0 , /* grandparents */ { } , /* is manual */ true ,
score , false /* deletion_compaction */ ,
CompactionReason : : kFilesMarkedForCompaction ) ;
}
} // namespace rocksdb
# endif // !ROCKSDB_LITE