Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve performance of EVM tracing Step event #1033

Merged
merged 3 commits into from
Dec 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 12 additions & 12 deletions client/evm-tracing/src/listeners/call_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::types::{CallResult, CallType, ContextType, CreateResult};
use ethereum_types::{H160, U256};
use evm_tracing_events::{
runtime::{Capture, ExitError, ExitReason, ExitSucceed},
Event, EvmEvent, GasometerEvent, Listener as ListenerT, RuntimeEvent,
Event, EvmEvent, GasometerEvent, Listener as ListenerT, RuntimeEvent, StepEventFilter,
};
use std::{collections::btree_map::BTreeMap, vec, vec::Vec};

Expand Down Expand Up @@ -636,6 +636,13 @@ impl ListenerT for Listener {
}
};
}

fn step_event_filter(&self) -> StepEventFilter {
StepEventFilter {
enable_memory: false,
enable_stack: false,
}
}
}

#[cfg(test)]
Expand Down Expand Up @@ -689,19 +696,12 @@ mod tests {
}
}

fn test_stack() -> Stack {
Stack {
data: Vec::new(),
limit: 0u64,
}
fn test_stack() -> Option<Stack> {
None
}

fn test_memory() -> Memory {
Memory {
data: Vec::new(),
effective_len: U256::zero(),
limit: 0u64,
}
fn test_memory() -> Option<Memory> {
None
}

fn test_snapshot() -> Snapshot {
Expand Down
23 changes: 20 additions & 3 deletions client/evm-tracing/src/listeners/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use std::{collections::btree_map::BTreeMap, vec, vec::Vec};
use crate::types::{convert_memory, single::RawStepLog, ContextType};
use evm_tracing_events::{
runtime::{Capture, ExitReason},
Event, GasometerEvent, Listener as ListenerT, RuntimeEvent,
Event, GasometerEvent, Listener as ListenerT, RuntimeEvent, StepEventFilter,
};

#[derive(Debug)]
Expand Down Expand Up @@ -155,12 +155,22 @@ impl Listener {
memory: if self.disable_memory {
None
} else {
Some(memory.data.clone())
Some(
memory
.expect("memory data to not be filtered out")
.data
.clone(),
)
},
stack: if self.disable_stack {
None
} else {
Some(stack.data.clone())
Some(
stack
.expect("stack data to not be filtered out")
.data
.clone(),
)
},
});
}
Expand Down Expand Up @@ -289,4 +299,11 @@ impl ListenerT for Listener {
_ => {}
};
}

fn step_event_filter(&self) -> StepEventFilter {
StepEventFilter {
enable_memory: !self.disable_memory,
enable_stack: !self.disable_stack,
}
}
}
9 changes: 8 additions & 1 deletion primitives/ext/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use sp_runtime_interface::runtime_interface;
use codec::Decode;
use sp_std::vec::Vec;

use evm_tracing_events::{Event, EvmEvent, GasometerEvent, RuntimeEvent};
use evm_tracing_events::{Event, EvmEvent, GasometerEvent, RuntimeEvent, StepEventFilter};

#[runtime_interface]
pub trait MoonbeamExt {
Expand Down Expand Up @@ -67,6 +67,13 @@ pub trait MoonbeamExt {
}
}

/// Allow the tracing module in the runtime to know how to filter Step event
/// content, as cloning the entire data is expensive and most of the time
/// not necessary.
fn step_event_filter(&self) -> StepEventFilter {
evm_tracing_events::step_event_filter().unwrap_or_default()
}

/// An event to create a new CallList (currently a new transaction when tracing a block).
#[version(2)]
fn call_list_new(&mut self) {
Expand Down
1 change: 1 addition & 0 deletions primitives/rpc/evm-tracing-events/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ environmental = { version = "1.1.2", default-features = false }

# Substrate
codec = { package = "parity-scale-codec", version = "2.2", default-features = false }
sp-runtime-interface = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.12", default-features = false }

# Ethereum
ethereum = { version = "0.9.0", default-features = false, features = [ "with-codec" ] }
Expand Down
21 changes: 21 additions & 0 deletions primitives/rpc/evm-tracing-events/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,23 @@ use ::evm::Opcode;
use alloc::vec::Vec;
use codec::{Decode, Encode};
use ethereum_types::{H160, U256};
use sp_runtime_interface::pass_by::PassByCodec;

environmental::environmental!(listener: dyn Listener + 'static);

pub fn using<R, F: FnOnce() -> R>(l: &mut (dyn Listener + 'static), f: F) -> R {
listener::using(l, f)
}

/// Allow to configure which data of the Step event
/// we want to keep or discard. Not discarding the data requires cloning the data
/// in the runtime which have a significant cost for each step.
#[derive(Clone, Copy, Eq, PartialEq, Debug, Encode, Decode, Default, PassByCodec)]
pub struct StepEventFilter {
pub enable_stack: bool,
pub enable_memory: bool,
}

#[derive(Clone, Eq, PartialEq, Debug, Encode, Decode)]
pub enum Event {
Evm(evm::EvmEvent),
Expand All @@ -74,6 +84,17 @@ impl Event {
/// - Inside the client to forward those events to the client listener.
pub trait Listener {
fn event(&mut self, event: Event);

/// Allow the runtime to know which data should be discarded and not cloned.
/// WARNING: It is only called once when the runtime tracing is instanciated to avoid
/// performing many ext calls.
fn step_event_filter(&self) -> StepEventFilter;
}

pub fn step_event_filter() -> Option<StepEventFilter> {
let mut filter = None;
listener::with(|listener| filter = Some(listener.step_event_filter()));
filter
}

#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq)]
Expand Down
22 changes: 16 additions & 6 deletions primitives/rpc/evm-tracing-events/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

extern crate alloc;

use crate::StepEventFilter;

use super::{opcodes_string, Context};
use alloc::vec::Vec;
use codec::{Decode, Encode};
Expand Down Expand Up @@ -73,8 +75,8 @@ pub enum RuntimeEvent {
opcode: Vec<u8>,
// We can use ExitReason with `with-codec` feature,
position: Result<u64, ExitReason>,
stack: Stack,
memory: Memory,
stack: Option<Stack>,
memory: Option<Memory>,
},
StepResult {
result: Result<(), Capture<ExitReason, Trap>>,
Expand All @@ -93,8 +95,8 @@ pub enum RuntimeEvent {
}

#[cfg(feature = "evm-tracing")]
impl<'a> From<evm_runtime::tracing::Event<'a>> for RuntimeEvent {
fn from(i: evm_runtime::tracing::Event<'a>) -> Self {
impl RuntimeEvent {
pub fn from_evm_event<'a>(i: evm_runtime::tracing::Event<'a>, filter: StepEventFilter) -> Self {
match i {
evm_runtime::tracing::Event::Step {
context,
Expand All @@ -109,8 +111,16 @@ impl<'a> From<evm_runtime::tracing::Event<'a>> for RuntimeEvent {
Ok(position) => Ok(*position as u64),
Err(e) => Err(e.clone()),
},
stack: stack.into(),
memory: memory.into(),
stack: if filter.enable_stack {
Some(stack.into())
} else {
None
},
memory: if filter.enable_memory {
Some(memory.into())
} else {
None
},
},
evm_runtime::tracing::Event::StepResult {
result,
Expand Down
14 changes: 10 additions & 4 deletions runtime/evm_tracer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

pub mod tracer {
use codec::Encode;
use evm_tracing_events::{EvmEvent, GasometerEvent, RuntimeEvent};
use evm_tracing_events::{EvmEvent, GasometerEvent, RuntimeEvent, StepEventFilter};

use evm::tracing::{using as evm_using, EventListener as EvmListener};
use evm_gasometer::tracing::{using as gasometer_using, EventListener as GasometerListener};
Expand All @@ -52,11 +52,17 @@ pub mod tracer {
}
}

pub struct EvmTracer;
pub struct EvmTracer {
step_event_filter: StepEventFilter,
}

impl EvmTracer {
pub fn new() -> Self {
Self
Self {
step_event_filter: moonbeam_primitives_ext::moonbeam_ext::step_event_filter(),
}
}

/// Setup event listeners and execute provided closure.
///
/// Consume the tracer and return it alongside the return value of
Expand Down Expand Up @@ -103,7 +109,7 @@ pub mod tracer {
impl RuntimeListener for EvmTracer {
/// Proxies `evm_runtime::tracing::Event` to the host.
fn event(&mut self, event: evm_runtime::tracing::Event) {
let event: RuntimeEvent = event.into();
let event = RuntimeEvent::from_evm_event(event, self.step_event_filter);
let message = event.encode();
moonbeam_primitives_ext::moonbeam_ext::runtime_event(message);
}
Expand Down