@@ -50,6 +50,8 @@ __wt_block_compact_end(WT_SESSION_IMPL *session, WT_BLOCK *block)
5050 block -> allocfirst = block -> allocfirst_save ;
5151 __wt_spin_unlock (session , & block -> live_lock );
5252
53+ block -> compact_pct_tenths = 0 ;
54+
5355 return (0 );
5456}
5557
@@ -64,7 +66,7 @@ __wt_block_compact_skip(WT_SESSION_IMPL *session, WT_BLOCK *block, int *skipp)
6466 WT_EXT * ext ;
6567 WT_EXTLIST * el ;
6668 WT_FH * fh ;
67- wt_off_t avail , ninety ;
69+ wt_off_t avail_eighty , avail_ninety , eighty , ninety ;
6870
6971 * skipp = 1 ; /* Return a default skip. */
7072
@@ -84,31 +86,53 @@ __wt_block_compact_skip(WT_SESSION_IMPL *session, WT_BLOCK *block, int *skipp)
8486 if (WT_VERBOSE_ISSET (session , WT_VERB_COMPACT ))
8587 WT_ERR (__block_dump_avail (session , block ));
8688
87- /* Sum the number of available bytes in the first 90% of the file. */
88- avail = 0 ;
89+ /* Sum the available bytes in the first 80% and 90% of the file. */
90+ avail_eighty = avail_ninety = 0 ;
8991 ninety = fh -> size - fh -> size / 10 ;
92+ eighty = fh -> size - ((fh -> size / 10 ) * 2 );
9093
9194 el = & block -> live .avail ;
9295 WT_EXT_FOREACH (ext , el -> off )
93- if (ext -> off < ninety )
94- avail += ext -> size ;
95-
96- /*
97- * If at least 10% of the total file is available and in the first 90%
98- * of the file, we'll try compaction.
99- */
100- if (avail >= fh -> size / 10 )
101- * skipp = 0 ;
96+ if (ext -> off < ninety ) {
97+ avail_ninety += ext -> size ;
98+ if (ext -> off < eighty )
99+ avail_eighty += ext -> size ;
100+ }
102101
103102 WT_ERR (__wt_verbose (session , WT_VERB_COMPACT ,
104103 "%s: %" PRIuMAX "MB (%" PRIuMAX ") available space in the first "
105- "90%% of the file, require 10%% or %" PRIuMAX "MB (%" PRIuMAX
106- ") to perform compaction, compaction %s" ,
104+ "80%% of the file" ,
105+ block -> name ,
106+ (uintmax_t )avail_eighty / WT_MEGABYTE , (uintmax_t )avail_eighty ));
107+ WT_ERR (__wt_verbose (session , WT_VERB_COMPACT ,
108+ "%s: %" PRIuMAX "MB (%" PRIuMAX ") available space in the first "
109+ "90%% of the file" ,
110+ block -> name ,
111+ (uintmax_t )avail_ninety / WT_MEGABYTE , (uintmax_t )avail_ninety ));
112+ WT_ERR (__wt_verbose (session , WT_VERB_COMPACT ,
113+ "%s: require 10%% or %" PRIuMAX "MB (%" PRIuMAX ") in the first "
114+ "90%% of the file to perform compaction, compaction %s" ,
107115 block -> name ,
108- (uintmax_t )avail / WT_MEGABYTE , (uintmax_t )avail ,
109116 (uintmax_t )(fh -> size / 10 ) / WT_MEGABYTE , (uintmax_t )fh -> size / 10 ,
110117 * skipp ? "skipped" : "proceeding" ));
111118
119+ /*
120+ * If at least 20% of the total file is available and in the first 80%
121+ * of the file, we'll try compaction on the last 20% of the file; else,
122+ * if at least 10% of the total file is available and in the first 90%
123+ * of the file, we'll try compaction on the last 10% of the file.
124+ *
125+ * We could push this further, but there's diminishing returns, a mostly
126+ * empty file can be processed quickly, so more aggressive compaction is
127+ * less useful.
128+ */
129+ if (avail_ninety >= fh -> size / 10 ) {
130+ * skipp = 0 ;
131+ block -> compact_pct_tenths = 1 ;
132+ if (avail_eighty >= ((fh -> size / 10 ) * 2 ))
133+ block -> compact_pct_tenths = 2 ;
134+ }
135+
112136err : __wt_spin_unlock (session , & block -> live_lock );
113137
114138 return (ret );
@@ -126,7 +150,7 @@ __wt_block_compact_page_skip(WT_SESSION_IMPL *session,
126150 WT_EXT * ext ;
127151 WT_EXTLIST * el ;
128152 WT_FH * fh ;
129- wt_off_t ninety , offset ;
153+ wt_off_t limit , offset ;
130154 uint32_t size , cksum ;
131155
132156 WT_UNUSED (addr_size );
@@ -138,21 +162,24 @@ __wt_block_compact_page_skip(WT_SESSION_IMPL *session,
138162 WT_RET (__wt_block_buffer_to_addr (block , addr , & offset , & size , & cksum ));
139163
140164 /*
141- * If this block is in the last 10% of the file and there's a block on
142- * the available list that's in the first 90% of the file, rewrite the
143- * block. Checking the available list is necessary (otherwise writing
144- * the block would extend the file), but there's an obvious race if the
145- * file is sufficiently busy.
165+ * If this block is in the chosen percentage of the file and there's a
166+ * block on the available list that's appears before that percentage of
167+ * the file, rewrite the block. Checking the available list is
168+ * necessary (otherwise writing the block would extend the file), but
169+ * there's an obvious race if the file is sufficiently busy.
146170 */
147171 __wt_spin_lock (session , & block -> live_lock );
148- ninety = fh -> size - fh -> size / 10 ;
149- if (offset > ninety ) {
172+ limit = fh -> size - (( fh -> size / 10 ) * block -> compact_pct_tenths ) ;
173+ if (offset > limit ) {
150174 el = & block -> live .avail ;
151- WT_EXT_FOREACH (ext , el -> off )
152- if (ext -> off < ninety && ext -> size >= size ) {
175+ WT_EXT_FOREACH (ext , el -> off ) {
176+ if (ext -> off >= limit )
177+ break ;
178+ if (ext -> size >= size ) {
153179 * skipp = 0 ;
154180 break ;
155181 }
182+ }
156183 }
157184 __wt_spin_unlock (session , & block -> live_lock );
158185
0 commit comments