-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
util/goroutine_pool: add a goroutine pool package utilities #3752
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please test this with sysbench.
util/goroutine_pool/gp.go
Outdated
@@ -0,0 +1,181 @@ | |||
// Copyright 2016 PingCAP, Inc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2016 -> 2017
util/goroutine_pool/gp_test.go
Outdated
@@ -0,0 +1,131 @@ | |||
// Copyright 2016 PingCAP, Inc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2016 -> 2017
util/goroutine_pool/gp.go
Outdated
ch: make(chan func()), | ||
pool: pool, | ||
} | ||
go func(g *goroutine) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think defining a method for goroutine
is more clear.
util/goroutine_pool/gp.go
Outdated
return ret | ||
} | ||
|
||
func (pool *Pool) put(p *goroutine) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is called by goroutine
in background, I think make this a goroutine
method is more reasonable.
util/goroutine_pool/gp.go
Outdated
} | ||
|
||
func (pool *Pool) put(p *goroutine) { | ||
p.next = nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it always nil, encured by get
?
util/goroutine_pool/gp.go
Outdated
|
||
func (g *goroutine) put(pool *Pool) { | ||
g.status = statusIdle | ||
g.next = nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible that g.next
is not nil here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure.
|
||
ret := head.next | ||
head.next = ret.next | ||
if ret == pool.tail { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pool.count--
if pool.count == 0 {
pool.tail = head
}
is easier to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't intent to maintain count, it's added later just for testing purpose.
util/goroutine_pool/gp.go
Outdated
} | ||
// Status already changed from statusIdle => statusDying, delete this goroutine. | ||
if atomic.LoadInt32(&g.status) == statusDying { | ||
g.status = statusDead |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems no body cares about this value any more.
It can be removed.
util/goroutine_pool/gp.go
Outdated
for { | ||
g = pool.get() | ||
if atomic.CompareAndSwapInt32(&g.status, statusIdle, statusInUse) { | ||
break |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think just call
g.ch <-f
and return here is easier to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's easier to read indeed, but there is a potential race condition.
util/goroutine_pool/gp_test.go
Outdated
} | ||
|
||
func TestRace(t *testing.T) { | ||
gp := New(200 * time.Millisecond) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't the timeout too long to test race?
ec66a8f
to
ecf54ca
Compare
LGTM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Reuse goroutine in a pool can avoid
runtime.morestack
. It may be useful sometimes.