Skip to content

Conversation

brunoerg
Copy link
Contributor

@brunoerg brunoerg commented Mar 6, 2024

GetAddr returns all or many randomly selected addresses, it uses vRandom (randomly-ordered vector of all nIds) to get the addresses. However, if a network is specified, we could check the number of entries in vRandom from that network using m_network_counts since it contains the number of entries in addrman per network. This way we could avoid unnecessary searchs in vRandom. So...

This PR improve the performance of addrman's GetAddr by checking m_network_counts when specifying a network.


AddrManGetAddrByNetwork bench:

master:

|               ns/op |                op/s |    err% |     total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
|          797,416.00 |            1,254.05 |    0.2% |      0.01 | `AddrManGetAddrByNetwork`

this PR:

|               ns/op |                op/s |    err% |     total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
|          462,875.00 |            2,160.41 |    5.6% |      0.01 | :wavy_dash: `AddrManGetAddrByNetwork` (Unstable with ~2.2 iters. Increase `minEpochIterations` to e.g. 22)

@DrahtBot
Copy link
Contributor

DrahtBot commented Mar 6, 2024

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

Code Coverage

For detailed information about the code coverage, see the test coverage report.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK vasild

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

@DrahtBot DrahtBot added the P2P label Mar 6, 2024
@l0rinc
Copy link
Contributor

l0rinc commented Mar 8, 2024

I was able to reproduce the diff, but please rebase the changes so that the benchmark is before the change so that we can easily check before/after.

Running it locally:

make && ./src/bench/bench_bitcoin --filter=AddrManGetAddrByNetwork --min-time=1000

Before:

|               ns/op |                op/s |    err% |     total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
|          819,423.49 |            1,220.37 |    0.3% |      1.07 | `AddrManGetAddrByNetwork`

after:

|               ns/op |                op/s |    err% |     total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
|          418,538.38 |            2,389.27 |    1.7% |      1.08 | `AddrManGetAddrByNetwork`

@brunoerg brunoerg force-pushed the 2024-03-addrman-getaddr branch from 98cc6ac to 1319958 Compare March 9, 2024 14:16
@brunoerg
Copy link
Contributor Author

brunoerg commented Mar 9, 2024

I was able to reproduce the diff, but please rebase the changes so that the benchmark is before the change so that we can easily check before/after.

Nice idea, force-pushed changing the order of the commits.

Copy link
Contributor

@vasild vasild left a comment

Choose a reason for hiding this comment

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

ACK 57db2e7

Changing the argument from std::optional<Network> to const std::optional<Network>& seems unnecessary because it is very cheap to copy that, it is 8 bytes. I would drop commit 1319958 addrman: net: use const ref for network in GetAddresses/GetAddr

@brunoerg brunoerg force-pushed the 2024-03-addrman-getaddr branch from 57db2e7 to e1e1078 Compare March 12, 2024 10:41
@brunoerg
Copy link
Contributor Author

Changing the argument from std::optional to const std::optional& seems unnecessary because it is very cheap to copy that, it is 8 bytes. I would drop commit 1319958 addrman: net: use const ref for network in GetAddresses/GetAddr

Done. Thanks, @vasild.

Copy link
Contributor

@vasild vasild left a comment

Choose a reason for hiding this comment

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

ACK e1e1078

brunoerg and others added 3 commits March 13, 2024 17:20
> make && ./src/bench/bench_bitcoin --filter=AddrManGetAddr --min-time=1000

Before:
```
|               ns/op |                op/s |    err% |     total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
|           76,852.79 |           13,011.89 |    0.4% |      1.07 | `AddrManGetAddr`
|           76,598.21 |           13,055.14 |    0.2% |      1.07 | `AddrManGetAddr`
|           76,296.32 |           13,106.79 |    0.1% |      1.07 | `AddrManGetAddr`
```
After:
```
|               ns/op |                op/s |    err% |     total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
|           65,966.97 |           15,159.10 |    0.3% |      1.07 | `AddrManGetAddr`
|           66,075.40 |           15,134.23 |    0.2% |      1.06 | `AddrManGetAddr`
|           66,306.34 |           15,081.51 |    0.3% |      1.06 | `AddrManGetAddr`
```
@brunoerg brunoerg force-pushed the 2024-03-addrman-getaddr branch from e1e1078 to 32a44d7 Compare March 13, 2024 20:20
@brunoerg
Copy link
Contributor Author

Rebased to fix CI.

Copy link
Contributor

@vasild vasild left a comment

Choose a reason for hiding this comment

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

ACK 32a44d7

@dergoegge
Copy link
Member

This PR improve the performance of addrman's GetAddr

I know I'm gonna make myself unpopular by saying this but these PRs require hours and hours from reviewers and authors that I'd rather see work on more impactful things. Given that this project has extremely limited resources, the cost to benefit ratio just doesn't make any sense to me here.

Why does the performance of GetAddr going from 797 to 460 micro seconds per call matter to this project? If you would create a trace for a running node instance, GetAddr would make up a tiny tiny tiny fraction of cpu time.

I'm open to being convinced but I'm very skeptical that there are no other more impactful performance improvements we could be spending our time on instead.

@brunoerg
Copy link
Contributor Author

This PR improve the performance of addrman's GetAddr

I know I'm gonna make myself unpopular by saying this but these PRs require hours and hours from reviewers and authors that I'd rather see work on more impactful things. Given that this project has extremely limited resources, the cost to benefit ratio just doesn't make any sense to me here.

Why does the performance of GetAddr going from 797 to 460 micro seconds per call matter to this project? If you would create a trace for a running node instance, GetAddr would make up a tiny tiny tiny fraction of cpu time.

I'm open to being convinced but I'm very skeptical that there are no other more impactful performance improvements we could be spending our time on instead.

I super respect your opinion and agree with your point about focusing on more impactful things. However, I do not think this PR requires hours and hours from reviewers/authors, the impactful change here is around 6 lines of code and it does not conflict with any other more important PR (better, any other PR). Also, GetAddr/GetAddresses is used in different scenarios: replying GETADDR, getnodeaddresses RPC, ASMapHealthCheck. I think this case worths, but I'm open and understand your point.

@l0rinc
Copy link
Contributor

l0rinc commented Mar 27, 2024

these PRs require hours and hours from reviewers and authors that I'd rather see work on more impactful things

This is how the new generation is recruited, newcomers cannot (and should not) start with "more impactful things".

@dergoegge
Copy link
Member

I do not think this PR requires hours and hours from reviewers/authors, the impactful change here is around 6 lines of code and it does not conflict with any other more important PR (better, any other PR).

One of these PRs might be harmless, but PRs like this one keep happening and the cumulative review time piles up.

Also, GetAddr/GetAddresses is used in different scenarios: replying GETADDR, getnodeaddresses RPC, ASMapHealthCheck.

Yes GetAddr is used but whether or not it can be called a 1000 or 2000 times per second doesn't matter to any of the use cases.

  • No application requires calling getnodeaddresses 1000s of times per second (is GetAddr even the bottleneck of that rpc?)
  • getaddr messages are on average received one time per connection (we only send it once during the version handshake)
  • ASMapHealthCheck is called once every 24 hours

This is how the new generation is recruited, newcomers cannot (and should not) start with "more impactful things".

@paplorinc I see your point but I don't think that "more impactful" implies non-trivial. Easy and smaller yet still impactful changes are certainly possible but I think this project could do better in providing guidance to newcomers in that regard.

@brunoerg
Copy link
Contributor Author

@dergoegge I'll consider your point for further PRs (including reviews). Thanks.

@brunoerg
Copy link
Contributor Author

brunoerg commented Apr 9, 2024

Closing for now.

@brunoerg brunoerg closed this Apr 9, 2024
@vasild
Copy link
Contributor

vasild commented Apr 19, 2024

The development of Bitcoin Core is decentralized because every developer decides for themselves what is important and what not.

Asserting one's opinion on others is more in line with centralized corporate management.

@maflcko
Copy link
Member

maflcko commented Apr 19, 2024

opinion

Performance improvements should be measured in numbers by machines, which does not seem like an opinion. According to #29578 (comment) , the code can only be reached by RPC and P2P. For those places no end-to-end performance difference has been provided. I'd say if there is a measurable (reproducible) performance improvement for a users' use case, or another use case that hasn't been mentioned yet, the change can be considered based on that. Otherwise, the code change seems like a style change, which largely is opinion-based.

@bitcoin bitcoin locked and limited conversation to collaborators Apr 19, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants