From 7d221214bbb9943710ce4f9b5c86d7bc941cf978 Mon Sep 17 00:00:00 2001 From: "Alex Chi Z." <4198311+skyzh@users.noreply.github.com> Date: Tue, 11 Mar 2025 15:13:52 -0400 Subject: [PATCH] feat(pageserver): support no-yield for gc-compaction (#11184) ## Problem This should also resolve the test flakiness of `test_gc_feedback`. close https://github.com/neondatabase/neon/issues/11144 ## Summary of changes If `NoYield` is set, do not yield in gc-compaction. --------- Signed-off-by: Alex Chi Z --- pageserver/src/tenant/timeline/compaction.rs | 55 +++++++++++++------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/pageserver/src/tenant/timeline/compaction.rs b/pageserver/src/tenant/timeline/compaction.rs index 123079804b..e6f2104e90 100644 --- a/pageserver/src/tenant/timeline/compaction.rs +++ b/pageserver/src/tenant/timeline/compaction.rs @@ -393,6 +393,9 @@ impl GcCompactionQueue { if job.dry_run { flags |= CompactFlags::DryRun; } + if options.flags.contains(CompactFlags::NoYield) { + flags |= CompactFlags::NoYield; + } let options = CompactOptions { flags, sub_compaction: false, @@ -2617,6 +2620,7 @@ impl Timeline { ) -> Result { let sub_compaction = options.sub_compaction; let job = GcCompactJob::from_compact_options(options.clone()); + let no_yield = options.flags.contains(CompactFlags::NoYield); if sub_compaction { info!( "running enhanced gc bottom-most compaction with sub-compaction, splitting compaction jobs" @@ -2631,14 +2635,15 @@ impl Timeline { idx + 1, jobs_len ); - self.compact_with_gc_inner(cancel, job, ctx).await?; + self.compact_with_gc_inner(cancel, job, ctx, no_yield) + .await?; } if jobs_len == 0 { info!("no jobs to run, skipping gc bottom-most compaction"); } return Ok(CompactionOutcome::Done); } - self.compact_with_gc_inner(cancel, job, ctx).await + self.compact_with_gc_inner(cancel, job, ctx, no_yield).await } async fn compact_with_gc_inner( @@ -2646,6 +2651,7 @@ impl Timeline { cancel: &CancellationToken, job: GcCompactJob, ctx: &RequestContext, + no_yield: bool, ) -> Result { // Block other compaction/GC tasks from running for now. GC-compaction could run along // with legacy compaction tasks in the future. Always ensure the lock order is compaction -> gc. @@ -2915,14 +2921,18 @@ impl Timeline { if cancel.is_cancelled() { return Err(CompactionError::ShuttingDown); } - let should_yield = self - .l0_compaction_trigger - .notified() - .now_or_never() - .is_some(); - if should_yield { - tracing::info!("preempt gc-compaction when downloading layers: too many L0 layers"); - return Ok(CompactionOutcome::YieldForL0); + if !no_yield { + let should_yield = self + .l0_compaction_trigger + .notified() + .now_or_never() + .is_some(); + if should_yield { + tracing::info!( + "preempt gc-compaction when downloading layers: too many L0 layers" + ); + return Ok(CompactionOutcome::YieldForL0); + } } let resident_layer = layer .download_and_keep_resident(ctx) @@ -3055,16 +3065,21 @@ impl Timeline { if cancel.is_cancelled() { return Err(CompactionError::ShuttingDown); } - keys_processed += 1; - if keys_processed % 1000 == 0 { - let should_yield = self - .l0_compaction_trigger - .notified() - .now_or_never() - .is_some(); - if should_yield { - tracing::info!("preempt gc-compaction in the main loop: too many L0 layers"); - return Ok(CompactionOutcome::YieldForL0); + + if !no_yield { + keys_processed += 1; + if keys_processed % 1000 == 0 { + let should_yield = self + .l0_compaction_trigger + .notified() + .now_or_never() + .is_some(); + if should_yield { + tracing::info!( + "preempt gc-compaction in the main loop: too many L0 layers" + ); + return Ok(CompactionOutcome::YieldForL0); + } } } if self.shard_identity.is_key_disposable(&key) {