From 80bc4a0c79f840e36059eae5427045086b7b8d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 18 Nov 2021 21:12:08 +0100 Subject: [PATCH] Make authorship soft deadline configurable. (#10125) * Make soft deadline configurable. * cargo +nightly fmt --all * Move setter where it belongs. --- .../basic-authorship/src/basic_authorship.rs | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 4c7f6c856ec86..0fd3932807a17 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -42,7 +42,7 @@ use sp_inherents::InherentData; use sp_runtime::{ generic::BlockId, traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as HeaderT}, - Digest, + Digest, Percent, SaturatedConversion, }; use std::{marker::PhantomData, pin::Pin, sync::Arc, time}; @@ -58,6 +58,8 @@ use sc_proposer_metrics::MetricsLink as PrometheusMetrics; /// transferred to other nodes. pub const DEFAULT_BLOCK_SIZE_LIMIT: usize = 4 * 1024 * 1024 + 512; +const DEFAULT_SOFT_DEADLINE_PERCENT: Percent = Percent::from_percent(50); + /// [`Proposer`] factory. pub struct ProposerFactory { spawn_handle: Box, @@ -72,6 +74,14 @@ pub struct ProposerFactory { /// If no `block_size_limit` is passed to [`sp_consensus::Proposer::propose`], this block size /// limit will be used. default_block_size_limit: usize, + /// Soft deadline percentage of hard deadline. + /// + /// The value is used to compute soft deadline during block production. + /// The soft deadline indicates where we should stop attempting to add transactions + /// to the block, which exhaust resources. After soft deadline is reached, + /// we switch to a fixed-amount mode, in which after we see `MAX_SKIPPED_TRANSACTIONS` + /// transactions which exhaust resrouces, we will conclude that the block is full. + soft_deadline_percent: Percent, telemetry: Option, /// When estimating the block size, should the proof be included? include_proof_in_block_size_estimation: bool, @@ -96,6 +106,7 @@ impl ProposerFactory { transaction_pool, metrics: PrometheusMetrics::new(prometheus), default_block_size_limit: DEFAULT_BLOCK_SIZE_LIMIT, + soft_deadline_percent: DEFAULT_SOFT_DEADLINE_PERCENT, telemetry, client, include_proof_in_block_size_estimation: false, @@ -124,6 +135,7 @@ impl ProposerFactory { transaction_pool, metrics: PrometheusMetrics::new(prometheus), default_block_size_limit: DEFAULT_BLOCK_SIZE_LIMIT, + soft_deadline_percent: DEFAULT_SOFT_DEADLINE_PERCENT, telemetry, include_proof_in_block_size_estimation: true, _phantom: PhantomData, @@ -147,6 +159,22 @@ impl ProposerFactory { pub fn set_default_block_size_limit(&mut self, limit: usize) { self.default_block_size_limit = limit; } + + /// Set soft deadline percentage. + /// + /// The value is used to compute soft deadline during block production. + /// The soft deadline indicates where we should stop attempting to add transactions + /// to the block, which exhaust resources. After soft deadline is reached, + /// we switch to a fixed-amount mode, in which after we see `MAX_SKIPPED_TRANSACTIONS` + /// transactions which exhaust resrouces, we will conclude that the block is full. + /// + /// Setting the value too low will significantly limit the amount of transactions + /// we try in case they exhaust resources. Setting the value too high can + /// potentially open a DoS vector, where many "exhaust resources" transactions + /// are being tried with no success, hence block producer ends up creating an empty block. + pub fn set_soft_deadline(&mut self, percent: Percent) { + self.soft_deadline_percent = percent; + } } impl ProposerFactory @@ -184,6 +212,7 @@ where now, metrics: self.metrics.clone(), default_block_size_limit: self.default_block_size_limit, + soft_deadline_percent: self.soft_deadline_percent, telemetry: self.telemetry.clone(), _phantom: PhantomData, include_proof_in_block_size_estimation: self.include_proof_in_block_size_estimation, @@ -229,6 +258,7 @@ pub struct Proposer { metrics: PrometheusMetrics, default_block_size_limit: usize, include_proof_in_block_size_estimation: bool, + soft_deadline_percent: Percent, telemetry: Option, _phantom: PhantomData<(B, PR)>, } @@ -340,7 +370,10 @@ where // proceed with transactions // We calculate soft deadline used only in case we start skipping transactions. let now = (self.now)(); - let soft_deadline = now + deadline.saturating_duration_since(now) / 2; + let left = deadline.saturating_duration_since(now); + let left_micros: u64 = left.as_micros().saturated_into(); + let soft_deadline = + now + time::Duration::from_micros(self.soft_deadline_percent.mul_floor(left_micros)); let block_timer = time::Instant::now(); let mut skipped = 0; let mut unqueue_invalid = Vec::new();