Discovery performance optimization (#2972)

This commit is contained in:
Arkadiy Paronyan 2016-10-29 17:38:34 +02:00 committed by Gav Wood
parent 3a6c1c377c
commit 99d6d87e78
3 changed files with 14 additions and 8 deletions

View File

View File

@ -57,6 +57,7 @@ pub struct NodeEntry {
pub struct BucketEntry { pub struct BucketEntry {
pub address: NodeEntry, pub address: NodeEntry,
pub id_hash: H256,
pub timeout: Option<u64>, pub timeout: Option<u64>,
} }
@ -85,6 +86,7 @@ struct Datagramm {
pub struct Discovery { pub struct Discovery {
id: NodeId, id: NodeId,
id_hash: H256,
secret: Secret, secret: Secret,
public_endpoint: NodeEndpoint, public_endpoint: NodeEndpoint,
udp_socket: UdpSocket, udp_socket: UdpSocket,
@ -109,6 +111,7 @@ impl Discovery {
let socket = UdpSocket::bound(&listen).expect("Error binding UDP socket"); let socket = UdpSocket::bound(&listen).expect("Error binding UDP socket");
Discovery { Discovery {
id: key.public().clone(), id: key.public().clone(),
id_hash: key.public().sha3(),
secret: key.secret().clone(), secret: key.secret().clone(),
public_endpoint: public, public_endpoint: public,
token: token, token: token,
@ -150,8 +153,9 @@ impl Discovery {
fn update_node(&mut self, e: NodeEntry) { fn update_node(&mut self, e: NodeEntry) {
trace!(target: "discovery", "Inserting {:?}", &e); trace!(target: "discovery", "Inserting {:?}", &e);
let id_hash = e.id.sha3();
let ping = { let ping = {
let mut bucket = self.node_buckets.get_mut(Discovery::distance(&self.id, &e.id) as usize).unwrap(); let mut bucket = self.node_buckets.get_mut(Discovery::distance(&self.id_hash, &id_hash) as usize).unwrap();
let updated = if let Some(node) = bucket.nodes.iter_mut().find(|n| n.address.id == e.id) { let updated = if let Some(node) = bucket.nodes.iter_mut().find(|n| n.address.id == e.id) {
node.address = e.clone(); node.address = e.clone();
node.timeout = None; node.timeout = None;
@ -159,7 +163,7 @@ impl Discovery {
} else { false }; } else { false };
if !updated { if !updated {
bucket.nodes.push_front(BucketEntry { address: e, timeout: None }); bucket.nodes.push_front(BucketEntry { address: e, timeout: None, id_hash: id_hash, });
} }
if bucket.nodes.len() > BUCKET_SIZE { if bucket.nodes.len() > BUCKET_SIZE {
@ -174,7 +178,7 @@ impl Discovery {
} }
fn clear_ping(&mut self, id: &NodeId) { fn clear_ping(&mut self, id: &NodeId) {
let mut bucket = self.node_buckets.get_mut(Discovery::distance(&self.id, id) as usize).unwrap(); let mut bucket = self.node_buckets.get_mut(Discovery::distance(&self.id_hash, &id.sha3()) as usize).unwrap();
if let Some(node) = bucket.nodes.iter_mut().find(|n| &n.address.id == id) { if let Some(node) = bucket.nodes.iter_mut().find(|n| &n.address.id == id) {
node.timeout = None; node.timeout = None;
} }
@ -224,8 +228,8 @@ impl Discovery {
self.discovery_round += 1; self.discovery_round += 1;
} }
fn distance(a: &NodeId, b: &NodeId) -> u32 { fn distance(a: &H256, b: &H256) -> u32 {
let d = a.sha3() ^ b.sha3(); let d = *a ^ *b;
let mut ret:u32 = 0; let mut ret:u32 = 0;
for i in 0..32 { for i in 0..32 {
let mut v: u8 = d[i]; let mut v: u8 = d[i];
@ -279,11 +283,12 @@ impl Discovery {
fn nearest_node_entries(target: &NodeId, buckets: &[NodeBucket]) -> Vec<NodeEntry> { fn nearest_node_entries(target: &NodeId, buckets: &[NodeBucket]) -> Vec<NodeEntry> {
let mut found: BTreeMap<u32, Vec<&NodeEntry>> = BTreeMap::new(); let mut found: BTreeMap<u32, Vec<&NodeEntry>> = BTreeMap::new();
let mut count = 0; let mut count = 0;
let target_hash = target.sha3();
// Sort nodes by distance to target // Sort nodes by distance to target
for bucket in buckets { for bucket in buckets {
for node in &bucket.nodes { for node in &bucket.nodes {
let distance = Discovery::distance(target, &node.address.id); let distance = Discovery::distance(&target_hash, &node.id_hash);
found.entry(distance).or_insert_with(Vec::new).push(&node.address); found.entry(distance).or_insert_with(Vec::new).push(&node.address);
if count == BUCKET_SIZE { if count == BUCKET_SIZE {
// delete the most distant element // delete the most distant element
@ -626,7 +631,8 @@ mod tests {
for _ in 0..(16 + 10) { for _ in 0..(16 + 10) {
buckets[0].nodes.push_back(BucketEntry { buckets[0].nodes.push_back(BucketEntry {
address: NodeEntry { id: NodeId::new(), endpoint: ep.clone() }, address: NodeEntry { id: NodeId::new(), endpoint: ep.clone() },
timeout: None timeout: None,
id_hash: NodeId::new().sha3(),
}); });
} }
let nearest = Discovery::nearest_node_entries(&NodeId::new(), &buckets); let nearest = Discovery::nearest_node_entries(&NodeId::new(), &buckets);

View File

@ -61,7 +61,7 @@ const SYS_TIMER: usize = LAST_SESSION + 1;
// Timeouts // Timeouts
const MAINTENANCE_TIMEOUT: u64 = 1000; const MAINTENANCE_TIMEOUT: u64 = 1000;
const DISCOVERY_REFRESH_TIMEOUT: u64 = 7200; const DISCOVERY_REFRESH_TIMEOUT: u64 = 60_000;
const DISCOVERY_ROUND_TIMEOUT: u64 = 300; const DISCOVERY_ROUND_TIMEOUT: u64 = 300;
const NODE_TABLE_TIMEOUT: u64 = 300_000; const NODE_TABLE_TIMEOUT: u64 = 300_000;