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).
This commit is contained in:
Owain G. Ainsworth 2014-04-18 14:49:43 +01:00
parent 08377c21e2
commit ec8d0e582c

View file

@ -27,10 +27,6 @@ import (
) )
const ( 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 // needAddressThreshold is the number of addresses under which the
// address manager will claim to need more addresses. // address manager will claim to need more addresses.
needAddressThreshold = 1000 needAddressThreshold = 1000
@ -115,13 +111,20 @@ func (a *AddrManager) updateAddress(netAddr, srcAddr *btcwire.NetAddress) {
ka := a.find(netAddr) ka := a.find(netAddr)
if ka != nil { if ka != nil {
// TODO(oga) only update adresses periodically. // TODO(oga) only update adresses periodically.
// Update the last seen time. // Update the last seen time and services.
if netAddr.Timestamp.After(ka.na.Timestamp) { // note that to prevent causing excess garbage on getaddr
ka.na.Timestamp = netAddr.Timestamp // 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. naCopy := *ka.na
ka.na.AddService(netAddr.Services) naCopy.Timestamp = netAddr.Timestamp
naCopy.AddService(netAddr.Services)
ka.na = &naCopy
}
// If already in tried, we have nothing to do here. // If already in tried, we have nothing to do here.
if ka.tried { if ka.tried {
@ -714,8 +717,7 @@ func (a *AddrManager) AddressCache() []*btcwire.NetAddress {
i := 0 i := 0
// Iteration order is undefined here, but we randomise it anyway. // Iteration order is undefined here, but we randomise it anyway.
for _, v := range a.addrIndex { for _, v := range a.addrIndex {
copyNa := *v.na allAddr[i] = v.na
allAddr[i] = &copyNa
i++ i++
} }
// Fisher-Yates shuffle the array // Fisher-Yates shuffle the array
@ -937,7 +939,10 @@ func (a *AddrManager) Connected(addr *btcwire.NetAddress) {
// so. // so.
now := time.Now() now := time.Now()
if now.After(ka.na.Timestamp.Add(time.Minute * 20)) { 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() now := time.Now()
ka.lastsuccess = now ka.lastsuccess = now
ka.lastattempt = now ka.lastattempt = now
ka.na.Timestamp = now naCopy := *ka.na
naCopy.Timestamp = time.Now()
ka.na = &naCopy
ka.attempts = 0 ka.attempts = 0
// move to tried set, optionally evicting other addresses if neeed. // move to tried set, optionally evicting other addresses if neeed.