@@ -10,9 +10,8 @@ use std::{
10
10
} ;
11
11
12
12
use crate :: {
13
- BlockIO , BlockOp , BlockOpWaiter , BlockRes , Buffer , JobId , RawReadResponse ,
14
- ReplaceResult , UpstairsAction , IO_OUTSTANDING_MAX_BYTES ,
15
- IO_OUTSTANDING_MAX_JOBS ,
13
+ backpressure:: BackpressureConfig , BlockIO , BlockOp , BlockOpWaiter ,
14
+ BlockRes , Buffer , JobId , RawReadResponse , ReplaceResult , UpstairsAction ,
16
15
} ;
17
16
use crucible_common:: { build_logger, Block , BlockIndex , CrucibleError } ;
18
17
use crucible_protocol:: SnapshotDetails ;
@@ -297,71 +296,6 @@ pub struct Guest {
297
296
log : Logger ,
298
297
}
299
298
300
- /// Configuration for host-side backpressure
301
- ///
302
- /// Backpressure adds an artificial delay to host write messages (which are
303
- /// otherwise acked immediately, before actually being complete). The delay is
304
- /// varied based on two metrics:
305
- ///
306
- /// - number of write bytes outstanding (as a fraction of max)
307
- /// - queue length as a fraction (where 1.0 is full)
308
- ///
309
- /// These two metrics are used for quadratic backpressure, picking the larger of
310
- /// the two delays.
311
- #[ derive( Copy , Clone , Debug ) ]
312
- struct BackpressureConfig {
313
- /// When should backpressure start, in units of bytes
314
- bytes_start : u64 ,
315
- /// Maximum number of bytes (i.e. backpressure goes to infinity)
316
- bytes_max : u64 ,
317
- /// Scale of bytes-based backpressure
318
- bytes_scale : Duration ,
319
-
320
- /// When should backpressure start, in units of jobs
321
- queue_start : u64 ,
322
- /// Maximum number of jobs (i.e. backpressure goes to infinity)
323
- queue_max : u64 ,
324
- /// Scale of queue-based delay
325
- queue_scale : Duration ,
326
- }
327
-
328
- impl BackpressureConfig {
329
- // Our chosen backpressure curve is quadratic for 1/2 of its range, then
330
- // goes to infinity in the second half. This gives C0 + C1 continuity.
331
- fn curve ( frac : f64 , scale : Duration ) -> Duration {
332
- // Remap from 0-1 to 0-1.5 for ease of calculation
333
- let frac = frac * 2.0 ;
334
- let v = if frac < 1.0 {
335
- frac
336
- } else {
337
- 1.0 / ( 1.0 - ( frac - 1.0 ) )
338
- } ;
339
- scale. mul_f64 ( v. powi ( 2 ) )
340
- }
341
-
342
- fn get_backpressure_us ( & self , bytes : u64 , jobs : u64 ) -> u64 {
343
- // Saturate at 1 hour per job, which is basically infinite
344
- if bytes >= self . bytes_max || jobs >= self . queue_max {
345
- return Duration :: from_secs ( 60 * 60 ) . as_micros ( ) as u64 ;
346
- }
347
-
348
- // These ratios start at 0 (at *_start) and hit 1 when backpressure
349
- // should be infinite.
350
- let jobs_frac = jobs. saturating_sub ( self . queue_start ) as f64
351
- / ( self . queue_max - self . queue_start ) as f64 ;
352
- let bytes_frac = bytes. saturating_sub ( self . bytes_start ) as f64
353
- / ( self . bytes_max - self . bytes_start ) as f64 ;
354
-
355
- // Delay should be 0 at frac = 0, and infinite at frac = 1
356
- let delay_bytes =
357
- Self :: curve ( bytes_frac, self . bytes_scale ) . as_micros ( ) as u64 ;
358
- let delay_jobs =
359
- Self :: curve ( jobs_frac, self . queue_scale ) . as_micros ( ) as u64 ;
360
-
361
- delay_bytes. max ( delay_jobs)
362
- }
363
- }
364
-
365
299
/*
366
300
* These methods are how to add or checking for new work on the Guest struct
367
301
*/
@@ -404,7 +338,7 @@ impl Guest {
404
338
iop_tokens : 0 ,
405
339
bw_tokens : 0 ,
406
340
backpressure_us : backpressure_us. clone ( ) ,
407
- backpressure_config : Self :: default_backpressure_config ( ) ,
341
+ backpressure_config : BackpressureConfig :: default ( ) ,
408
342
log : log. clone ( ) ,
409
343
} ;
410
344
let guest = Guest {
@@ -419,20 +353,6 @@ impl Guest {
419
353
( guest, io)
420
354
}
421
355
422
- fn default_backpressure_config ( ) -> BackpressureConfig {
423
- BackpressureConfig {
424
- // Byte-based backpressure
425
- bytes_start : 50 * 1024u64 . pow ( 2 ) , // 50 MiB
426
- bytes_max : IO_OUTSTANDING_MAX_BYTES * 2 ,
427
- bytes_scale : Duration :: from_millis ( 100 ) ,
428
-
429
- // Queue-based backpressure
430
- queue_start : 500 ,
431
- queue_max : IO_OUTSTANDING_MAX_JOBS as u64 * 2 ,
432
- queue_scale : Duration :: from_millis ( 5 ) ,
433
- }
434
- }
435
-
436
356
/*
437
357
* This is used to submit a new BlockOp IO request to Crucible.
438
358
*
@@ -941,17 +861,17 @@ impl GuestIoHandle {
941
861
942
862
#[ cfg( test) ]
943
863
pub fn disable_queue_backpressure ( & mut self ) {
944
- self . backpressure_config . queue_scale = Duration :: ZERO ;
864
+ self . backpressure_config . queue . scale = Duration :: ZERO ;
945
865
}
946
866
947
867
#[ cfg( test) ]
948
868
pub fn disable_byte_backpressure ( & mut self ) {
949
- self . backpressure_config . bytes_scale = Duration :: ZERO ;
869
+ self . backpressure_config . bytes . scale = Duration :: ZERO ;
950
870
}
951
871
952
872
#[ cfg( test) ]
953
873
pub fn is_queue_backpressure_disabled ( & self ) -> bool {
954
- self . backpressure_config . queue_scale == Duration :: ZERO
874
+ self . backpressure_config . queue . scale == Duration :: ZERO
955
875
}
956
876
957
877
/// Set `self.backpressure_us` based on outstanding IO ratio
@@ -1460,38 +1380,4 @@ mod test {
1460
1380
1461
1381
Ok ( ( ) )
1462
1382
}
1463
-
1464
- #[ test]
1465
- fn check_max_backpressure ( ) {
1466
- let cfg = Guest :: default_backpressure_config ( ) ;
1467
- let t = cfg. get_backpressure_us (
1468
- IO_OUTSTANDING_MAX_BYTES * 2 - 1024u64 . pow ( 2 ) ,
1469
- 0 ,
1470
- ) ;
1471
- let timeout = Duration :: from_micros ( t) ;
1472
- println ! (
1473
- "max byte-based delay: {}" ,
1474
- humantime:: format_duration( timeout)
1475
- ) ;
1476
- assert ! (
1477
- timeout > Duration :: from_secs( 60 * 60 ) ,
1478
- "max byte-based backpressure delay is too low;
1479
- expected > 1 hr, got {}" ,
1480
- humantime:: format_duration( timeout)
1481
- ) ;
1482
-
1483
- let t =
1484
- cfg. get_backpressure_us ( 0 , IO_OUTSTANDING_MAX_JOBS as u64 * 2 - 1 ) ;
1485
- let timeout = Duration :: from_micros ( t) ;
1486
- println ! (
1487
- "max job-based delay: {}" ,
1488
- humantime:: format_duration( timeout)
1489
- ) ;
1490
- assert ! (
1491
- timeout > Duration :: from_secs( 60 * 60 ) ,
1492
- "max job-based backpressure delay is too low;
1493
- expected > 1 hr, got {}" ,
1494
- humantime:: format_duration( timeout)
1495
- ) ;
1496
- }
1497
1383
}
0 commit comments