Use spawn_async in ByRoot handling workers (#5557)

* Use spawn_async in ByRoot handling workers

* box large variants
This commit is contained in:
Lion - dapplion
2024-04-13 04:30:04 +09:00
committed by GitHub
parent 116a55e8a5
commit b6a1c863a2
3 changed files with 184 additions and 239 deletions

View File

@@ -571,7 +571,7 @@ pub enum BlockingOrAsync {
/// queuing specifics. /// queuing specifics.
pub enum Work<E: EthSpec> { pub enum Work<E: EthSpec> {
GossipAttestation { GossipAttestation {
attestation: GossipAttestationPackage<E>, attestation: Box<GossipAttestationPackage<E>>,
process_individual: Box<dyn FnOnce(GossipAttestationPackage<E>) + Send + Sync>, process_individual: Box<dyn FnOnce(GossipAttestationPackage<E>) + Send + Sync>,
process_batch: Box<dyn FnOnce(Vec<GossipAttestationPackage<E>>) + Send + Sync>, process_batch: Box<dyn FnOnce(Vec<GossipAttestationPackage<E>>) + Send + Sync>,
}, },
@@ -583,7 +583,7 @@ pub enum Work<E: EthSpec> {
process_batch: Box<dyn FnOnce(Vec<GossipAttestationPackage<E>>) + Send + Sync>, process_batch: Box<dyn FnOnce(Vec<GossipAttestationPackage<E>>) + Send + Sync>,
}, },
GossipAggregate { GossipAggregate {
aggregate: GossipAggregatePackage<E>, aggregate: Box<GossipAggregatePackage<E>>,
process_individual: Box<dyn FnOnce(GossipAggregatePackage<E>) + Send + Sync>, process_individual: Box<dyn FnOnce(GossipAggregatePackage<E>) + Send + Sync>,
process_batch: Box<dyn FnOnce(Vec<GossipAggregatePackage<E>>) + Send + Sync>, process_batch: Box<dyn FnOnce(Vec<GossipAggregatePackage<E>>) + Send + Sync>,
}, },
@@ -624,8 +624,8 @@ pub enum Work<E: EthSpec> {
ChainSegment(AsyncFn), ChainSegment(AsyncFn),
ChainSegmentBackfill(AsyncFn), ChainSegmentBackfill(AsyncFn),
Status(BlockingFn), Status(BlockingFn),
BlocksByRangeRequest(BlockingFnWithManualSendOnIdle), BlocksByRangeRequest(AsyncFn),
BlocksByRootsRequest(BlockingFnWithManualSendOnIdle), BlocksByRootsRequest(AsyncFn),
BlobsByRangeRequest(BlockingFn), BlobsByRangeRequest(BlockingFn),
BlobsByRootsRequest(BlockingFn), BlobsByRootsRequest(BlockingFn),
GossipBlsToExecutionChange(BlockingFn), GossipBlsToExecutionChange(BlockingFn),
@@ -1015,7 +1015,7 @@ impl<E: EthSpec> BeaconProcessor<E> {
process_individual: _, process_individual: _,
process_batch, process_batch,
} => { } => {
aggregates.push(aggregate); aggregates.push(*aggregate);
if process_batch_opt.is_none() { if process_batch_opt.is_none() {
process_batch_opt = Some(process_batch); process_batch_opt = Some(process_batch);
} }
@@ -1075,7 +1075,7 @@ impl<E: EthSpec> BeaconProcessor<E> {
process_individual: _, process_individual: _,
process_batch, process_batch,
} => { } => {
attestations.push(attestation); attestations.push(*attestation);
if process_batch_opt.is_none() { if process_batch_opt.is_none() {
process_batch_opt = Some(process_batch); process_batch_opt = Some(process_batch);
} }
@@ -1445,7 +1445,7 @@ impl<E: EthSpec> BeaconProcessor<E> {
process_individual, process_individual,
process_batch: _, process_batch: _,
} => task_spawner.spawn_blocking(move || { } => task_spawner.spawn_blocking(move || {
process_individual(attestation); process_individual(*attestation);
}), }),
Work::GossipAttestationBatch { Work::GossipAttestationBatch {
attestations, attestations,
@@ -1458,7 +1458,7 @@ impl<E: EthSpec> BeaconProcessor<E> {
process_individual, process_individual,
process_batch: _, process_batch: _,
} => task_spawner.spawn_blocking(move || { } => task_spawner.spawn_blocking(move || {
process_individual(aggregate); process_individual(*aggregate);
}), }),
Work::GossipAggregateBatch { Work::GossipAggregateBatch {
aggregates, aggregates,
@@ -1493,7 +1493,7 @@ impl<E: EthSpec> BeaconProcessor<E> {
task_spawner.spawn_blocking(process_fn) task_spawner.spawn_blocking(process_fn)
} }
Work::BlocksByRangeRequest(work) | Work::BlocksByRootsRequest(work) => { Work::BlocksByRangeRequest(work) | Work::BlocksByRootsRequest(work) => {
task_spawner.spawn_blocking_with_manual_send_idle(work) task_spawner.spawn_async(work)
} }
Work::ChainSegmentBackfill(process_fn) => task_spawner.spawn_async(process_fn), Work::ChainSegmentBackfill(process_fn) => task_spawner.spawn_async(process_fn),
Work::ApiRequestP0(process_fn) | Work::ApiRequestP1(process_fn) => match process_fn { Work::ApiRequestP0(process_fn) | Work::ApiRequestP1(process_fn) => match process_fn {
@@ -1555,23 +1555,6 @@ impl TaskSpawner {
WORKER_TASK_NAME, WORKER_TASK_NAME,
) )
} }
/// Spawn a blocking task, passing the `SendOnDrop` into the task.
///
/// ## Notes
///
/// Users must ensure the `SendOnDrop` is dropped at the appropriate time!
pub fn spawn_blocking_with_manual_send_idle<F>(self, task: F)
where
F: FnOnce(SendOnDrop) + Send + 'static,
{
self.executor.spawn_blocking(
|| {
task(self.send_idle_on_drop);
},
WORKER_TASK_NAME,
)
}
} }
/// This struct will send a message on `self.tx` when it is dropped. An error will be logged on /// This struct will send a message on `self.tx` when it is dropped. An error will be logged on

View File

@@ -102,14 +102,14 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
self.try_send(BeaconWorkEvent { self.try_send(BeaconWorkEvent {
drop_during_sync: true, drop_during_sync: true,
work: Work::GossipAttestation { work: Work::GossipAttestation {
attestation: GossipAttestationPackage { attestation: Box::new(GossipAttestationPackage {
message_id, message_id,
peer_id, peer_id,
attestation: Box::new(attestation), attestation: Box::new(attestation),
subnet_id, subnet_id,
should_import, should_import,
seen_timestamp, seen_timestamp,
}, }),
process_individual: Box::new(process_individual), process_individual: Box::new(process_individual),
process_batch: Box::new(process_batch), process_batch: Box::new(process_batch),
}, },
@@ -148,13 +148,13 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
self.try_send(BeaconWorkEvent { self.try_send(BeaconWorkEvent {
drop_during_sync: true, drop_during_sync: true,
work: Work::GossipAggregate { work: Work::GossipAggregate {
aggregate: GossipAggregatePackage { aggregate: Box::new(GossipAggregatePackage {
message_id, message_id,
peer_id, peer_id,
aggregate: Box::new(aggregate), aggregate: Box::new(aggregate),
beacon_block_root, beacon_block_root,
seen_timestamp, seen_timestamp,
}, }),
process_individual: Box::new(process_individual), process_individual: Box::new(process_individual),
process_batch: Box::new(process_batch), process_batch: Box::new(process_batch),
}, },
@@ -508,20 +508,16 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
request: BlocksByRangeRequest, request: BlocksByRangeRequest,
) -> Result<(), Error<T::EthSpec>> { ) -> Result<(), Error<T::EthSpec>> {
let processor = self.clone(); let processor = self.clone();
let process_fn = move |send_idle_on_drop| { let process_fn = async move {
let executor = processor.executor.clone(); let executor = processor.executor.clone();
processor.handle_blocks_by_range_request( processor
executor, .handle_blocks_by_range_request(executor, peer_id, request_id, request)
send_idle_on_drop, .await;
peer_id,
request_id,
request,
)
}; };
self.try_send(BeaconWorkEvent { self.try_send(BeaconWorkEvent {
drop_during_sync: false, drop_during_sync: false,
work: Work::BlocksByRangeRequest(Box::new(process_fn)), work: Work::BlocksByRangeRequest(Box::pin(process_fn)),
}) })
} }
@@ -533,20 +529,16 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
request: BlocksByRootRequest, request: BlocksByRootRequest,
) -> Result<(), Error<T::EthSpec>> { ) -> Result<(), Error<T::EthSpec>> {
let processor = self.clone(); let processor = self.clone();
let process_fn = move |send_idle_on_drop| { let process_fn = async move {
let executor = processor.executor.clone(); let executor = processor.executor.clone();
processor.handle_blocks_by_root_request( processor
executor, .handle_blocks_by_root_request(executor, peer_id, request_id, request)
send_idle_on_drop, .await;
peer_id,
request_id,
request,
)
}; };
self.try_send(BeaconWorkEvent { self.try_send(BeaconWorkEvent {
drop_during_sync: false, drop_during_sync: false,
work: Work::BlocksByRootsRequest(Box::new(process_fn)), work: Work::BlocksByRootsRequest(Box::pin(process_fn)),
}) })
} }

View File

@@ -3,7 +3,6 @@ use crate::service::NetworkMessage;
use crate::status::ToStatusMessage; use crate::status::ToStatusMessage;
use crate::sync::SyncMessage; use crate::sync::SyncMessage;
use beacon_chain::{BeaconChainError, BeaconChainTypes, HistoricalBlockError, WhenSlotSkipped}; use beacon_chain::{BeaconChainError, BeaconChainTypes, HistoricalBlockError, WhenSlotSkipped};
use beacon_processor::SendOnDrop;
use itertools::process_results; use itertools::process_results;
use lighthouse_network::rpc::methods::{BlobsByRangeRequest, BlobsByRootRequest}; use lighthouse_network::rpc::methods::{BlobsByRangeRequest, BlobsByRootRequest};
use lighthouse_network::rpc::*; use lighthouse_network::rpc::*;
@@ -128,10 +127,9 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
} }
/// Handle a `BlocksByRoot` request from the peer. /// Handle a `BlocksByRoot` request from the peer.
pub fn handle_blocks_by_root_request( pub async fn handle_blocks_by_root_request(
self: Arc<Self>, self: Arc<Self>,
executor: TaskExecutor, executor: TaskExecutor,
send_on_drop: SendOnDrop,
peer_id: PeerId, peer_id: PeerId,
request_id: PeerRequestId, request_id: PeerRequestId,
request: BlocksByRootRequest, request: BlocksByRootRequest,
@@ -145,10 +143,7 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
Err(e) => return error!(self.log, "Error getting block stream"; "error" => ?e), Err(e) => return error!(self.log, "Error getting block stream"; "error" => ?e),
}; };
// Fetching blocks is async because it may have to hit the execution layer for payloads. // Fetching blocks is async because it may have to hit the execution layer for payloads.
executor.spawn(
async move {
let mut send_block_count = 0; let mut send_block_count = 0;
let mut send_response = true;
while let Some((root, result)) = block_stream.next().await { while let Some((root, result)) = block_stream.next().await {
match result.as_ref() { match result.as_ref() {
Ok(Some(block)) => { Ok(Some(block)) => {
@@ -175,14 +170,12 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
"reason" => "execution layer not synced", "reason" => "execution layer not synced",
); );
// send the stream terminator // send the stream terminator
self.send_error_response( return self.send_error_response(
peer_id, peer_id,
RPCResponseErrorCode::ResourceUnavailable, RPCResponseErrorCode::ResourceUnavailable,
"Execution layer not synced".into(), "Execution layer not synced".into(),
request_id, request_id,
); );
send_response = false;
break;
} }
Err(e) => { Err(e) => {
debug!( debug!(
@@ -204,14 +197,8 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
); );
// send stream termination // send stream termination
if send_response {
self.send_response(peer_id, Response::BlocksByRoot(None), request_id); self.send_response(peer_id, Response::BlocksByRoot(None), request_id);
} }
drop(send_on_drop);
},
"load_blocks_by_root_blocks",
)
}
/// Handle a `BlobsByRoot` request from the peer. /// Handle a `BlobsByRoot` request from the peer.
pub fn handle_blobs_by_root_request( pub fn handle_blobs_by_root_request(
@@ -386,10 +373,9 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
} }
/// Handle a `BlocksByRange` request from the peer. /// Handle a `BlocksByRange` request from the peer.
pub fn handle_blocks_by_range_request( pub async fn handle_blocks_by_range_request(
self: Arc<Self>, self: Arc<Self>,
executor: TaskExecutor, executor: TaskExecutor,
send_on_drop: SendOnDrop,
peer_id: PeerId, peer_id: PeerId,
request_id: PeerRequestId, request_id: PeerRequestId,
req: BlocksByRangeRequest, req: BlocksByRangeRequest,
@@ -499,10 +485,7 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
}; };
// Fetching blocks is async because it may have to hit the execution layer for payloads. // Fetching blocks is async because it may have to hit the execution layer for payloads.
executor.spawn(
async move {
let mut blocks_sent = 0; let mut blocks_sent = 0;
let mut send_response = true;
while let Some((root, result)) = block_stream.next().await { while let Some((root, result)) = block_stream.next().await {
match result.as_ref() { match result.as_ref() {
@@ -528,14 +511,12 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
"peer" => %peer_id, "peer" => %peer_id,
"request_root" => ?root "request_root" => ?root
); );
self.send_error_response( return self.send_error_response(
peer_id, peer_id,
RPCResponseErrorCode::ServerError, RPCResponseErrorCode::ServerError,
"Database inconsistency".into(), "Database inconsistency".into(),
request_id, request_id,
); );
send_response = false;
break;
} }
Err(BeaconChainError::BlockHashMissingFromExecutionLayer(_)) => { Err(BeaconChainError::BlockHashMissingFromExecutionLayer(_)) => {
debug!( debug!(
@@ -545,14 +526,12 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
"reason" => "execution layer not synced", "reason" => "execution layer not synced",
); );
// send the stream terminator // send the stream terminator
self.send_error_response( return self.send_error_response(
peer_id, peer_id,
RPCResponseErrorCode::ResourceUnavailable, RPCResponseErrorCode::ResourceUnavailable,
"Execution layer not synced".into(), "Execution layer not synced".into(),
request_id, request_id,
); );
send_response = false;
break;
} }
Err(e) => { Err(e) => {
if matches!( if matches!(
@@ -577,14 +556,12 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
} }
// send the stream terminator // send the stream terminator
self.send_error_response( return self.send_error_response(
peer_id, peer_id,
RPCResponseErrorCode::ServerError, RPCResponseErrorCode::ServerError,
"Failed fetching blocks".into(), "Failed fetching blocks".into(),
request_id, request_id,
); );
send_response = false;
break;
} }
} }
} }
@@ -617,7 +594,6 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
); );
} }
if send_response {
// send the stream terminator // send the stream terminator
self.send_network_message(NetworkMessage::SendResponse { self.send_network_message(NetworkMessage::SendResponse {
peer_id, peer_id,
@@ -626,12 +602,6 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
}); });
} }
drop(send_on_drop);
},
"load_blocks_by_range_blocks",
);
}
/// Handle a `BlobsByRange` request from the peer. /// Handle a `BlobsByRange` request from the peer.
pub fn handle_blobs_by_range_request( pub fn handle_blobs_by_range_request(
self: Arc<Self>, self: Arc<Self>,