From 33c8ac47ec269d777097513b65b3f28987c5c8c1 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 6 Oct 2016 00:55:38 +0300 Subject: [PATCH 1/5] stack size for io workers & evm threshold --- ethcore/src/executive.rs | 2 +- util/io/src/worker.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index b0b0b58c856..fb7cd91cf92 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -28,7 +28,7 @@ pub use types::executed::{Executed, ExecutionResult}; /// Max depth to avoid stack overflow (when it's reached we start a new thread with VM) /// TODO [todr] We probably need some more sophisticated calculations here (limit on my machine 132) /// Maybe something like here: `https://github.com/ethereum/libethereum/blob/4db169b8504f2b87f7d5a481819cfb959fc65f6c/libethereum/ExtVM.cpp` -const MAX_VM_DEPTH_FOR_THREAD: usize = 64; +const MAX_VM_DEPTH_FOR_THREAD: usize = 1024; /// Returns new address created from address and given nonce. pub fn contract_address(address: &Address, nonce: &U256) -> Address { diff --git a/util/io/src/worker.rs b/util/io/src/worker.rs index 0176c467cad..223f2ac0efe 100644 --- a/util/io/src/worker.rs +++ b/util/io/src/worker.rs @@ -25,6 +25,8 @@ use panics::*; use std::sync::{Condvar as SCondvar, Mutex as SMutex}; +const STACK_SIZE: usize = 16*1024*1024; + pub enum WorkType { Readable, Writable, @@ -66,7 +68,7 @@ impl Worker { deleting: deleting.clone(), wait_mutex: wait_mutex.clone(), }; - worker.thread = Some(thread::Builder::new().name(format!("IO Worker #{}", index)).spawn( + worker.thread = Some(thread::Builder::new().stack_size(STACK_SIZE).name(format!("IO Worker #{}", index)).spawn( move || { panic_handler.catch_panic(move || { Worker::work_loop(stealer, channel.clone(), wait, wait_mutex.clone(), deleting) From f2186f5a1e817a2f717a65052b6abab6abe5d39a Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 6 Oct 2016 02:19:12 +0300 Subject: [PATCH 2/5] rust way to remember stack size --- ethcore/src/executive.rs | 9 ++++++--- util/io/src/lib.rs | 2 ++ util/io/src/worker.rs | 9 +++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index fb7cd91cf92..b970c1b12b8 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -25,10 +25,10 @@ use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer, VMTrace, VMTracer, E use crossbeam; pub use types::executed::{Executed, ExecutionResult}; -/// Max depth to avoid stack overflow (when it's reached we start a new thread with VM) +/// Roughly estimate what stack size each level of evm depth will use /// TODO [todr] We probably need some more sophisticated calculations here (limit on my machine 132) /// Maybe something like here: `https://github.com/ethereum/libethereum/blob/4db169b8504f2b87f7d5a481819cfb959fc65f6c/libethereum/ExtVM.cpp` -const MAX_VM_DEPTH_FOR_THREAD: usize = 1024; +const STACK_SIZE_PER_DEPTH: usize = 256*1024; /// Returns new address created from address and given nonce. pub fn contract_address(address: &Address, nonce: &U256) -> Address { @@ -212,8 +212,11 @@ impl<'a> Executive<'a> { tracer: &mut T, vm_tracer: &mut V ) -> evm::Result where T: Tracer, V: VMTracer { + + let depth_threshold = ::io::LOCAL_STACK_SIZE.with(|sz| sz.get() / STACK_SIZE_PER_DEPTH); + // Ordinary execution - keep VM in same thread - if (self.depth + 1) % MAX_VM_DEPTH_FOR_THREAD != 0 { + if (self.depth + 1) % depth_threshold != 0 { let vm_factory = self.vm_factory; let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer); trace!(target: "executive", "ext.schedule.have_delegate_call: {}", ext.schedule().have_delegate_call); diff --git a/util/io/src/lib.rs b/util/io/src/lib.rs index b2a16e19bb2..082192dfaf0 100644 --- a/util/io/src/lib.rs +++ b/util/io/src/lib.rs @@ -68,6 +68,8 @@ mod panics; use mio::{EventLoop, Token}; use std::fmt; +pub use worker::LOCAL_STACK_SIZE; + #[derive(Debug)] /// IO Error pub enum IoError { diff --git a/util/io/src/worker.rs b/util/io/src/worker.rs index 223f2ac0efe..f4f63919f14 100644 --- a/util/io/src/worker.rs +++ b/util/io/src/worker.rs @@ -22,11 +22,19 @@ use crossbeam::sync::chase_lev; use service::{HandlerId, IoChannel, IoContext}; use IoHandler; use panics::*; +use std::cell::Cell; use std::sync::{Condvar as SCondvar, Mutex as SMutex}; const STACK_SIZE: usize = 16*1024*1024; +thread_local! { + /// Stack size + /// Should be modified if it is changed in Rust since it is no way + /// to know or get it + pub static LOCAL_STACK_SIZE: Cell = Cell::new(::std::env::var("RUST_MIN_STACK").ok().and_then(|s| s.parse().ok()).unwrap_or(2 * 1024 * 1024)); +} + pub enum WorkType { Readable, Writable, @@ -70,6 +78,7 @@ impl Worker { }; worker.thread = Some(thread::Builder::new().stack_size(STACK_SIZE).name(format!("IO Worker #{}", index)).spawn( move || { + LOCAL_STACK_SIZE.with(|val| val.set(STACK_SIZE)); panic_handler.catch_panic(move || { Worker::work_loop(stealer, channel.clone(), wait, wait_mutex.clone(), deleting) }).unwrap() From be2307f227c2b2802fd322a58b5722719a2c02f7 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 6 Oct 2016 11:50:54 +0300 Subject: [PATCH 3/5] right value --- ethcore/src/executive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index b970c1b12b8..973b588fb42 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -28,7 +28,7 @@ pub use types::executed::{Executed, ExecutionResult}; /// Roughly estimate what stack size each level of evm depth will use /// TODO [todr] We probably need some more sophisticated calculations here (limit on my machine 132) /// Maybe something like here: `https://github.com/ethereum/libethereum/blob/4db169b8504f2b87f7d5a481819cfb959fc65f6c/libethereum/ExtVM.cpp` -const STACK_SIZE_PER_DEPTH: usize = 256*1024; +const STACK_SIZE_PER_DEPTH: usize = 16*1024; /// Returns new address created from address and given nonce. pub fn contract_address(address: &Address, nonce: &U256) -> Address { From 841401e6fe80c7f9a9c289cb822aad0428b5c822 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Thu, 6 Oct 2016 13:38:48 +0300 Subject: [PATCH 4/5] 24kb size --- ethcore/src/executive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 973b588fb42..d83d7a9c609 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -28,7 +28,7 @@ pub use types::executed::{Executed, ExecutionResult}; /// Roughly estimate what stack size each level of evm depth will use /// TODO [todr] We probably need some more sophisticated calculations here (limit on my machine 132) /// Maybe something like here: `https://github.com/ethereum/libethereum/blob/4db169b8504f2b87f7d5a481819cfb959fc65f6c/libethereum/ExtVM.cpp` -const STACK_SIZE_PER_DEPTH: usize = 16*1024; +const STACK_SIZE_PER_DEPTH: usize = 24*1024; /// Returns new address created from address and given nonce. pub fn contract_address(address: &Address, nonce: &U256) -> Address { From 7b956a8bdfbce2353f6db50b881d4289d6264c74 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Thu, 6 Oct 2016 14:26:36 +0300 Subject: [PATCH 5/5] some stack reduction --- ethcore/src/executive.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index d83d7a9c609..97bbafed804 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -149,12 +149,13 @@ impl<'a> Executive<'a> { // TODO: we might need bigints here, or at least check overflows. let balance = self.state.balance(&sender); - let gas_cost = U512::from(t.gas) * U512::from(t.gas_price); + let gas_cost = t.gas.full_mul(t.gas_price); let total_cost = U512::from(t.value) + gas_cost; // avoid unaffordable transactions - if U512::from(balance) < total_cost { - return Err(From::from(ExecutionError::NotEnoughCash { required: total_cost, got: U512::from(balance) })); + let balance512 = U512::from(balance); + if balance512 < total_cost { + return Err(From::from(ExecutionError::NotEnoughCash { required: total_cost, got: balance512 })); } // NOTE: there can be no invalid transactions from this point. @@ -416,7 +417,7 @@ impl<'a> Executive<'a> { // real ammount to refund let gas_left_prerefund = match result { Ok(x) => x, _ => 0.into() }; - let refunded = cmp::min(refunds_bound, (t.gas - gas_left_prerefund) / U256::from(2)); + let refunded = cmp::min(refunds_bound, (t.gas - gas_left_prerefund) >> 1); let gas_left = gas_left_prerefund + refunded; let gas_used = t.gas - gas_left;