2
0
mirror of https://github.com/soheilhy/cmux.git synced 2024-09-20 02:55:46 +08:00

Merge pull request #30 from soheilhy/fix-patricia-tree

Fix race in patricia tree
This commit is contained in:
Soheil Hassas Yeganeh 2016-07-15 08:04:18 -07:00 committed by GitHub
commit e85da3027e
3 changed files with 40 additions and 31 deletions

View File

@ -24,4 +24,5 @@ before_script:
- if [[ $TRAVIS_GO_VERSION == 1.6* ]]; then go tool vet --shadow .; fi - if [[ $TRAVIS_GO_VERSION == 1.6* ]]; then go tool vet --shadow .; fi
script: script:
- go test -v ./... - go test -bench . -v ./...
- go test -race -bench . -v ./...

View File

@ -62,12 +62,14 @@ func BenchmarkCMuxConnHTTP1(b *testing.B) {
wg.Add(b.N) wg.Add(b.N)
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { b.RunParallel(func(pb *testing.PB) {
c := &mockConn{ for pb.Next() {
r: bytes.NewReader(benchHTTP1Payload), wg.Add(1)
m.serve(&mockConn{
r: bytes.NewReader(benchHTTP1Payload),
}, donec, &wg)
} }
m.serve(c, donec, &wg) })
}
} }
func BenchmarkCMuxConnHTTP2(b *testing.B) { func BenchmarkCMuxConnHTTP2(b *testing.B) {
@ -80,12 +82,14 @@ func BenchmarkCMuxConnHTTP2(b *testing.B) {
wg.Add(b.N) wg.Add(b.N)
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { b.RunParallel(func(pb *testing.PB) {
c := &mockConn{ for pb.Next() {
r: bytes.NewReader(benchHTTP2Payload), wg.Add(1)
m.serve(&mockConn{
r: bytes.NewReader(benchHTTP2Payload),
}, donec, &wg)
} }
m.serve(c, donec, &wg) })
}
} }
func BenchmarkCMuxConnHTTP1n2(b *testing.B) { func BenchmarkCMuxConnHTTP1n2(b *testing.B) {
@ -98,15 +102,16 @@ func BenchmarkCMuxConnHTTP1n2(b *testing.B) {
donec := make(chan struct{}) donec := make(chan struct{})
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(b.N)
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { b.RunParallel(func(pb *testing.PB) {
c := &mockConn{ for pb.Next() {
r: bytes.NewReader(benchHTTP2Payload), wg.Add(1)
m.serve(&mockConn{
r: bytes.NewReader(benchHTTP2Payload),
}, donec, &wg)
} }
m.serve(c, donec, &wg) })
}
} }
func BenchmarkCMuxConnHTTP2n1(b *testing.B) { func BenchmarkCMuxConnHTTP2n1(b *testing.B) {
@ -119,13 +124,14 @@ func BenchmarkCMuxConnHTTP2n1(b *testing.B) {
donec := make(chan struct{}) donec := make(chan struct{})
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(b.N)
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { b.RunParallel(func(pb *testing.PB) {
c := &mockConn{ for pb.Next() {
r: bytes.NewReader(benchHTTP1Payload), wg.Add(1)
m.serve(&mockConn{
r: bytes.NewReader(benchHTTP1Payload),
}, donec, &wg)
} }
m.serve(c, donec, &wg) })
}
} }

View File

@ -22,8 +22,8 @@ import (
// patriciaTree is a simple patricia tree that handles []byte instead of string // patriciaTree is a simple patricia tree that handles []byte instead of string
// and cannot be changed after instantiation. // and cannot be changed after instantiation.
type patriciaTree struct { type patriciaTree struct {
root *ptNode root *ptNode
buf []byte // preallocated buffer to read data while matching maxDepth int // max depth of the tree.
} }
func newPatriciaTree(bs ...[]byte) *patriciaTree { func newPatriciaTree(bs ...[]byte) *patriciaTree {
@ -34,8 +34,8 @@ func newPatriciaTree(bs ...[]byte) *patriciaTree {
} }
} }
return &patriciaTree{ return &patriciaTree{
root: newNode(bs), root: newNode(bs),
buf: make([]byte, max+1), maxDepth: max + 1,
} }
} }
@ -48,13 +48,15 @@ func newPatriciaTreeString(strs ...string) *patriciaTree {
} }
func (t *patriciaTree) matchPrefix(r io.Reader) bool { func (t *patriciaTree) matchPrefix(r io.Reader) bool {
n, _ := io.ReadFull(r, t.buf) buf := make([]byte, t.maxDepth)
return t.root.match(t.buf[:n], true) n, _ := io.ReadFull(r, buf)
return t.root.match(buf[:n], true)
} }
func (t *patriciaTree) match(r io.Reader) bool { func (t *patriciaTree) match(r io.Reader) bool {
n, _ := io.ReadFull(r, t.buf) buf := make([]byte, t.maxDepth)
return t.root.match(t.buf[:n], false) n, _ := io.ReadFull(r, buf)
return t.root.match(buf[:n], false)
} }
type ptNode struct { type ptNode struct {