utxoset: Fix parallel script checking to use only as many threads as CPUs

This commit is contained in:
Andrew Poelstra 2014-08-14 17:14:32 -07:00
parent fc04462682
commit c28c261b74
1 changed files with 36 additions and 27 deletions

View File

@ -18,8 +18,10 @@
//! index of UTXOs. //! index of UTXOs.
//! //!
use std::cmp;
use std::collections::HashMap; use std::collections::HashMap;
use std::mem; use std::mem;
use std::os::num_cpus;
use std::sync::Future; use std::sync::Future;
use blockdata::transaction::{Transaction, TxOut}; use blockdata::transaction::{Transaction, TxOut};
@ -207,38 +209,45 @@ impl UtxoSet {
let mut future_vec = Vec::with_capacity(block.txdata.len() - 1); let mut future_vec = Vec::with_capacity(block.txdata.len() - 1);
// skip the genesis since we don't validate this script. (TODO this might // skip the genesis since we don't validate this script. (TODO this might
// be a consensus bug since we don't even check that the opcodes make sense.) // be a consensus bug since we don't even check that the opcodes make sense.)
for tx in block.txdata.iter().skip(1) { let n_threads = cmp::min(block.txdata.len() - 1, num_cpus());
for j in range(0, n_threads) {
let n_elems = block.txdata.len() - 1;
let start = 1 + j * n_elems / n_threads;
let end = cmp::min(n_elems, 1 + (j + 1) * n_elems / n_threads);
let s = self as *mut _ as *const UtxoSet; let s = self as *mut _ as *const UtxoSet;
let tx = tx as *const _; let txes = &block.txdata as *const _;
future_vec.push(Future::spawn(proc() { future_vec.push(Future::spawn(proc() {
let tx = unsafe {&*tx}; let txes = unsafe {&*txes};
for (n, input) in tx.input.iter().enumerate() { for tx in txes.slice(start, end).iter() {
let txo = unsafe { (*s).get_utxo(input.prev_hash, input.prev_index) }; for (n, input) in tx.input.iter().enumerate() {
match txo { let txo = unsafe { (*s).get_utxo(input.prev_hash, input.prev_index) };
Some(txo) => { match txo {
let mut stack = Vec::with_capacity(6); Some(txo) => {
if input.script_sig.evaluate(&mut stack, Some((tx, n))).is_err() { let mut stack = Vec::with_capacity(6);
println!("txid was {}", tx.bitcoin_hash()); if input.script_sig.evaluate(&mut stack, Some((tx, n))).is_err() {
return false; println!("txid was {}", tx.bitcoin_hash());
} return false;
if txo.script_pubkey.evaluate(&mut stack, Some((tx, n))).is_err() { }
println!("txid was {}", tx.bitcoin_hash()); if txo.script_pubkey.evaluate(&mut stack, Some((tx, n))).is_err() {
return false; println!("txid was {}", tx.bitcoin_hash());
} return false;
match stack.pop() { }
Some(v) => { match stack.pop() {
if !read_scriptbool(v.as_slice()) { Some(v) => {
use serialize::json::ToJson; if !read_scriptbool(v.as_slice()) {
println!("txid was {}", tx.bitcoin_hash()); use serialize::json::ToJson;
println!("tx was {}", tx.to_json().to_string()); println!("txid was {}", tx.bitcoin_hash());
println!("script ended with stack {}", stack); println!("tx was {}", tx.to_json().to_string());
return false; println!("script ended with stack {}", stack);
} return false;
}
}
None => { return false; }
} }
None => { return false; }
} }
None => { return false; }
} }
None => { return false; }
} }
} }
true true