20260504 优化phase2 finalize调度长尾

This commit is contained in:
yuyr 2026-05-06 12:05:02 +08:00
parent b3b44d50c6
commit f843eedda9
5 changed files with 946 additions and 307 deletions

View File

@ -156,6 +156,16 @@ Options:
Phase 2 per-worker object queue capacity (default: 256) Phase 2 per-worker object queue capacity (default: 256)
--parallel-phase2-ready-batch-size <n> --parallel-phase2-ready-batch-size <n>
Phase 2 ready publication points processed per scheduler turn (default: 256) Phase 2 ready publication points processed per scheduler turn (default: 256)
--parallel-phase2-ready-batch-wall-time-budget-ms <n>
Phase 2 ready staging wall-time budget per scheduler turn (default: 100)
--parallel-phase2-result-drain-batch-size <n>
Phase 2 object results drained per scheduler turn (default: 2048)
--parallel-phase2-finalize-batch-size <n>
Legacy Phase 2 scheduler finalize budget; dedicated finalize worker ignores it (default: 256)
--parallel-phase2-finalize-batch-wall-time-budget-ms <n>
Legacy Phase 2 scheduler finalize time budget; dedicated finalize worker ignores it (default: 100)
--parallel-phase2-finalize-queue-capacity <n>
Phase 2 dedicated finalize worker queue capacity (default: 32768)
--rsync-local-dir <path> Use LocalDirRsyncFetcher rooted at this directory (offline tests) --rsync-local-dir <path> Use LocalDirRsyncFetcher rooted at this directory (offline tests)
--disable-rrdp Disable RRDP and synchronize only via rsync --disable-rrdp Disable RRDP and synchronize only via rsync
@ -293,6 +303,55 @@ pub fn parse_args(argv: &[String]) -> Result<CliArgs, String> {
.parse::<usize>() .parse::<usize>()
.map_err(|_| format!("invalid --parallel-phase2-ready-batch-size: {v}"))?; .map_err(|_| format!("invalid --parallel-phase2-ready-batch-size: {v}"))?;
} }
"--parallel-phase2-ready-batch-wall-time-budget-ms" => {
i += 1;
let v = argv
.get(i)
.ok_or("--parallel-phase2-ready-batch-wall-time-budget-ms requires a value")?;
parallel_phase2_cfg.ready_batch_wall_time_budget_ms =
v.parse::<u64>().map_err(|_| {
format!("invalid --parallel-phase2-ready-batch-wall-time-budget-ms: {v}")
})?;
}
"--parallel-phase2-result-drain-batch-size" => {
i += 1;
let v = argv
.get(i)
.ok_or("--parallel-phase2-result-drain-batch-size requires a value")?;
parallel_phase2_cfg.object_result_drain_batch_size =
v.parse::<usize>().map_err(|_| {
format!("invalid --parallel-phase2-result-drain-batch-size: {v}")
})?;
}
"--parallel-phase2-finalize-batch-size" => {
i += 1;
let v = argv
.get(i)
.ok_or("--parallel-phase2-finalize-batch-size requires a value")?;
parallel_phase2_cfg.publication_point_finalize_batch_size = v
.parse::<usize>()
.map_err(|_| format!("invalid --parallel-phase2-finalize-batch-size: {v}"))?;
}
"--parallel-phase2-finalize-batch-wall-time-budget-ms" => {
i += 1;
let v = argv.get(i).ok_or(
"--parallel-phase2-finalize-batch-wall-time-budget-ms requires a value",
)?;
parallel_phase2_cfg.publication_point_finalize_wall_time_budget_ms =
v.parse::<u64>().map_err(|_| {
format!("invalid --parallel-phase2-finalize-batch-wall-time-budget-ms: {v}")
})?;
}
"--parallel-phase2-finalize-queue-capacity" => {
i += 1;
let v = argv
.get(i)
.ok_or("--parallel-phase2-finalize-queue-capacity requires a value")?;
parallel_phase2_cfg.publication_point_finalize_queue_capacity =
v.parse::<usize>().map_err(|_| {
format!("invalid --parallel-phase2-finalize-queue-capacity: {v}")
})?;
}
"--db" => { "--db" => {
i += 1; i += 1;
let v = argv.get(i).ok_or("--db requires a value")?; let v = argv.get(i).ok_or("--db requires a value")?;
@ -513,6 +572,36 @@ pub fn parse_args(argv: &[String]) -> Result<CliArgs, String> {
usage() usage()
)); ));
} }
if parallel_phase2_cfg.ready_batch_wall_time_budget_ms == 0 {
return Err(format!(
"--parallel-phase2-ready-batch-wall-time-budget-ms must be > 0\n\n{}",
usage()
));
}
if parallel_phase2_cfg.object_result_drain_batch_size == 0 {
return Err(format!(
"--parallel-phase2-result-drain-batch-size must be > 0\n\n{}",
usage()
));
}
if parallel_phase2_cfg.publication_point_finalize_batch_size == 0 {
return Err(format!(
"--parallel-phase2-finalize-batch-size must be > 0\n\n{}",
usage()
));
}
if parallel_phase2_cfg.publication_point_finalize_wall_time_budget_ms == 0 {
return Err(format!(
"--parallel-phase2-finalize-batch-wall-time-budget-ms must be > 0\n\n{}",
usage()
));
}
if parallel_phase2_cfg.publication_point_finalize_queue_capacity == 0 {
return Err(format!(
"--parallel-phase2-finalize-queue-capacity must be > 0\n\n{}",
usage()
));
}
if !tal_urls.is_empty() && !ta_paths.is_empty() { if !tal_urls.is_empty() && !ta_paths.is_empty() {
return Err(format!( return Err(format!(
"--ta-path cannot be used with --tal-url mode\n\n{}", "--ta-path cannot be used with --tal-url mode\n\n{}",
@ -2191,11 +2280,44 @@ mod tests {
"17".to_string(), "17".to_string(),
"--parallel-phase2-ready-batch-size".to_string(), "--parallel-phase2-ready-batch-size".to_string(),
"31".to_string(), "31".to_string(),
"--parallel-phase2-ready-batch-wall-time-budget-ms".to_string(),
"43".to_string(),
"--parallel-phase2-result-drain-batch-size".to_string(),
"37".to_string(),
"--parallel-phase2-finalize-batch-size".to_string(),
"41".to_string(),
"--parallel-phase2-finalize-batch-wall-time-budget-ms".to_string(),
"47".to_string(),
"--parallel-phase2-finalize-queue-capacity".to_string(),
"8192".to_string(),
]; ];
let args = parse_args(&argv).expect("parse args"); let args = parse_args(&argv).expect("parse args");
assert_eq!(args.parallel_phase2_config.object_workers, 3); assert_eq!(args.parallel_phase2_config.object_workers, 3);
assert_eq!(args.parallel_phase2_config.worker_queue_capacity, 17); assert_eq!(args.parallel_phase2_config.worker_queue_capacity, 17);
assert_eq!(args.parallel_phase2_config.ready_batch_size, 31); assert_eq!(args.parallel_phase2_config.ready_batch_size, 31);
assert_eq!(
args.parallel_phase2_config.ready_batch_wall_time_budget_ms,
43
);
assert_eq!(
args.parallel_phase2_config.object_result_drain_batch_size,
37
);
assert_eq!(
args.parallel_phase2_config
.publication_point_finalize_batch_size,
41
);
assert_eq!(
args.parallel_phase2_config
.publication_point_finalize_wall_time_budget_ms,
47
);
assert_eq!(
args.parallel_phase2_config
.publication_point_finalize_queue_capacity,
8192
);
assert_eq!(args.parallel_phase1_config, ParallelPhase1Config::default()); assert_eq!(args.parallel_phase1_config, ParallelPhase1Config::default());
} }
@ -2214,6 +2336,96 @@ mod tests {
assert!(err.contains("--parallel-phase2-ready-batch-size"), "{err}"); assert!(err.contains("--parallel-phase2-ready-batch-size"), "{err}");
} }
#[test]
fn parse_rejects_zero_phase2_result_drain_batch_size() {
let argv = vec![
"rpki".to_string(),
"--db".to_string(),
"db".to_string(),
"--tal-url".to_string(),
"https://example.test/root.tal".to_string(),
"--parallel-phase2-result-drain-batch-size".to_string(),
"0".to_string(),
];
let err = parse_args(&argv).expect_err("zero result drain batch must fail");
assert!(
err.contains("--parallel-phase2-result-drain-batch-size"),
"{err}"
);
}
#[test]
fn parse_rejects_zero_phase2_ready_batch_wall_time_budget_ms() {
let argv = vec![
"rpki".to_string(),
"--db".to_string(),
"db".to_string(),
"--tal-url".to_string(),
"https://example.test/root.tal".to_string(),
"--parallel-phase2-ready-batch-wall-time-budget-ms".to_string(),
"0".to_string(),
];
let err = parse_args(&argv).expect_err("zero ready time budget must fail");
assert!(
err.contains("--parallel-phase2-ready-batch-wall-time-budget-ms"),
"{err}"
);
}
#[test]
fn parse_rejects_zero_phase2_finalize_batch_size() {
let argv = vec![
"rpki".to_string(),
"--db".to_string(),
"db".to_string(),
"--tal-url".to_string(),
"https://example.test/root.tal".to_string(),
"--parallel-phase2-finalize-batch-size".to_string(),
"0".to_string(),
];
let err = parse_args(&argv).expect_err("zero finalize batch must fail");
assert!(
err.contains("--parallel-phase2-finalize-batch-size"),
"{err}"
);
}
#[test]
fn parse_rejects_zero_phase2_finalize_batch_wall_time_budget_ms() {
let argv = vec![
"rpki".to_string(),
"--db".to_string(),
"db".to_string(),
"--tal-url".to_string(),
"https://example.test/root.tal".to_string(),
"--parallel-phase2-finalize-batch-wall-time-budget-ms".to_string(),
"0".to_string(),
];
let err = parse_args(&argv).expect_err("zero finalize time budget must fail");
assert!(
err.contains("--parallel-phase2-finalize-batch-wall-time-budget-ms"),
"{err}"
);
}
#[test]
fn parse_rejects_zero_phase2_finalize_queue_capacity() {
let argv = vec![
"rpki".to_string(),
"--db".to_string(),
"db".to_string(),
"--tal-url".to_string(),
"https://example.test/root.tal".to_string(),
"--parallel-phase2-finalize-queue-capacity".to_string(),
"0".to_string(),
];
let err = parse_args(&argv).expect_err("zero finalize queue capacity must fail");
assert!(
err.contains("--parallel-phase2-finalize-queue-capacity"),
"{err}"
);
}
#[test] #[test]
fn parse_rejects_removed_parallel_enable_flags() { fn parse_rejects_removed_parallel_enable_flags() {
let argv = vec![ let argv = vec![

View File

@ -10,6 +10,11 @@ pub struct ParallelPhase2Config {
pub object_workers: usize, pub object_workers: usize,
pub worker_queue_capacity: usize, pub worker_queue_capacity: usize,
pub ready_batch_size: usize, pub ready_batch_size: usize,
pub ready_batch_wall_time_budget_ms: u64,
pub object_result_drain_batch_size: usize,
pub publication_point_finalize_batch_size: usize,
pub publication_point_finalize_wall_time_budget_ms: u64,
pub publication_point_finalize_queue_capacity: usize,
} }
impl Default for ParallelPhase2Config { impl Default for ParallelPhase2Config {
@ -18,6 +23,11 @@ impl Default for ParallelPhase2Config {
object_workers: 8, object_workers: 8,
worker_queue_capacity: 256, worker_queue_capacity: 256,
ready_batch_size: 256, ready_batch_size: 256,
ready_batch_wall_time_budget_ms: 100,
object_result_drain_batch_size: 2048,
publication_point_finalize_batch_size: 256,
publication_point_finalize_wall_time_budget_ms: 100,
publication_point_finalize_queue_capacity: 32768,
} }
} }
} }
@ -50,5 +60,10 @@ mod tests {
assert!(cfg.object_workers > 0); assert!(cfg.object_workers > 0);
assert!(cfg.worker_queue_capacity > 0); assert!(cfg.worker_queue_capacity > 0);
assert!(cfg.ready_batch_size > 0); assert!(cfg.ready_batch_size > 0);
assert!(cfg.ready_batch_wall_time_budget_ms > 0);
assert!(cfg.object_result_drain_batch_size > 0);
assert!(cfg.publication_point_finalize_batch_size > 0);
assert!(cfg.publication_point_finalize_wall_time_budget_ms > 0);
assert!(cfg.publication_point_finalize_queue_capacity > 0);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -192,6 +192,7 @@ fn parallel_roa_processing_matches_serial_for_real_cernet_fixture() {
&ParallelPhase2Config { &ParallelPhase2Config {
object_workers: 2, object_workers: 2,
worker_queue_capacity: 4, worker_queue_capacity: 4,
..ParallelPhase2Config::default()
}, },
); );
@ -238,6 +239,7 @@ fn parallel_roa_processing_reports_issuer_decode_failure_like_serial() {
&ParallelPhase2Config { &ParallelPhase2Config {
object_workers: 2, object_workers: 2,
worker_queue_capacity: 4, worker_queue_capacity: 4,
..ParallelPhase2Config::default()
}, },
); );
@ -287,6 +289,7 @@ fn parallel_roa_processing_reports_missing_crl_like_serial() {
&ParallelPhase2Config { &ParallelPhase2Config {
object_workers: 2, object_workers: 2,
worker_queue_capacity: 4, worker_queue_capacity: 4,
..ParallelPhase2Config::default()
}, },
); );

View File

@ -559,6 +559,7 @@ fn parallel_roa_processing_drop_object_records_roa_and_aspa_errors_like_serial()
let phase2_config = ParallelPhase2Config { let phase2_config = ParallelPhase2Config {
object_workers: 2, object_workers: 2,
worker_queue_capacity: 1, worker_queue_capacity: 1,
..ParallelPhase2Config::default()
}; };
let pool = ParallelRoaWorkerPool::new(&phase2_config).expect("parallel roa pool"); let pool = ParallelRoaWorkerPool::new(&phase2_config).expect("parallel roa pool");
let parallel = process_publication_point_for_issuer_parallel_roa_with_pool( let parallel = process_publication_point_for_issuer_parallel_roa_with_pool(
@ -637,6 +638,7 @@ fn parallel_roa_processing_falls_back_for_drop_publication_point_policy() {
&ParallelPhase2Config { &ParallelPhase2Config {
object_workers: 2, object_workers: 2,
worker_queue_capacity: 1, worker_queue_capacity: 1,
..ParallelPhase2Config::default()
}, },
); );
@ -689,6 +691,7 @@ fn parallel_roa_processing_falls_back_for_single_worker_config() {
&ParallelPhase2Config { &ParallelPhase2Config {
object_workers: 1, object_workers: 1,
worker_queue_capacity: 1, worker_queue_capacity: 1,
..ParallelPhase2Config::default()
}, },
); );
@ -740,6 +743,7 @@ fn parallel_roa_processing_falls_back_when_pool_creation_fails() {
&ParallelPhase2Config { &ParallelPhase2Config {
object_workers: 2, object_workers: 2,
worker_queue_capacity: 0, worker_queue_capacity: 0,
..ParallelPhase2Config::default()
}, },
); );