Skip to content

Conversation

naumenkogs
Copy link
Member

@naumenkogs naumenkogs commented Oct 16, 2019

We should allocate memory for addrKnown filter only for those peers which are expected to participate in address relay.

Currently, we do it for all peers (including SPV and block-relay-only), which results in extra RAM where it's not needed.

Upd:
In future, we would still allow SPVs to ask for addrs, so allocation still will be done by default.
However, they will be able to opt-out via this proposal and then we could save some more memory.
This PR still saves memory for block-relay-only peers immediately after merging.

Copy link
Member

@maflcko maflcko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only relevant for nodes that accept incoming connections? And those nodes are assumed to have a ton of resources. Though, it can't hurt to same some bits, if it can be done conveniently.

@naumenkogs
Copy link
Member Author

This is only relevant for nodes that accept incoming connections?

Not really. To all the nodes with block-relay-only peers.

@naumenkogs naumenkogs force-pushed the addr_relay_optimization_4 branch from e65af6e to 90407e6 Compare October 16, 2019 18:10
@GChuf
Copy link
Contributor

GChuf commented Oct 16, 2019

Concept ACK.
Respectfully, assuming nodes have a ton of resources is dangerous - every optimization is potentially important (talking as a multiple nodes operator here).

@@ -115,9 +115,6 @@ class CBloomFilter
class CRollingBloomFilter
{
public:
// A random bloom filter calls GetRand() at creation time.
// Don't create global CRollingBloomFilter objects, as they may be
// constructed before the randomizer is properly initialized.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note to other reviewers: The comment no longer applies after 05fde14

@maflcko
Copy link
Member

maflcko commented Oct 16, 2019

I did some testing with massif, and this saves about 263.3 KiB for 10 peers that connect, but don't have address relay enabled. Note that the tx relay rolling bloom filter takes up 5.1 MB, which sort of dwarfs the gains here.

ACK 90407e6

Show signature and timestamp

Signature:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

ACK 90407e6fab74cd849d474f0c5dea19b9954d4196
-----BEGIN PGP SIGNATURE-----

iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
pUj6UAv/S2YrC/LwxnSHSRI8/CTG/D4keXVDin7cH//FaaKlFa3yLaiDU6Fiwnj0
VuaOdGdxxfxrBRmFI3afL1mpNwbA24ny7pdrHbMVQJ6vLnPWOyXespyT6M7idrLZ
xYP2yt7RIufDgLkLV15PlI4YahsTo/fnLfMs3bOA+3/zc8g3q4YLxThBrk5P8fZJ
iYaM3uENRl+/7Ny5N1Wfkdl8tXDqbC6/2pYwBI7BNTPSrTOdERymW5EHvfG/IWSE
v8VELXxdt2LBWLMODEz2Q4Huib5MeoYJenZvGwnauOun17gHSYi0Ksy8Q8OA0MTU
IYZ8J4olbEjJsWlOmKeS774r+s4nf4iwSIw0lx/58ITLECsuGxJbsquYTyB+vP6q
RBaNFBoTHshue1c7nH/aHYftfdlNThc+d3Rqas78mIGBFbynJ3a10S1cl37TkApy
oyDzr7BnQV7ZdUV0WcVudrNnBVRAky7PmOndvAbStI79TLU5GwGXessK/7lgZibV
TcsFz/y0
=gtc/
-----END PGP SIGNATURE-----

Timestamp of file with hash 283bf14cba6f831bf8491da4b8a98092329778b2783d5ed8f6bbf7462772ff0f -

@GChuf
Copy link
Contributor

GChuf commented Oct 16, 2019

@MarcoFalke so, the result is actually ... an extra ~4.8 MB RAM usage?

@naumenkogs
Copy link
Member Author

@GChuf no, Marco's just saying that this update probably saves only 5% of the overall memory we dedicate per peer (or maybe even a bit less due to other stuff).

My code does not introduce any extra overhead.

@naumenkogs naumenkogs force-pushed the addr_relay_optimization_4 branch from 26802de to 090b75c Compare October 16, 2019 21:06
@GChuf
Copy link
Contributor

GChuf commented Oct 16, 2019

@naumenkogs thanks for clarifying. Just had to ask because I wasn't sure I understand.
Anyway like I said, I think every improvement is important, no matter how small.

@maflcko
Copy link
Member

maflcko commented Oct 17, 2019

re-ACK 090b75c

Show signature and timestamp

Signature:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

re-ACK 090b75c14be6b9ba2efe38a17d141c6e6af575cb
-----BEGIN PGP SIGNATURE-----

iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
pUjXJgwAqkfJNeBc+WA9VZaMmaiR1ZLmyt/oKW8fcehMV1FS0Vf0sm32JsuUYsqH
t/E4L4Hg2lG/7d+wNmQcwXW+gPYAubpBDkZjJw2jCjqptKim9wWnUa1/twgpCfFZ
/bBowXhvRuI5wVZhlP7GyKLFdSZqp16goEqYi1IbpjROUFHIvEqXexs5FKmNK9EF
ySMMDLgazsmCYsVNtWOh8GbxUuALPX0Sbh3Wv9Lt9YFSVwRFim+b3emO8nGmovSI
wkclHFUpmTpYEOmZC+B+/ZR2P9EdFkWzUIgoqiFpkEHCqgMowjF2lGPiMqvcbO6i
m/6zWTLtgMxNm1VG2HrAhqbj81NzqO6BYH3T1sO959aSVdSu+VDi5xd3gh6jrpX5
WNqxIAWfWu0ISnnWtz0kcTRjLcpqI0QQfzcUXeSWfodS3q4pRNV4abvo8Hb8b6/Q
TLJuGRFTQbMGSF7eU9FUDgV8NpCzXbu7Pu1L+FgDgBQfpxgYvGXyitgfaGPLX2TJ
ZrlPc95E
=Toyw
-----END PGP SIGNATURE-----

Timestamp of file with hash 7806780bf7d730ec30b25732f4026f506b9c7fbff0e3b47a2803142242aea1b6 -

@DrahtBot
Copy link
Contributor

DrahtBot commented Oct 17, 2019

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

No conflicts as of last run.

@laanwj
Copy link
Member

laanwj commented Oct 24, 2019

I think there should be NULL pointer checks or assertions at the locations that now use m_addr_known, just in case.

@laanwj
Copy link
Member

laanwj commented Oct 28, 2019

ACK a552e84

@maflcko
Copy link
Member

maflcko commented Oct 28, 2019

re-ACK a552e84

Show signature and timestamp

Signature:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

re-ACK a552e8477c5bcd22a5457f4f73a2fd6db8acd2c2
-----BEGIN PGP SIGNATURE-----

iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
pUibEQwAr22ss9KohgyamVhNe0/FeIO1vHR9dSdSknvqKD6DoGkCzgctdooQJhiW
4QKzssocyI/i1Jbg9O3Ckl14IcfFyhnYBLmA+u01Oqxp/rEWtVPHS32mw7xj+LPk
0ABS7uZSEdzkFcupONG/4zFoC60LokZi1DszYUNRfpxRbgMFlWSJtaMuBJn5Bp8y
tq2Sn9h2IojdUyHvdWpwpMFHmN6fP0PORI6XvHVSIB7Vi1c7+sAuDOaEVS7E6PW2
cPuX8VV/rYO0K67bmDY4tS2r07UEuBCwDS59NxHDoGpVBH0fKINbMEhu0ETNIPZ9
avrIkaaYcehiv5qn6J3ocpZT4wnoAXjes+GMcCTbnhdB+2+fWlk+mWYRFTYT7UEg
Q06HINGY7amistUcZRNrScIDWfsReoxMx7HihrcxcYgpT4t2OVWYtRewDx1f99iE
ZO4xfqgDd2S/grEsV5rp0Nv6Bb6D0MIG2kjYg3kCG2h1ASPHvcWLsAcupDHajIpy
rPPybuft
=/ueI
-----END PGP SIGNATURE-----

Timestamp of file with hash 0ab34613ea38e4bc0035a5ffbe8b4c57fd1cbe756bb708ed3a66369644787338 -

@dongcarl
Copy link
Contributor

ACK a552e84


Potential Followups

  • Add comments to these functions that describe their assumptions about preconditions (pto->IsAddrRelayPeer())
  • Perhaps tweak the API so that there doesn't need to be preconditions like this (no idea how to do)

Review Notes

Looked through to see that the new asserts won't crash the daemon where previously it might have been a silent failure...

The assert in bool PeerLogicValidation::SendMessages(CNode* pto) is guaranteed to succeed because of the pto->IsAddrRelayPeer() check a few lines up:

bitcoin/src/net_processing.cpp

Lines 3560 to 3564 in a552e84

if (pto->IsAddrRelayPeer() && pto->nNextAddrSend < nNow) {
pto->nNextAddrSend = PoissonNextSend(nNow, AVG_ADDRESS_BROADCAST_INTERVAL);
std::vector<CAddress> vAddr;
vAddr.reserve(pto->vAddrToSend.size());
assert(pto->m_addr_known);

The assert in void AddAddressKnown(const CAddress& _addr) is guaranteed to succeed because its only call-site is pre-empted by an early return if !pfrom->IsAddrRelayPeer()

bitcoin/src/net_processing.cpp

Lines 2101 to 2128 in a552e84

if (!pfrom->IsAddrRelayPeer()) {
return true;
}
if (vAddr.size() > 1000)
{
LOCK(cs_main);
Misbehaving(pfrom->GetId(), 20, strprintf("message addr size() = %u", vAddr.size()));
return false;
}
// Store the new addresses
std::vector<CAddress> vAddrOk;
int64_t nNow = GetAdjustedTime();
int64_t nSince = nNow - 10 * 60;
for (CAddress& addr : vAddr)
{
if (interruptMsgProc)
return true;
// We only bother storing full nodes, though this may include
// things which we would not make an outbound connection to, in
// part because we may make feeler connections to them.
if (!MayHaveUsefulAddressDB(addr.nServices) && !HasAllDesirableServiceFlags(addr.nServices))
continue;
if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
addr.nTime = nNow - 5 * 24 * 60 * 60;
pfrom->AddAddressKnown(addr);

For the assert in void PushAddress(const CAddress& _addr, FastRandomContext &insecure_rand), there are 5 call-sites:

1 of them in static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connman), where it is called in pushfunc, which is only called on CNode *s that are pnode->IsAddrRelayPeer()

bitcoin/src/net_processing.cpp

Lines 1326 to 1345 in a552e84

auto sortfunc = [&best, &hasher, nRelayNodes](CNode* pnode) {
if (pnode->nVersion >= CADDR_TIME_VERSION && pnode->IsAddrRelayPeer()) {
uint64_t hashKey = CSipHasher(hasher).Write(pnode->GetId()).Finalize();
for (unsigned int i = 0; i < nRelayNodes; i++) {
if (hashKey > best[i].first) {
std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
best[i] = std::make_pair(hashKey, pnode);
break;
}
}
}
};
auto pushfunc = [&addr, &best, nRelayNodes, &insecure_rand] {
for (unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
best[i].second->PushAddress(addr, insecure_rand);
}
};
connman->ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));

3 of them in bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc) where they are guarded by pfrom->IsAddrRelayPeer()

bitcoin/src/net_processing.cpp

Lines 1985 to 1999 in a552e84

if (!pfrom->fInbound && pfrom->IsAddrRelayPeer())
{
// Advertise our address
if (fListen && !::ChainstateActive().IsInitialBlockDownload())
{
CAddress addr = GetLocalAddress(&pfrom->addr, pfrom->GetLocalServices());
FastRandomContext insecure_rand;
if (addr.IsRoutable())
{
LogPrint(BCLog::NET, "ProcessMessages: advertising address %s\n", addr.ToString());
pfrom->PushAddress(addr, insecure_rand);
} else if (IsPeerAddrLocalGood(pfrom)) {
addr.SetIP(addrMe);
LogPrint(BCLog::NET, "ProcessMessages: advertising address %s\n", addr.ToString());
pfrom->PushAddress(addr, insecure_rand);

bitcoin/src/net_processing.cpp

Lines 2964 to 2982 in a552e84

if (!pfrom->IsAddrRelayPeer()) {
LogPrint(BCLog::NET, "Ignoring \"getaddr\" from block-relay-only connection. peer=%d\n", pfrom->GetId());
return true;
}
// Only send one GetAddr response per connection to reduce resource waste
// and discourage addr stamping of INV announcements.
if (pfrom->fSentAddr) {
LogPrint(BCLog::NET, "Ignoring repeated \"getaddr\". peer=%d\n", pfrom->GetId());
return true;
}
pfrom->fSentAddr = true;
pfrom->vAddrToSend.clear();
std::vector<CAddress> vAddr = connman->GetAddresses();
FastRandomContext insecure_rand;
for (const CAddress &addr : vAddr) {
if (!g_banman->IsBanned(addr)) {
pfrom->PushAddress(addr, insecure_rand);

The last one in void AdvertiseLocal(CNode *pnode), whose only call-site is guarded by a pto->IsAddrRelayPeer() in bool PeerLogicValidation::SendMessages(CNode* pto)

bitcoin/src/net_processing.cpp

Lines 3552 to 3553 in a552e84

if (pto->IsAddrRelayPeer() && !::ChainstateActive().IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
AdvertiseLocal(pto);

@naumenkogs
Copy link
Member Author

naumenkogs commented Oct 30, 2019

I agree. At least right now m_addr_known strongly correlates with m_addr_relay_peer. We can merge 2 variables.
It's also very unlikely that these 2 variables would ever mean different things.

Co-authored-by: MarcoFalke <falke.marco@gmail.com>
@naumenkogs naumenkogs force-pushed the addr_relay_optimization_4 branch from ccf5aa7 to b6d2183 Compare October 31, 2019 17:42
@luke-jr
Copy link
Member

luke-jr commented Nov 4, 2019

This is only relevant for nodes that accept incoming connections? And those nodes are assumed to have a ton of resources.

What? No. All nodes ideally should accept incoming connections, it doesn't imply "a ton of resources"!

maflcko pushed a commit that referenced this pull request Nov 4, 2019
…'t need it

b6d2183 Minor refactoring to remove implied m_addr_relay_peer. (User)
a552e84 added asserts to check m_addr_known when it's used (User)
090b75c p2p: Avoid allocating memory for addrKnown where we don't need it (User)

Pull request description:

  We should allocate memory for addrKnown filter only for those peers which are expected to participate in address relay.

  Currently, we do it for all peers (including SPV and block-relay-only),  which results in extra RAM where it's not needed.

  Upd:
  In future, we would still allow SPVs to ask for addrs, so allocation still will be done by default.
  However, they will be able to opt-out via [this proposal](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-October/017428.html) and then we could save some more memory.
  This PR still saves memory for block-relay-only peers immediately after merging.

Top commit has no ACKs.

Tree-SHA512: e84d93b2615556d466f5ca0e543580fde763911a3bfea3127c493ddfaba8f05c8605cb94ff795d165af542b594400995a2c51338185c298581408687e7812463
@maflcko maflcko merged commit b6d2183 into bitcoin:master Nov 4, 2019
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Nov 7, 2019
… we don't need it

b6d2183 Minor refactoring to remove implied m_addr_relay_peer. (User)
a552e84 added asserts to check m_addr_known when it's used (User)
090b75c p2p: Avoid allocating memory for addrKnown where we don't need it (User)

Pull request description:

  We should allocate memory for addrKnown filter only for those peers which are expected to participate in address relay.

  Currently, we do it for all peers (including SPV and block-relay-only),  which results in extra RAM where it's not needed.

  Upd:
  In future, we would still allow SPVs to ask for addrs, so allocation still will be done by default.
  However, they will be able to opt-out via [this proposal](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-October/017428.html) and then we could save some more memory.
  This PR still saves memory for block-relay-only peers immediately after merging.

Top commit has no ACKs.

Tree-SHA512: e84d93b2615556d466f5ca0e543580fde763911a3bfea3127c493ddfaba8f05c8605cb94ff795d165af542b594400995a2c51338185c298581408687e7812463
@laanwj
Copy link
Member

laanwj commented May 25, 2020

@naumenkogs Please set a different name than User in your commits if you want to be credited correctly in the future (I'll fix it up manually for 0.20).

commit b6d2183858975abc961207c125c15791e531edcc
Author:     User <n…@gmail.com>
AuthorDate: Thu Oct 31 13:42:02 2019 -0400
Commit:     User <n…@gmail.com>
CommitDate: Thu Oct 31 13:42:02 2019 -0400

    Minor refactoring to remove implied m_addr_relay_peer. 
    Co-authored-by: MarcoFalke <falke.marco@gmail.com>

jasonbcox pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Nov 3, 2020
Summary:
> We should allocate memory for addrKnown filter only for those peers which are expected to participate in address relay.
>
> Currently, we do it for all peers (including SPV and block-relay-only), which results in extra RAM where it's not needed.
>
> Upd:
> In future, we would still allow SPVs to ask for addrs, so allocation still will be done by default.
> However, they will be able to opt-out via this proposal and then we could save some more memory.
> This PR still saves memory for block-relay-only peers immediately after merging.

We use `std::make_unique` instead of `MakeUnique` (see D2463)

This is a backport of Core [[bitcoin/bitcoin#17164 | PR17164]] [1/3]
bitcoin/bitcoin@090b75c

Test Plan: `ninja all check-all`

Reviewers: O1 Bitcoin ABC, #bitcoin_abc, Fabien

Reviewed By: O1 Bitcoin ABC, #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D8238
jasonbcox pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Nov 3, 2020
Summary:
This is a backport of Core  [[bitcoin/bitcoin#17164 | PR17164]]  [2/3]
bitcoin/bitcoin@a552e84

Depends on D8238

Test Plan: `ninja all check-all`

Reviewers: O1 Bitcoin ABC, #bitcoin_abc, Fabien

Reviewed By: O1 Bitcoin ABC, #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D8239
jasonbcox pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Nov 3, 2020
Summary:
Co-authored-by: MarcoFalke <falke.marco@gmail.com>

This is a backport of Core [[bitcoin/bitcoin#17164 | PR17164]] [3/3]
bitcoin/bitcoin@b6d2183
Depends on D8239

Test Plan: `ninja all check-all`

Reviewers: O1 Bitcoin ABC, #bitcoin_abc, deadalnix

Reviewed By: O1 Bitcoin ABC, #bitcoin_abc, deadalnix

Differential Revision: https://reviews.bitcoinabc.org/D8240
sidhujag pushed a commit to syscoin-core/syscoin that referenced this pull request Nov 10, 2020
… we don't need it

b6d2183 Minor refactoring to remove implied m_addr_relay_peer. (User)
a552e84 added asserts to check m_addr_known when it's used (User)
090b75c p2p: Avoid allocating memory for addrKnown where we don't need it (User)

Pull request description:

  We should allocate memory for addrKnown filter only for those peers which are expected to participate in address relay.

  Currently, we do it for all peers (including SPV and block-relay-only),  which results in extra RAM where it's not needed.

  Upd:
  In future, we would still allow SPVs to ask for addrs, so allocation still will be done by default.
  However, they will be able to opt-out via [this proposal](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-October/017428.html) and then we could save some more memory.
  This PR still saves memory for block-relay-only peers immediately after merging.

Top commit has no ACKs.

Tree-SHA512: e84d93b2615556d466f5ca0e543580fde763911a3bfea3127c493ddfaba8f05c8605cb94ff795d165af542b594400995a2c51338185c298581408687e7812463
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants