Skip to content
This repository has been archived by the owner on Aug 19, 2022. It is now read-only.

segment the memory peerstore + granular locks #78

Merged
merged 12 commits into from
May 18, 2019
Merged

Conversation

raulk
Copy link
Member

@raulk raulk commented May 8, 2019

Quick attempt to remove the global lock on addr map. Should reduce lock contention under high load. Please try out and report results, @vyzo!

@raulk raulk requested a review from vyzo May 8, 2019 23:29
@ghost ghost assigned raulk May 8, 2019
@ghost ghost added the status/in-progress In progress label May 8, 2019
@raulk raulk requested a review from Stebalien May 8, 2019 23:29
@Stebalien Stebalien removed their request for review May 9, 2019 00:01
Copy link
Contributor

@vyzo vyzo left a comment

Choose a reason for hiding this comment

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

We need the stiped locks on the protocols as well (and possibly the keybook)
I am going to implement.

pstoremem/addr_book.go Show resolved Hide resolved
@ghost ghost assigned vyzo May 9, 2019
@vyzo
Copy link
Contributor

vyzo commented May 10, 2019

Just a summary of progress: this patch, together with libp2p/go-libp2p-connmgr#40, has eliminated all lock contention in the test relay.

@vyzo
Copy link
Contributor

vyzo commented May 10, 2019

I will move the peerstore striping logic to its own component, and add support for the ds-backed peerstore as well.

@vyzo
Copy link
Contributor

vyzo commented May 17, 2019

Split off the protocol book in the interface, with implementations for both the memory and datastore-backed peerstore.

@vyzo vyzo marked this pull request as ready for review May 17, 2019 10:17
@vyzo vyzo requested a review from Stebalien May 17, 2019 10:17
@vyzo
Copy link
Contributor

vyzo commented May 17, 2019

this is ready for review now.


func (s *protoSegments) get(p peer.ID) *protoSegment {
b := []byte(p)
return s[b[len(b)-1]]
Copy link
Member

Choose a reason for hiding this comment

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

Go may optimize this, but it might just decide to copy the slice. How about s[byte(p[len(p)-1])]?

Copy link
Contributor

Choose a reason for hiding this comment

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

hrm, I don't think that it copies in such casts, but hard to be certain.

Copy link
Contributor

Choose a reason for hiding this comment

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

How does the rune to byte conversion work here btw?

Copy link
Member

Choose a reason for hiding this comment

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

hrm, I don't think that it copies in such casts, but hard to be certain.

It []byte(string) usually copies as []byte is mutable whyle strings aren't. However, go does the right thing in some cases, IIRC.

How does the rune to byte conversion work here btw?

Go indexes strings by byte. Think of go strings like python strings, they can contain arbitrary bytes but are sometimes valid UTF8.

Copy link
Contributor

Choose a reason for hiding this comment

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

ok, avoided the intermediate byte slice.

}

func (mab *memoryAddrBook) PeersWithAddrs() peer.IDSlice {
mab.addrmu.RLock()
defer mab.addrmu.RUnlock()
var length uint32
Copy link
Member

Choose a reason for hiding this comment

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

Optimizing for this case probably isn't worth it. This function isn't likely to be called frequently so we can probably just allocate the peer ID slice as needed and drop the atomic length updating logic.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, good point.

Copy link
Contributor

Choose a reason for hiding this comment

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

done.


func (pb *dsProtoBook) SetProtocols(p peer.ID, protos ...string) error {
pb.Lock(p)
defer pb.Unlock(p)
Copy link
Member

Choose a reason for hiding this comment

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

We could also just require a transaction datastore and avoid locking entirely. cc @raulk?

return &dsProtoBook{meta: meta}
}

func (pb *dsProtoBook) Lock(p peer.ID) {
Copy link
Member

Choose a reason for hiding this comment

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

These methods should be private.

Copy link
Contributor

Choose a reason for hiding this comment

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

ok.

Copy link
Contributor

Choose a reason for hiding this comment

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

done.

@vyzo vyzo requested a review from Stebalien May 17, 2019 20:41
}

func (pb *dsProtoBook) lock(p peer.ID) {
pb.lks[byte(p[len(p)-1])].Lock()
Copy link
Member

Choose a reason for hiding this comment

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

nit: a segment(p peer.ID) *segment function would be nice (could even drop all of these functions and just call pb.segment(p).Lock().

Copy link
Contributor

Choose a reason for hiding this comment

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

ok, will do. I'll call it get similar to how we do it in the memory peerstore.

Copy link
Contributor

Choose a reason for hiding this comment

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

done.

@vyzo vyzo merged commit 80303a4 into master May 18, 2019
@vyzo vyzo deleted the feat/segmented-map branch May 18, 2019 08:45
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.

3 participants