2
0
mirror of https://github.com/soheilhy/cmux.git synced 2024-11-09 19:21:52 +08:00

Add locking to patricia tree

Fixes race conditions in matchers. Impact on benchmarks:

name               old time/op    new time/op    delta
CMuxConnHTTP1-4       664ns ±19%     849ns ± 6%  +27.91%         (p=0.000 n=9+10)
CMuxConnHTTP2-4       745ns ±16%     699ns ± 9%     ~            (p=0.075 n=9+10)
CMuxConnHTTP1n2-4     930ns ±28%    1079ns ± 4%  +16.00%         (p=0.022 n=10+9)
CMuxConnHTTP2n1-4    1.18µs ±52%    0.98µs ±13%     ~           (p=1.000 n=10+10)

name               old alloc/op   new alloc/op   delta
CMuxConnHTTP1-4        256B ± 0%      256B ± 0%     ~     (all samples are equal)
CMuxConnHTTP2-4        288B ± 0%      288B ± 0%     ~     (all samples are equal)
CMuxConnHTTP1n2-4      288B ± 0%      288B ± 0%     ~     (all samples are equal)
CMuxConnHTTP2n1-4      288B ± 0%      288B ± 0%     ~     (all samples are equal)

name               old allocs/op  new allocs/op  delta
CMuxConnHTTP1-4        3.00 ± 0%      3.00 ± 0%     ~     (all samples are equal)
CMuxConnHTTP2-4        4.00 ± 0%      4.00 ± 0%     ~     (all samples are equal)
CMuxConnHTTP1n2-4      4.00 ± 0%      4.00 ± 0%     ~     (all samples are equal)
CMuxConnHTTP2n1-4      4.00 ± 0%      4.00 ± 0%     ~     (all samples are equal)
This commit is contained in:
Tamir Duberstein 2016-07-12 12:19:27 -04:00
parent f4d9321cb4
commit 9421819d79
No known key found for this signature in database
GPG Key ID: 1C1E98CC8E17BB89

View File

@ -17,13 +17,17 @@ package cmux
import (
"bytes"
"io"
"sync"
)
// patriciaTree is a simple patricia tree that handles []byte instead of string
// and cannot be changed after instantiation.
type patriciaTree struct {
root *ptNode
buf []byte // preallocated buffer to read data while matching
mu struct {
sync.Mutex
buf []byte // preallocated buffer to read data while matching
}
}
func newPatriciaTree(bs ...[]byte) *patriciaTree {
@ -33,10 +37,10 @@ func newPatriciaTree(bs ...[]byte) *patriciaTree {
max = len(b)
}
}
return &patriciaTree{
root: newNode(bs),
buf: make([]byte, max+1),
}
t := patriciaTree{root: newNode(bs)}
t.mu.buf = make([]byte, max+1)
return &t
}
func newPatriciaTreeString(strs ...string) *patriciaTree {
@ -48,13 +52,19 @@ func newPatriciaTreeString(strs ...string) *patriciaTree {
}
func (t *patriciaTree) matchPrefix(r io.Reader) bool {
n, _ := io.ReadFull(r, t.buf)
return t.root.match(t.buf[:n], true)
t.mu.Lock()
defer t.mu.Unlock()
n, _ := io.ReadFull(r, t.mu.buf)
return t.root.match(t.mu.buf[:n], true)
}
func (t *patriciaTree) match(r io.Reader) bool {
n, _ := io.ReadFull(r, t.buf)
return t.root.match(t.buf[:n], false)
t.mu.Lock()
defer t.mu.Unlock()
n, _ := io.ReadFull(r, t.mu.buf)
return t.root.match(t.mu.buf[:n], false)
}
type ptNode struct {