Move spawning tasks from thread pools to Service's TaskManager for block importing (#5647)

Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
This commit is contained in:
pscott
2020-04-29 18:46:39 +02:00
committed by GitHub
parent bb94695a4e
commit 0f401e4699
22 changed files with 124 additions and 107 deletions
+12 -8
View File
@@ -15,7 +15,7 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use crate::{Service, NetworkStatus, NetworkState, error::Error, DEFAULT_PROTOCOL_ID, MallocSizeOfWasm};
use crate::{start_rpc_servers, build_network_future, TransactionPoolAdapter, TaskManager};
use crate::{start_rpc_servers, build_network_future, TransactionPoolAdapter, TaskManager, SpawnTaskHandle};
use crate::status_sinks;
use crate::config::{Configuration, KeystoreConfig, PrometheusConfig, OffchainWorkerConfig};
use crate::metrics::MetricsService;
@@ -97,7 +97,7 @@ pub struct ServiceBuilder<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp,
remote_backend: Option<Arc<dyn RemoteBlockchain<TBl>>>,
marker: PhantomData<(TBl, TRtApi)>,
background_tasks: Vec<(&'static str, BackgroundTask)>,
block_announce_validator_builder: Option<Box<dyn FnOnce(Arc<TCl>) -> Box<dyn BlockAnnounceValidator<TBl> + Send>>>,
block_announce_validator_builder: Option<Box<dyn FnOnce(Arc<TCl>) -> Box<dyn BlockAnnounceValidator<TBl> + Send> + Send>>,
}
/// Full client type.
@@ -487,7 +487,7 @@ impl<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend>
/// Defines which import queue to use.
pub fn with_import_queue<UImpQu>(
self,
builder: impl FnOnce(&Configuration, Arc<TCl>, Option<TSc>, Arc<TExPool>)
builder: impl FnOnce(&Configuration, Arc<TCl>, Option<TSc>, Arc<TExPool>, &SpawnTaskHandle)
-> Result<UImpQu, Error>
) -> Result<ServiceBuilder<TBl, TRtApi, TCl, TFchr, TSc, UImpQu, TFprb, TFpp,
TExPool, TRpc, Backend>, Error>
@@ -496,7 +496,8 @@ impl<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend>
&self.config,
self.client.clone(),
self.select_chain.clone(),
self.transaction_pool.clone()
self.transaction_pool.clone(),
&self.task_manager.spawn_handle(),
)?;
Ok(ServiceBuilder {
@@ -588,6 +589,7 @@ impl<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend>
Option<TFchr>,
Option<TSc>,
Arc<TExPool>,
&SpawnTaskHandle,
) -> Result<(UImpQu, Option<UFprb>), Error>
) -> Result<ServiceBuilder<TBl, TRtApi, TCl, TFchr, TSc, UImpQu, UFprb, TFpp,
TExPool, TRpc, Backend>, Error>
@@ -598,7 +600,8 @@ impl<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend>
self.backend.clone(),
self.fetcher.clone(),
self.select_chain.clone(),
self.transaction_pool.clone()
self.transaction_pool.clone(),
&self.task_manager.spawn_handle(),
)?;
Ok(ServiceBuilder {
@@ -631,12 +634,13 @@ impl<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend>
Option<TFchr>,
Option<TSc>,
Arc<TExPool>,
&SpawnTaskHandle,
) -> Result<(UImpQu, UFprb), Error>
) -> Result<ServiceBuilder<TBl, TRtApi, TCl, TFchr, TSc, UImpQu, UFprb, TFpp,
TExPool, TRpc, Backend>, Error>
where TSc: Clone, TFchr: Clone {
self.with_import_queue_and_opt_fprb(|cfg, cl, b, f, sc, tx|
builder(cfg, cl, b, f, sc, tx)
self.with_import_queue_and_opt_fprb(|cfg, cl, b, f, sc, tx, tb|
builder(cfg, cl, b, f, sc, tx, tb)
.map(|(q, f)| (q, Some(f)))
)
}
@@ -718,7 +722,7 @@ impl<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend>
pub fn with_block_announce_validator(
self,
block_announce_validator_builder:
impl FnOnce(Arc<TCl>) -> Box<dyn BlockAnnounceValidator<TBl> + Send> + 'static,
impl FnOnce(Arc<TCl>) -> Box<dyn BlockAnnounceValidator<TBl> + Send> + Send + 'static,
) -> Result<ServiceBuilder<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp,
TExPool, TRpc, Backend>, Error>
where TSc: Clone, TFchr: Clone {
+8 -6
View File
@@ -56,12 +56,13 @@ impl<
TExecDisp: 'static + NativeExecutionDispatch,
TImpQu: 'static + ImportQueue<TBl>,
TRtApi: 'static + Send + Sync,
Self: Send + 'static,
{
type Block = TBl;
type NativeDispatch = TExecDisp;
fn import_blocks(
self,
mut self,
input: impl Read + Seek + Send + 'static,
force: bool,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send>> {
@@ -98,9 +99,6 @@ impl<
}
}
let client = self.client;
let mut queue = self.import_queue;
let mut io_reader_input = IoReader(input);
let mut count = None::<u64>;
let mut read_block_count = 0;
@@ -114,6 +112,9 @@ impl<
// This makes it possible either to interleave other operations in-between the block imports,
// or to stop the operation completely.
let import = future::poll_fn(move |cx| {
let client = &self.client;
let queue = &mut self.import_queue;
// Start by reading the number of blocks if not done so already.
let count = match count {
Some(c) => c,
@@ -203,13 +204,12 @@ impl<
to: Option<NumberFor<TBl>>,
binary: bool
) -> Pin<Box<dyn Future<Output = Result<(), Error>>>> {
let client = self.client;
let mut block = from;
let last = match to {
Some(v) if v.is_zero() => One::one(),
Some(v) => v,
None => client.chain_info().best_number,
None => self.client.chain_info().best_number,
};
let mut wrote_header = false;
@@ -222,6 +222,8 @@ impl<
// This makes it possible either to interleave other operations in-between the block exports,
// or to stop the operation completely.
let export = future::poll_fn(move |cx| {
let client = &self.client;
if last < block {
return std::task::Poll::Ready(Err("Invalid block range specified".into()));
}
+10 -1
View File
@@ -38,7 +38,7 @@ pub struct Configuration {
/// Node role.
pub role: Role,
/// How to spawn background tasks. Mandatory, otherwise creating a `Service` will error.
pub task_executor: Arc<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send + Sync>,
pub task_executor: Arc<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>, TaskType) + Send + Sync>,
/// Extrinsic pool configuration.
pub transaction_pool: TransactionPoolOptions,
/// Network configuration.
@@ -102,6 +102,15 @@ pub struct Configuration {
pub announce_block: bool,
}
/// Type for tasks spawned by the executor.
#[derive(PartialEq)]
pub enum TaskType {
/// Regular non-blocking futures. Polling the task is expected to be a lightweight operation.
Async,
/// The task might perform a lot of expensive CPU operations and/or call `thread::sleep`.
Blocking,
}
/// Configuration of the client keystore.
#[derive(Clone)]
pub enum KeystoreConfig {
+1 -1
View File
@@ -64,7 +64,7 @@ pub use self::builder::{
ServiceBuilder, ServiceBuilderCommand, TFullClient, TLightClient, TFullBackend, TLightBackend,
TFullCallExecutor, TLightCallExecutor,
};
pub use config::{Configuration, Role, PruningMode, DatabaseConfig};
pub use config::{Configuration, Role, PruningMode, DatabaseConfig, TaskType};
pub use sc_chain_spec::{
ChainSpec, GenericChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension,
NoExtension, ChainType,
+13 -2
View File
@@ -31,11 +31,12 @@ use prometheus_endpoint::{
CounterVec, HistogramOpts, HistogramVec, Opts, Registry, U64
};
use sc_client_api::CloneableSpawn;
use crate::config::TaskType;
mod prometheus_future;
/// Type alias for service task executor (usually runtime).
pub type ServiceTaskExecutor = Arc<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send + Sync>;
pub type ServiceTaskExecutor = Arc<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>, TaskType) + Send + Sync>;
/// An handle for spawning tasks in the service.
#[derive(Clone)]
@@ -55,6 +56,16 @@ impl SpawnTaskHandle {
/// In other words, it would be a bad idea for someone to do for example
/// `spawn(format!("{:?}", some_public_key))`.
pub fn spawn(&self, name: &'static str, task: impl Future<Output = ()> + Send + 'static) {
self.spawn_inner(name, task, TaskType::Async)
}
/// Spawns the blocking task with the given name. See also `spawn`.
pub fn spawn_blocking(&self, name: &'static str, task: impl Future<Output = ()> + Send + 'static) {
self.spawn_inner(name, task, TaskType::Blocking)
}
/// Helper function that implements the spawning logic. See `spawn` and `spawn_blocking`.
fn spawn_inner(&self, name: &'static str, task: impl Future<Output = ()> + Send + 'static, task_type: TaskType) {
let on_exit = self.on_exit.clone();
let metrics = self.metrics.clone();
@@ -80,7 +91,7 @@ impl SpawnTaskHandle {
}
};
(self.executor)(Box::pin(future));
(self.executor)(Box::pin(future), task_type);
}
}