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 (
// 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] = &copyNa
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.