Skip to content

Commit 28b71ba

Browse files
Dean KarnDean Karn
authored andcommitted
Merge pull request #102 from joeybloggs/v5-development
Implement native go sync.Pool
2 parents e5ebe76 + 9d4c0ec commit 28b71ba

File tree

3 files changed

+91
-122
lines changed

3 files changed

+91
-122
lines changed

.travis.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ notificaitons:
77
on_failure: always
88

99
go:
10-
- 1.2
1110
- 1.3
1211
- 1.4
1312
- tip
14-
15-
before_install:
16-
- go get github.com/axw/gocov/gocov
17-
- go get github.com/mattn/goveralls
18-
- if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
13+
1914
script:
20-
- $HOME/gopath/bin/goveralls -service=travis-ci
15+
- go get golang.org/x/tools/cmd/cover
16+
- go get github.com/mattn/goveralls
17+
- go test -v -covermode=count -coverprofile=cover.out
18+
19+
after_success:
20+
- goveralls -coverprofile=cover.out -service=travis-ci -repotoken I6M8FiXZzErImgwMotJ7fwFlHOX8Hqdq1

benchmarks_test.go

Lines changed: 74 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,23 @@ func BenchmarkValidateStructSimple(b *testing.B) {
2424
}
2525
}
2626

27-
// func BenchmarkTemplateParallelSimple(b *testing.B) {
27+
func BenchmarkTemplateParallelSimple(b *testing.B) {
2828

29-
// type Foo struct {
30-
// StringValue string `validate:"min=5,max=10"`
31-
// IntValue int `validate:"min=5,max=10"`
32-
// }
29+
type Foo struct {
30+
StringValue string `validate:"min=5,max=10"`
31+
IntValue int `validate:"min=5,max=10"`
32+
}
3333

34-
// validFoo := &Foo{StringValue: "Foobar", IntValue: 7}
35-
// invalidFoo := &Foo{StringValue: "Fo", IntValue: 3}
34+
validFoo := &Foo{StringValue: "Foobar", IntValue: 7}
35+
invalidFoo := &Foo{StringValue: "Fo", IntValue: 3}
3636

37-
// b.RunParallel(func(pb *testing.PB) {
38-
// for pb.Next() {
39-
// validate.Struct(validFoo)
40-
// validate.Struct(invalidFoo)
41-
// }
42-
// })
43-
// }
37+
b.RunParallel(func(pb *testing.PB) {
38+
for pb.Next() {
39+
validate.Struct(validFoo)
40+
validate.Struct(invalidFoo)
41+
}
42+
})
43+
}
4444

4545
func BenchmarkValidateStructLarge(b *testing.B) {
4646

@@ -101,63 +101,63 @@ func BenchmarkValidateStructLarge(b *testing.B) {
101101
}
102102
}
103103

104-
// func BenchmarkTemplateParallelLarge(b *testing.B) {
105-
106-
// tFail := &TestString{
107-
// Required: "",
108-
// Len: "",
109-
// Min: "",
110-
// Max: "12345678901",
111-
// MinMax: "",
112-
// Lt: "0123456789",
113-
// Lte: "01234567890",
114-
// Gt: "1",
115-
// Gte: "1",
116-
// OmitEmpty: "12345678901",
117-
// Sub: &SubTest{
118-
// Test: "",
119-
// },
120-
// Anonymous: struct {
121-
// A string `validate:"required"`
122-
// }{
123-
// A: "",
124-
// },
125-
// Iface: &Impl{
126-
// F: "12",
127-
// },
128-
// }
129-
130-
// tSuccess := &TestString{
131-
// Required: "Required",
132-
// Len: "length==10",
133-
// Min: "min=1",
134-
// Max: "1234567890",
135-
// MinMax: "12345",
136-
// Lt: "012345678",
137-
// Lte: "0123456789",
138-
// Gt: "01234567890",
139-
// Gte: "0123456789",
140-
// OmitEmpty: "",
141-
// Sub: &SubTest{
142-
// Test: "1",
143-
// },
144-
// SubIgnore: &SubTest{
145-
// Test: "",
146-
// },
147-
// Anonymous: struct {
148-
// A string `validate:"required"`
149-
// }{
150-
// A: "1",
151-
// },
152-
// Iface: &Impl{
153-
// F: "123",
154-
// },
155-
// }
156-
157-
// b.RunParallel(func(pb *testing.PB) {
158-
// for pb.Next() {
159-
// validate.Struct(tSuccess)
160-
// validate.Struct(tFail)
161-
// }
162-
// })
163-
// }
104+
func BenchmarkTemplateParallelLarge(b *testing.B) {
105+
106+
tFail := &TestString{
107+
Required: "",
108+
Len: "",
109+
Min: "",
110+
Max: "12345678901",
111+
MinMax: "",
112+
Lt: "0123456789",
113+
Lte: "01234567890",
114+
Gt: "1",
115+
Gte: "1",
116+
OmitEmpty: "12345678901",
117+
Sub: &SubTest{
118+
Test: "",
119+
},
120+
Anonymous: struct {
121+
A string `validate:"required"`
122+
}{
123+
A: "",
124+
},
125+
Iface: &Impl{
126+
F: "12",
127+
},
128+
}
129+
130+
tSuccess := &TestString{
131+
Required: "Required",
132+
Len: "length==10",
133+
Min: "min=1",
134+
Max: "1234567890",
135+
MinMax: "12345",
136+
Lt: "012345678",
137+
Lte: "0123456789",
138+
Gt: "01234567890",
139+
Gte: "0123456789",
140+
OmitEmpty: "",
141+
Sub: &SubTest{
142+
Test: "1",
143+
},
144+
SubIgnore: &SubTest{
145+
Test: "",
146+
},
147+
Anonymous: struct {
148+
A string `validate:"required"`
149+
}{
150+
A: "1",
151+
},
152+
Iface: &Impl{
153+
F: "123",
154+
},
155+
}
156+
157+
b.RunParallel(func(pb *testing.PB) {
158+
for pb.Next() {
159+
validate.Struct(tSuccess)
160+
validate.Struct(tFail)
161+
}
162+
})
163+
}

validator.go

Lines changed: 10 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -37,43 +37,13 @@ const (
3737
mapIndexFieldName = "%s[%v]"
3838
)
3939

40-
var structPool *pool
40+
var structPool *sync.Pool
4141

42-
// Pool holds a channelStructErrors.
43-
type pool struct {
44-
pool chan *StructErrors
45-
}
46-
47-
// NewPool creates a new pool of Clients.
48-
func newPool(max int) *pool {
49-
return &pool{
50-
pool: make(chan *StructErrors, max),
51-
}
52-
}
53-
54-
// Borrow a StructErrors from the pool.
55-
func (p *pool) Borrow() *StructErrors {
56-
var c *StructErrors
57-
58-
select {
59-
case c = <-p.pool:
60-
default:
61-
c = &StructErrors{
62-
Errors: map[string]*FieldError{},
63-
StructErrors: map[string]*StructErrors{},
64-
}
65-
}
66-
67-
return c
68-
}
69-
70-
// Return returns a StructErrors to the pool.
71-
func (p *pool) Return(c *StructErrors) {
72-
73-
select {
74-
case p.pool <- c:
75-
default:
76-
// let it go, let it go...
42+
// returns new *StructErrors to the pool
43+
func newStructErrors() interface{} {
44+
return &StructErrors{
45+
Errors: map[string]*FieldError{},
46+
StructErrors: map[string]*StructErrors{},
7747
}
7848
}
7949

@@ -357,7 +327,7 @@ type Validate struct {
357327
// New creates a new Validate instance for use.
358328
func New(tagName string, funcs map[string]Func) *Validate {
359329

360-
structPool = newPool(10)
330+
structPool = &sync.Pool{New: newStructErrors}
361331

362332
return &Validate{
363333
tagName: tagName,
@@ -377,9 +347,8 @@ func (v *Validate) SetTag(tagName string) {
377347
// nearly all cases. only increase if you have a deeply nested struct structure.
378348
// NOTE: this method is not thread-safe
379349
// NOTE: this is only here to keep compatibility with v5, in v6 the method will be removed
380-
// and the max pool size will be passed into the New function
381350
func (v *Validate) SetMaxStructPoolSize(max int) {
382-
structPool = newPool(max)
351+
structPool = &sync.Pool{New: newStructErrors}
383352
}
384353

385354
// AddFunction adds a validation Func to a Validate's map of validators denoted by the key
@@ -440,7 +409,7 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
440409
cs = &cachedStruct{name: structName, children: numFields}
441410
}
442411

443-
validationErrors := structPool.Borrow()
412+
validationErrors := structPool.Get().(*StructErrors)
444413
validationErrors.Struct = structName
445414

446415
for i := 0; i < numFields; i++ {
@@ -617,7 +586,7 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
617586
structCache.Set(structType, cs)
618587

619588
if len(validationErrors.Errors) == 0 && len(validationErrors.StructErrors) == 0 {
620-
structPool.Return(validationErrors)
589+
structPool.Put(validationErrors)
621590
return nil
622591
}
623592

0 commit comments

Comments
 (0)