Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

first draft proposal of multi-have BEP #28

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

arvidn
Copy link
Contributor

@arvidn arvidn commented May 26, 2016

please don't pull this until there's been some discussion. I expect to revise this a few times.

In some sense this proposal builds on the merkle tree torrent extension. It attempts to tackle the excessive protocol overhead associated with taking full advantage of merkle tree torrents, namely to have 16 kiB pieces.

Using 16 kiB pieces would improve performance for both streaming and traditional downloading.

  • delay to first upload contribution would be a lot lower
  • forwarding bytes to other peers in the swarm would have a lot lower latency
  • consuming downloaded bytes would have a lot lower latency (streaming)

Thanks @ssiloti for encouraging me to embrace small piece sizes :)


This BEP attempts to address (2) and (3) with a few different extensions.

Redundant HAVEs
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I feel pretty confident the redundant HAVE portion is non-controversial and a clear benefit.

@arvidn
Copy link
Contributor Author

arvidn commented May 26, 2016

ping @xercesblue @the8472

@the8472
Copy link
Contributor

the8472 commented May 26, 2016

I feel pretty confident the redundant HAVE portion is non-controversial and a clear benefit.

I disagree. It skews the availability calculations that clients make. I don't mind it being opt-in for clients that don't want to receive haves. But how it's currently phrased it encourages that behavior too much and even proposes to make it the default in the future.

This is also a UI issue. When doing a 1:1 transfer I want to see as a seeder whether things actually arrive on the other side. And it's a diagnostic thing, to see whether peers are doing rarest-first correctly, which is also good to know as a seeder.

Instead I would suggest just dropping the whole section and replace it with the notion of urgent and non-urgent HAVEs. Pieces a peer does not have would be urgent and should be sent soonish with minimal batching while non-urgent ones could be batched up more. Vuze already does this and also has multi-have messages and the resulting overhead is vanishingly small.

Or put differently, is there really still a bandwidth issue with HAVEs even when they're replaced with compressed bitfields?

@the8472
Copy link
Contributor

the8472 commented May 26, 2016

Also, for 16KiB pieces clients will probably want to do strided requests, to emulate fetching larger pieces to be more IO-friendly (for both sides). This will also result in nicely batchable HAVEs.

@arvidn
Copy link
Contributor Author

arvidn commented May 26, 2016

It skews the availability calculations that clients make

I take it you don't mean the piece picker's piece-availability state, right? presumably it would not track availability of pieces it already has (which will never be picked).

Do you mean a UI piece-availability view? (if so, asking for redundant haves could be enabled only if that view is enabled).

This is also a UI issue. When doing a 1:1 transfer I want to see as a seeder whether things actually arrive on the other side.

That's what I referred to with the progress-report. We used haves for this purpose at bittorrent at a few occasions. I'll add your point about diagnostics and monitoring peers to the list.

Or put differently, is there really still a bandwidth issue with HAVEs even when they're replaced with compressed bitfields?

I can't tell for sure (yet). I should do some more research. However, the effort of supporting the redundant have portion of this bep is trivial, which cannot be said about the compressed bitfields. At least not to do batching efficiently. So in some sense I imagine overhead-savings per effort is likely pretty high.

I'm imagining doing batching efficiently by re-writing messages in the send buffer to coalesce new haves, instead of sticking them at the end of the send buffer. Or something like inserting haves at the first message boundary in the beginning of the send buffer.

Also, for 16KiB pieces clients will probably want to do strided requests, to emulate fetching larger pieces to be more IO-friendly (for both sides). This will also result in nicely batchable HAVEs.

exactly. That was what I had in mind with command 3. But 8 bits may not be enough as it's just 128 kB (and that's only if it's perfectly aligned).

@the8472
Copy link
Contributor

the8472 commented May 26, 2016

Do you mean a UI piece-availability view? (if so, asking for redundant haves could be enabled only if that view is enabled).

Yes.

But "view is enabled" is not really a thing, since you can look at it whenever you want and that doesn't magically update all remote states. And even a daemon could never need that stat itself but a consumer of its APIs may or may not display it.

I'm imagining doing batching efficiently by re-writing messages in the send buffer to coalesce new haves,

Yeah, iirc that's what vuze does.

However, the effort of supporting the redundant have portion of this bep is trivial

Yeah, but i don't like the incentives here. "i can save upload bandwidth by withholding information that only affects someone else" vs. "i can save upload bandwidth by doing some extra implementation work myself".

I'm worrying because I already see clients misbehaving and unilaterally dropping haves. So I see this as encouraging this further, even talking about making it the default behavior in a future where correct statistics are some kind of optional behavior which you have to pretty please ask for.

which cannot be said about the compressed bitfields. At least not to do batching efficiently.

Well, an alternative to rewriting the send queue is to just do an urgent, not-urgent discrimination and put the urgent haves as-is on the send queue and put the non-urgent ones on a separate queue and flush that once a minute or something. that shouldn't be too hard.

Another alternative is completely doing away with pieces and just sending haves as a list of byte or 16KiB chunk (irrespective of piece size) offset-length pairs. A client could then translate them back into piece or merkle representation however it wants.

@the8472
Copy link
Contributor

the8472 commented May 26, 2016

Assuming that rarest first leads to perfect randomization and the swarm is not bottlenecked on waiting for the seed then the chance of a have being redundant only depends on the completion of a peer. High completion peer -> high redundancy chance.

Seeds -> obviously 100% redundancy.
Peers joining swarm -> 0% redundancy

This means the redundant have elimination might work the best when its bandwidth savings are the least needed, on a seed-saturated swarm.

Batching on the other hand should (almost) always work if you design your urgent/non-urgent discriminator carefully. E.g. it could be based on additional criteria:

  • piece availability: highly available pieces should be less urgent
  • redundancy: redundant are never urgent
  • non-redundant surplus: if the peer already knows about a lot of haves that they could request from us then it's less important to add yet another one right now
  • choke and interested states

With the right algorithm I imagine almost all HAVEs could be batched and only a smaller flux of live updates to keep rare pieces and interested state up to date would be needed.

@arvidn
Copy link
Contributor Author

arvidn commented May 26, 2016

I'm worrying because I already see clients misbehaving and unilaterally dropping haves. So I see this as encouraging this further, even talking about making it the default behavior in a future where correct statistics are some kind of optional behavior which you have to pretty please ask for.

If the default is to not send redundant haves, the currently misbehaving clients would be well-behaving all of a sudden (except in the cases where they're asked to send them) :)

my point is, why is "correct statistics" something useful in and of itself? It does not improve the data transfer performance. You seem to be suggesting it's good just because that's how the protocol was defined.

I'm not suggesting that super-seeding, monitoring, upload-feedback or any of those uses of redundant haves are bad and should be banned. I'm suggesting that they are not core to the purpose of bittorrent and seem reasonable to be opt-in (at some point).

This means the redundant have elimination might work the best when its bandwidth savings are the least needed, on a seed-saturated swarm.

Right, with the assumption that it's fine to waste the upload bandwidth as long as it's not interfering with the transfer. I'm not sure that's a fair assumption though, users may want to use their upload capacity for other things. Also, since the have-bandwidth scales by the number of peers you're connected to, with sufficient number of connections, the have-traffic could start to infringe on the piece request traffic. Actually, this reminds me, the request traffic is also overhead that increases with small pieces. I should add that to the list.

@the8472
Copy link
Contributor

the8472 commented May 26, 2016

I'm suggesting that they are not core to the purpose of bittorrent and seem reasonable to be opt-in (at some point).

Well, let me put it this way, I only see marginal benefit in the redundant have scheme. And you see only marginal benefit in the diagnostics.

Right, with the assumption that it's fine to waste the upload bandwidth as long as it's not interfering with the transfer. I'm not sure that's a fair assumption though

Sorry, I wasn't really aiming for that. I was kind of aiming at the implied converse as my main argument. What I really wanted to say is that redundant have logic does the least savings when it's most useful. Sure, saved bandwidth is nice. But when it matters matters most (few seeds) then it does the least.

So, redundant haves alone might not be good enough for that scenario and 16KiB pieces. And if we have batching and RLE bitfields then redundant haves might not be needed.

Actually, this reminds me, the request traffic is also overhead that increases with small pieces. I should add that to the list.

Yeah, but that does not scale with the # of connections. But range-requests should be easier than RLE.

@arvidn
Copy link
Contributor Author

arvidn commented May 26, 2016

Instead I would suggest just dropping the whole section and replace it with the notion of urgent and non-urgent HAVEs. Pieces a peer does not have would be urgent and should be sent soonish with minimal batching while non-urgent ones could be batched up more.

You're right that the amount of overhead would be minimal employing the scheme of deferring redundant haves. At first I was thinking that this kind of batching would be complicated, but thinking about it some more, it's close to trivial to do this.

The one issue I can think of that I would feel a bit uneasy about is time interval for sending the updates. you say 1 minute, but maybe it should be 10 pieces or 1 minute, whichever is longer, or maybe it could be 10 minutes. Some uses of redundant haves may deteriorate the longer you push this batching timer though. Especially with super seeding it might be urgent to indicate that you've received a piece, to make the seeder know that you're interested in having another pieces assigned to you. Anything short of immediate in this case could severely impact performance.

Vuze already does this and also has multi-have messages and the resulting overhead is vanishingly small.

Is the vuze protocol documented anywhere?

@the8472
Copy link
Contributor

the8472 commented May 26, 2016

Is the vuze protocol documented anywhere?

No. It only does that over its own extension protocol and I think it was just an array of piece number + number of consecutive coding or something like that. The gain might also have been higher because the extension protocol had a bit more per-message overhead than ltep.

Especially with super seeding it might be urgent to indicate that you've received a piece, to make the seeder know that you're interested in having another pieces assigned to you. Anything short of immediate in this case could severely impact performance.

That's a good point. But I believe that we can design an algorithm that covers this case - and starved swarms in general - and put that into the BEP. There's no need to have implementers figure out all the tricky details on their own.

For example the piece availability criterion and non-redundant-surplus things I mentioned earlier would already play into this and flag a have for a fresh superseeded piece as urgent to practically everyone in the swarm.

@arvidn
Copy link
Contributor Author

arvidn commented May 28, 2016

regarding redundant haves. I suppose one scheme could be to always send redundant haves back to the peers the piece was downloaded from. Any other redundant haves could be deferred and coalesced, and if they are delayed by several minutes, none of the use cases we have come up with would be particularly poorly affected (apart perhaps from monitoring whether peers pick rarest first or not. on the other hand though, I think there may be a privacy argument for suppressing such redundant haves).

On the other hand, it seems like a fairly complicated scheme compared to being explicit about wanting redundant haves. I can't think of a good reason not to be explicit. I would imagine it's a lot less error prone. Even with a deferred-have implementation, it would let you defer more have messages. And a deferred have optimization is somewhat orthogonal.

as for suppressing redundant haves only saving bandwidth when you need it the least. In my mind, any bandwidth savings is valuable. I like the heuristics you mention for deferring some non-redundant haves too, I think that is also an important optimization. But explicitly declaring interest for and suppressing redundant haves is trivial and explicit of intent, which I think are fairly strong argument.

I will split the BEP in two, and we can separate the discussions.

@the8472
Copy link
Contributor

the8472 commented May 28, 2016

I suppose one scheme could be to always send redundant haves back to the peers the piece was downloaded from.

That only gets you halfway to the superseeding case. The superseed checks when you received the piece and when someone else receives it, presumably from you. For that both clients have to send haves in a timely fashion to the superseed.

@the8472
Copy link
Contributor

the8472 commented May 28, 2016

But explicitly declaring interest for and suppressing redundant haves is trivial and explicit of intent

Well, could we make the omission of redundant haves semantically an opt-in at least?

nrh=1, no redundant haves.

@ssiloti
Copy link
Contributor

ssiloti commented May 28, 2016

I'm with 8472 on this one. Omitting redundant haves doesn't seem like a big enough win compared to the headaches it would cause. I think have batching should be done first, then only if redundant haves are shown to still represent a significant overhead should omitting them be supported.

@arvidn
Copy link
Contributor Author

arvidn commented May 30, 2016

I've moved this document into its own repository along with reference implementations and benchmarks.

I've stripped it down to just the compressed bitfield proposal, I've made some changes to the encoding inspired by chris as well. Please comment on it at https://github.com/arvidn/bittorrent-multi-have.

@the8472
Copy link
Contributor

the8472 commented May 30, 2016

You mention splitting redundant haves and compressed haves into separate BEPs.

But into which will deferred haves go? Or is that yet another one?

@arvidn
Copy link
Contributor Author

arvidn commented May 30, 2016

yeah, I'm putting that off until the dust settles on this one

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.

None yet

4 participants