lib/protocol: Use one mutex for rawConnect.awaiting and nextID (#8198)

Having a separate mutex for the three or four instructions needed to
fetch and increment nextID means the overhead exceeds the cost of this
operation.  nextID is now handled inside the critical section for
awaiting instead, while the more expensive channel creation has been
moved outside it.

This is mostly a simplification, though it may have minor performance
benefits in some situations. The single-threaded sender benchmark shows
no significant difference:

name               old speed      new speed      delta
RequestsRawTCP-8   55.3MB/s ± 7%  56.6MB/s ± 6%   ~     (p=0.190 n=10+10)
RequestsTLSoTCP-8  20.5MB/s ±20%  20.8MB/s ± 8%   ~     (p=0.604 n=10+9)
This commit is contained in:
greatroar 2022-02-28 09:13:30 +01:00 committed by GitHub
parent f25947e5eb
commit bd0acd04b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 5 additions and 9 deletions

View File

@ -180,14 +180,12 @@ type rawConnection struct {
cw *countingWriter
closer io.Closer // Closing the underlying connection and thus cr and cw
awaitingMut sync.Mutex // Protects awaiting and nextID.
awaiting map[int]chan asyncResult
awaitingMut sync.Mutex
nextID int
idxMut sync.Mutex // ensures serialization of Index calls
nextID int
nextIDMut sync.Mutex
inbox chan message
outbox chan asyncMessage
closeBox chan asyncMessage
@ -336,17 +334,15 @@ func (c *rawConnection) IndexUpdate(ctx context.Context, folder string, idx []Fi
// Request returns the bytes for the specified block after fetching them from the connected peer.
func (c *rawConnection) Request(ctx context.Context, folder string, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
c.nextIDMut.Lock()
id := c.nextID
c.nextID++
c.nextIDMut.Unlock()
rc := make(chan asyncResult, 1)
c.awaitingMut.Lock()
id := c.nextID
c.nextID++
if _, ok := c.awaiting[id]; ok {
c.awaitingMut.Unlock()
panic("id taken")
}
rc := make(chan asyncResult, 1)
c.awaiting[id] = rc
c.awaitingMut.Unlock()