From bd0acd04b17a38a51fb57d1513fc04c72c8fa05b Mon Sep 17 00:00:00 2001 From: greatroar <61184462+greatroar@users.noreply.github.com> Date: Mon, 28 Feb 2022 09:13:30 +0100 Subject: [PATCH] lib/protocol: Use one mutex for rawConnect.awaiting and nextID (#8198) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- lib/protocol/protocol.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/protocol/protocol.go b/lib/protocol/protocol.go index 57a2661ed..61ff3a3e5 100644 --- a/lib/protocol/protocol.go +++ b/lib/protocol/protocol.go @@ -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()