Skip to content

Commit 975debd

Browse files
authoredApr 29, 2020
Using sync.Pool to optimize TokenResult creation (alibaba#137) (alibaba#142)
Using sync.Pool to optimize TokenResult creation
1 parent 7e2e72b commit 975debd

File tree

8 files changed

+101
-18
lines changed

8 files changed

+101
-18
lines changed
 

‎api/api.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ func Entry(resource string, opts ...EntryOption) (*base.SentinelEntry, *base.Blo
8787
}
8888

8989
func entry(resource string, options *EntryOptions) (*base.SentinelEntry, *base.BlockError) {
90+
var r *base.TokenResult
91+
defer func() {
92+
if r != nil {
93+
base.RefurbishTokenResult(r)
94+
}
95+
}()
96+
9097
rw := base.NewResourceWrapper(resource, options.resourceType, options.entryType)
9198
sc := options.slotChain
9299

@@ -104,8 +111,7 @@ func entry(resource string, options *EntryOptions) (*base.SentinelEntry, *base.B
104111
}
105112

106113
e := base.NewSentinelEntry(ctx, rw, sc)
107-
108-
r := sc.Entry(ctx)
114+
r = sc.Entry(ctx)
109115
if r == nil {
110116
// This indicates internal error in some slots, so just pass
111117
return e, nil

‎core/base/result.go

+38-12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package base
22

33
import (
44
"fmt"
5+
"sync"
56
)
67

78
type BlockType int32
@@ -13,6 +14,12 @@ const (
1314
BlockTypeSystemFlow
1415
)
1516

17+
var resultPool = sync.Pool{
18+
New: func() interface{} {
19+
return NewTokenResultEmpty()
20+
},
21+
}
22+
1623
func (t BlockType) String() string {
1724
switch t {
1825
case BlockTypeUnknown:
@@ -73,26 +80,45 @@ func (r *TokenResult) String() string {
7380
return fmt.Sprintf("TokenResult{status=%d, blockErr=%s, waitMs=%d}", r.status, blockMsg, r.waitMs)
7481
}
7582

83+
func NewTokenResultEmpty() *TokenResult {
84+
return &TokenResult{
85+
status: ResultStatusPass,
86+
blockErr: nil,
87+
waitMs: 0,
88+
}
89+
}
90+
7691
func NewTokenResultPass() *TokenResult {
77-
return &TokenResult{status: ResultStatusPass, waitMs: 0}
92+
return resultPool.Get().(*TokenResult)
7893
}
7994

8095
func NewTokenResultBlocked(blockType BlockType, blockMsg string) *TokenResult {
81-
return &TokenResult{
82-
status: ResultStatusBlocked,
83-
blockErr: NewBlockError(blockType, blockMsg),
84-
waitMs: 0,
85-
}
96+
result := resultPool.Get().(*TokenResult)
97+
result.status = ResultStatusBlocked
98+
result.blockErr = NewBlockError(blockType, blockMsg)
99+
return result
86100
}
87101

88102
func NewTokenResultBlockedWithCause(blockType BlockType, blockMsg string, rule SentinelRule, snapshot interface{}) *TokenResult {
89-
return &TokenResult{
90-
status: ResultStatusBlocked,
91-
blockErr: NewBlockErrorWithCause(blockType, blockMsg, rule, snapshot),
92-
waitMs: 0,
93-
}
103+
result := resultPool.Get().(*TokenResult)
104+
result.status = ResultStatusBlocked
105+
result.blockErr = NewBlockErrorWithCause(blockType, blockMsg, rule, snapshot)
106+
return result
94107
}
95108

96109
func NewTokenResultShouldWait(waitMs uint64) *TokenResult {
97-
return &TokenResult{status: ResultStatusShouldWait, waitMs: waitMs}
110+
result := resultPool.Get().(*TokenResult)
111+
result.status = ResultStatusShouldWait
112+
result.waitMs = waitMs
113+
return result
114+
}
115+
116+
func RefurbishTokenResult(result *TokenResult) {
117+
if result != nil {
118+
result.status = ResultStatusPass
119+
result.blockErr = nil
120+
result.waitMs = 0
121+
122+
resultPool.Put(result)
123+
}
98124
}

‎core/base/result_test.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package base
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func BenchmarkWithPool(b *testing.B) {
8+
var result *TokenResult
9+
b.ReportAllocs()
10+
for i := 0; i < b.N; i++ {
11+
for j := 0; j < 10000; j++ {
12+
result = NewTokenResultPass()
13+
RefurbishTokenResult(result)
14+
}
15+
}
16+
}
17+
18+
func BenchmarkWithNoPool(b *testing.B) {
19+
var result *TokenResult
20+
b.ReportAllocs()
21+
for i := 0; i < b.N; i++ {
22+
for j := 0; j < 10000; j++ {
23+
result = NewTokenResultEmpty()
24+
result.status = ResultStatusPass
25+
result.blockErr = nil
26+
result.waitMs = 0
27+
}
28+
}
29+
}

‎core/base/slot_chain.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -136,20 +136,26 @@ func (sc *SlotChain) Entry(ctx *EntryContext) *TokenResult {
136136

137137
// execute rule based checking slot
138138
rcs := sc.ruleChecks
139-
ruleCheckRet := NewTokenResultPass()
139+
var ruleCheckRet *TokenResult
140140
if len(rcs) > 0 {
141141
for _, s := range rcs {
142+
if ruleCheckRet != nil {
143+
RefurbishTokenResult(ruleCheckRet)
144+
}
145+
142146
sr := s.Check(ctx)
143-
ctx.Output.LastResult = sr
147+
ruleCheckRet = sr
144148
// check slot result
145149
if sr.status == ResultStatusBlocked {
146-
ruleCheckRet = sr
147150
break
148151
}
149152

150153
// This slot passed, continue.
151154
}
152155
}
156+
if ruleCheckRet == nil {
157+
ruleCheckRet = NewTokenResultPass()
158+
}
153159
ctx.Output.LastResult = ruleCheckRet
154160

155161
// execute statistic slot

‎core/circuit_breaker/slot.go

+2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ func checkPass(ctx *base.EntryContext) *base.TokenResult {
2929
// Handle waiting action.
3030
time.Sleep(time.Duration(waitMs) * time.Millisecond)
3131
}
32+
base.RefurbishTokenResult(r)
3233
continue
3334
}
35+
base.RefurbishTokenResult(r)
3436
}
3537
return base.NewTokenResultPass()
3638
}

‎core/flow/slot.go

+2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ func (s *FlowSlot) Check(ctx *base.EntryContext) *base.TokenResult {
3333
// Handle waiting action.
3434
time.Sleep(time.Duration(waitMs) * time.Millisecond)
3535
}
36+
base.RefurbishTokenResult(r)
3637
continue
3738
}
39+
base.RefurbishTokenResult(r)
3840
}
3941
return base.NewTokenResultPass()
4042
}

‎go.mod

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ require (
99
github.com/fsnotify/fsnotify v1.4.7
1010
github.com/gin-gonic/gin v1.5.0
1111
github.com/go-ole/go-ole v1.2.4 // indirect
12-
github.com/labstack/echo/v4 v4.1.15
1312
github.com/google/uuid v1.1.1
13+
github.com/labstack/echo/v4 v4.1.15
1414
github.com/pkg/errors v0.8.1
1515
github.com/shirou/gopsutil v2.19.12+incompatible
1616
github.com/stretchr/testify v1.4.0
1717
go.uber.org/multierr v1.5.0
18+
golang.org/x/tools v0.0.0-20200428021058-7ae4988eb4d9 // indirect
1819
google.golang.org/grpc v1.22.1
1920
gopkg.in/yaml.v2 v2.2.2
2021
)

‎go.sum

+11
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy
340340
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
341341
github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
342342
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
343+
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
343344
github.com/zouyx/agollo v0.0.0-20191114083447-dde9fc9f35b8/go.mod h1:S1cAa98KMFv4Sa8SbJ6ZtvOmf0VlgH0QJ1gXI0lBfBY=
344345
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
345346
go.etcd.io/etcd v3.3.13+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI=
@@ -360,13 +361,16 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf
360361
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
361362
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
362363
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
364+
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
363365
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=
364366
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
365367
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
366368
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
367369
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
368370
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
369371
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
372+
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
373+
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
370374
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
371375
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
372376
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -388,6 +392,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
388392
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
389393
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
390394
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
395+
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
391396
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
392397
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
393398
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -422,7 +427,13 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw
422427
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
423428
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
424429
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
430+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
431+
golang.org/x/tools v0.0.0-20200428021058-7ae4988eb4d9 h1:nSSuQTxk9hjYf2koTs9mHZtYm2pu7Yt8WuIeKOrCWNI=
432+
golang.org/x/tools v0.0.0-20200428021058-7ae4988eb4d9/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
425433
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
434+
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
435+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
436+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
426437
google.golang.org/api v0.0.0-20180829000535-087779f1d2c9/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
427438
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
428439
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=

0 commit comments

Comments
 (0)
Please sign in to comment.