Skip to content
This repository has been archived by the owner on Feb 1, 2023. It is now read-only.

Fix: don't ignore received blocks for pending wants #174

Merged
merged 12 commits into from Aug 23, 2019

Conversation

dirkmc
Copy link
Contributor

@dirkmc dirkmc commented Aug 13, 2019

Fixes #172

@dirkmc
Copy link
Contributor Author

dirkmc commented Aug 13, 2019

One concern with this approach is that we ask each session in turn if it is interested in the CID. If there are N sessions, then (N - 1) / N times the session will not have the CID. As noted in the comment in the code in session.go:149, this may cause performance issues:

// InterestedIn returns true if this session is interested in the given Cid.
func (s *Session) InterestedIn(c cid.Cid) bool {
if s.interest.Contains(c) {
return true
}
// TODO: PERF: this is using a channel to guard a map access against race
// conditions. This is definitely much slower than a mutex, though its unclear
// if it will actually induce any noticeable slowness. This is implemented this
// way to avoid adding a more complex set of mutexes around the liveWants map.
// note that in the average case (where this session *is* interested in the
// block we received) this function will not be called, as the cid will likely
// still be in the interest cache.
resp := make(chan bool, 1)
select {
case s.interestReqs <- interestReq{
c: c,
resp: resp,
}:
case <-s.ctx.Done():
return false
}
select {
case want := <-resp:
return want
case <-s.ctx.Done():
return false
}
}

One option would be to simply replace the s.interest LRU with a map[cid.Cid]struct{} (guarded by a lock)

bitswap.go Outdated Show resolved Hide resolved
@Stebalien
Copy link
Member

One option would be to simply replace the s.interest LRU with a map[cid.Cid]struct{} (guarded by a lock).

We're going to have to check this anyways when we figure out where to send the blocks. However, it's slightly worse in this case as we'll need to call this on duplicates as well.

I'd like to drop the interest cache and provide a way to check this without using channels anyways so I'm all for fixing this.

To handle, the many sessions issue, we could even have a second, global & reference counted interest set.

I believe we'll still have races where we'll receive multiple blocks quickly before we record that we've received them but I believe that's a problem anyways.

@dirkmc
Copy link
Contributor Author

dirkmc commented Aug 14, 2019

I guess the most important property is that if session.GetBlocks() has ever been called on a session, then when a corresponding block is received, we should always make sure the session receives the block.

The session stores all the CIDs it has ever been asked for in liveWants, tofetch and pastWants, so we shouldn't actually need a separate set to determine if the session is interested.

We just need to make sure we take a lock each time we manipulate or query any of those sets of CIDs.

@dirkmc
Copy link
Contributor Author

dirkmc commented Aug 15, 2019

I created a PR #184 that branches off this PR, to explore refactoring want management into a separate class, so that it's easier to put locks around the want queues. With locks in place we can avoid going through Session's event loop when calling InterestedIn() and IsWanted().

EDIT: I merged the want management PR into this PR. Now it just puts want management behind locks

@dirkmc
Copy link
Contributor Author

dirkmc commented Aug 20, 2019

Tests are failing because of some flakiness that is fixed in #185

@dirkmc dirkmc force-pushed the fix/dont-ignore-pending-blocks branch from 3f85389 to 7458eb8 Compare August 20, 2019 22:27
Copy link
Member

@Stebalien Stebalien left a comment

Choose a reason for hiding this comment

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

Nits you can ignore (or not). But this really does feel simpler

session/session.go Outdated Show resolved Hide resolved
session/session.go Outdated Show resolved Hide resolved
session/session.go Outdated Show resolved Hide resolved
session/session.go Outdated Show resolved Hide resolved
session/session.go Outdated Show resolved Hide resolved
session/session.go Outdated Show resolved Hide resolved
Copy link
Member

@Stebalien Stebalien left a comment

Choose a reason for hiding this comment

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

My only real comment is on the goroutines. I'd leave those out (unless you feel that there's a strong need for them).

session/sessionwants.go Outdated Show resolved Hide resolved
session/sessionwants.go Outdated Show resolved Hide resolved

s.sw.RUnlock()
// Record unique vs duplicate blocks
s.sw.ForEachUniqDup(rcv.ks, s.srs.RecordUniqueBlock, s.srs.RecordDuplicateBlock)
Copy link
Member

Choose a reason for hiding this comment

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

Hm. I'm not sure of a better way to do this but this is a bit funky. But it's probably fine.

sessionmanager/sessionmanager.go Outdated Show resolved Hide resolved
session/sessionwants.go Outdated Show resolved Hide resolved
@Stebalien Stebalien merged commit 7944a99 into master Aug 23, 2019
@Stebalien Stebalien deleted the fix/dont-ignore-pending-blocks branch August 23, 2019 18:41
Jorropo pushed a commit to Jorropo/go-libipfs that referenced this pull request Jan 26, 2023
…ing-blocks

Fix: don't ignore received blocks for pending wants

This commit was moved from ipfs/go-bitswap@7944a99
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Don't discard unwanted blocks we actually want
2 participants