Skip to content

WIP: PEX - Peer Exchange#210

Closed
izderadicka wants to merge 4 commits into
ikatson:mainfrom
izderadicka:pex
Closed

WIP: PEX - Peer Exchange#210
izderadicka wants to merge 4 commits into
ikatson:mainfrom
izderadicka:pex

Conversation

@izderadicka

Copy link
Copy Markdown
Contributor

This is WORK IN PROGRESS (WIP) on adding PEX.

I wanted to share early - to get some feedback if I'm moving in wrong direction.

If this "early draft PR" does not work with project workflow, sorry for that, just close it.
WIP PRs did work for me to have place to discuss and share on particular feature, but if this does not fit this project sorry again.

I thought that PEX could be usefull, and should not be so difficult at least on receiving side. And I can try something bit more substantial .... But I do not have much time left - so it can take quite some time to finish.

@ikatson

ikatson commented Aug 24, 2024

Copy link
Copy Markdown
Owner

On a quick look from phone, seems like a reasonable thing to have. Code is mostly ok, minor comments so far not worth writing them down until this is finished.

Thanks for the early feedback ask, so far so good

Comment thread crates/peer_binary_protocol/src/extended/ut_pex.rs Outdated
where
B: AsRef<[u8]>,
{
pub fn added_peers<'a>(&'a self) -> anyhow::Result<Box<dyn Iterator<Item = PexPeerInfo> + 'a>> {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I'd avoid allocation here as it's quite easy to do.

two options:

  1. either use itertools::Either (minimal changes to your existing code, good enough)
  2. Option is also an iterator, and you can flatten it.

Option 2 would be smth like this:

if self.added.as_ref().map(|added| added.len() % 6 != 0).unwrap_or(false) {
    bail!(...)
}

let ips = self.added.as_ref().map(|addrs| addrs.chunk_exact(6)).flatten();
let flags = self.added_f.as_ref().map(|flags| flags.iter().copied()).flatten();

return ips.zip(flags).filter_map(|(ip, flags)| PexPeerInfo::from_bytes(ip, flags).ok())

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

added flags - added_f - are optional - so we can have addresses but not flags, in that case zip will not work. But chunks might make things easier - will look into it.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Look into the PR I put into your repo I've done it already

{
// TODO: this is just first attempt at pex - will need more sophistication on adding peers - BEP 40, check number of live, seen peers ...
if let Ok(peers) = msg.added_peers() {
peers.for_each(|peer| {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Clearly adding eagerly is not good - it takes huge amount of CPU - will need to find something better

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

What eats CPU exactly out of this?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Adding eagerly should be the way to go, just need to fix our workaround the issues

@ikatson

ikatson commented Aug 25, 2024

Copy link
Copy Markdown
Owner

I tried to look into it, and it seems totally ok to me. The peers get added, I don't see why this in particular would increase CPU usage.
Tweaked it all to fix all the things I mentioned + nicer debug

izderadicka#1

Comment thread .gitignore
/target
.DS_Store No newline at end of file
.DS_Store
/.vscode No newline at end of file

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Please don't remove this. It's for consistent linter / prettifier for JS mostly

@ikatson

ikatson commented Aug 25, 2024

Copy link
Copy Markdown
Owner

Also profiled in release mode, no CPU issues noticed, works like a charm. On my box, the absolute majority of the CPU is taken by:

  • syscal write to disk (45%)
  • read from network (14%)
  • checksum (9%)
  • write to network (4%)

The rest is rqbit itself + tokio overhead.

@izderadicka

izderadicka commented Aug 25, 2024

Copy link
Copy Markdown
Contributor Author

Still see about 150% CPU - it's on big swarm - https://releases.ubuntu.com/24.04/ubuntu-24.04-desktop-amd64.iso.torrent?_gl=1*1bi12tz*_gcl_au*MTA4NjA0NjI5Ny4xNzI0NDkzMjYy&_ga=2.207753554.1199975540.1724493262-752598451.1714415561

Only when torrent is downloading, when stopped, CPU is minimal. Looks like this behaviour is only on this pex branch.

@ikatson

ikatson commented Aug 25, 2024

Copy link
Copy Markdown
Owner

Just checking, can that be that with that branch there's many more live peers that you observe?

The CPU would be proportional to the number of live (i.e. connected and communicating) peers usually.

Otherwise maybe you can profile with perf or whatever you have on your system to see where's the new hotspot? I didn't see any on the torrent I checked

@ikatson

ikatson commented Aug 25, 2024

Copy link
Copy Markdown
Owner

I'll check that Ubuntu one too

@ikatson

ikatson commented Aug 25, 2024

Copy link
Copy Markdown
Owner

Just tried the ubuntu one.

System: macbook air m1
Max CPU usage - 80%
Seen peers - about 3000.
Downloading at about 85 megabytes per second.

There are 0 hotspots in the new code, all of "on_received_message" is in "on_received_piece".
Screenshot 2024-08-25 at 21 58 43

  1. Can you ensure you're profiling a release build
  2. Ensure you don't write logs / tracing is at "info" level.

You can use the newly added "make devserver-profile" command to do all that.

@ikatson

ikatson commented Aug 27, 2024

Copy link
Copy Markdown
Owner

@izderadicka any updates on this? I think I can just go ahead and merge this + izderadicka#1, as it seems useful on its own already for discovering peers even if we don't send our peers yet

@izderadicka

Copy link
Copy Markdown
Contributor Author

Sorry I did not have time to look at - as I said I do have only limited time - I'm still concerned about increase on CPU.
As I tested on Ubuntu torrent (only rather subjective tests, with top running) - this PR - high CPU, main branch - almost no CPU. Will like to look at it little bit more. Also it now looks only for IPv4 added peers - should look also at other categories.

@ikatson

ikatson commented Aug 28, 2024

Copy link
Copy Markdown
Owner

Also it now looks only for IPv4 added peers - should look also at other categories.

I addresed this already.

Let's do this: I merge this as-is plus my changes on top. If we figure out perf issues we fix them, but I don't see any so far as I mentioned. The PR is useful already on its own and it doesn't need to wait until all PEX features are implemented.

I'll merge this one instead #221 which includes your changes

@ikatson ikatson closed this Aug 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants