From ec8d0e582ccbef46371238cb5b5f1e4622b657f8 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 18 Apr 2014 14:49:43 +0100 Subject: [PATCH] Attempt to create less garbage for getaddr calls. We make ka.na immutable in the address manager. Whenever we would update the structure we replace it with a new copy. This beats making a copy of all addresses once per getaddr command (max is just over 23000 we would be copying, compared to at most 2000 copies on a new getaddr that has all addresses we know with newer dates). --- addrmanager.go | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/addrmanager.go b/addrmanager.go index 21ea3a71..ba96a482 100644 --- a/addrmanager.go +++ b/addrmanager.go @@ -27,10 +27,6 @@ import ( ) const ( - // maxAddresses identifies the maximum number of addresses that the - // address manager will track. - maxAddresses = 2500 - // needAddressThreshold is the number of addresses under which the // address manager will claim to need more addresses. needAddressThreshold = 1000 @@ -115,13 +111,20 @@ func (a *AddrManager) updateAddress(netAddr, srcAddr *btcwire.NetAddress) { ka := a.find(netAddr) if ka != nil { // TODO(oga) only update adresses periodically. - // Update the last seen time. - if netAddr.Timestamp.After(ka.na.Timestamp) { - ka.na.Timestamp = netAddr.Timestamp - } + // Update the last seen time and services. + // note that to prevent causing excess garbage on getaddr + // messages the netaddresses in addrmaanger are *immutable*, + // if we need to change them then we replace the pointer with a + // new copy so that we don't have to copy every na for getaddr. + if netAddr.Timestamp.After(ka.na.Timestamp) || + (ka.na.Services&netAddr.Services) != + netAddr.Services { - // Update services. - ka.na.AddService(netAddr.Services) + naCopy := *ka.na + naCopy.Timestamp = netAddr.Timestamp + naCopy.AddService(netAddr.Services) + ka.na = &naCopy + } // If already in tried, we have nothing to do here. if ka.tried { @@ -714,8 +717,7 @@ func (a *AddrManager) AddressCache() []*btcwire.NetAddress { i := 0 // Iteration order is undefined here, but we randomise it anyway. for _, v := range a.addrIndex { - copyNa := *v.na - allAddr[i] = ©Na + allAddr[i] = v.na i++ } // Fisher-Yates shuffle the array @@ -937,7 +939,10 @@ func (a *AddrManager) Connected(addr *btcwire.NetAddress) { // so. now := time.Now() if now.After(ka.na.Timestamp.Add(time.Minute * 20)) { - ka.na.Timestamp = time.Now() + // ka.na is immutable, so replace it. + naCopy := *ka.na + naCopy.Timestamp = time.Now() + ka.na = &naCopy } } @@ -955,7 +960,9 @@ func (a *AddrManager) Good(addr *btcwire.NetAddress) { now := time.Now() ka.lastsuccess = now ka.lastattempt = now - ka.na.Timestamp = now + naCopy := *ka.na + naCopy.Timestamp = time.Now() + ka.na = &naCopy ka.attempts = 0 // move to tried set, optionally evicting other addresses if neeed.