From e33ead2540b99701cb4b2b10d96a2a335ebf1408 Mon Sep 17 00:00:00 2001
From: James Rasell
Date: Fri, 11 Oct 2019 13:54:13 +0200
Subject: [PATCH] mod/vendor: update panjf2000/ants to latest v2 release.
---
go.mod | 2 +-
go.sum | 4 +-
pkg/autoscale/handler.go | 10 +-
vendor/github.com/panjf2000/ants/go.mod | 1 -
.../panjf2000/ants/{ => v2}/.gitignore | 0
.../panjf2000/ants/{ => v2}/.travis.yml | 2 +-
.../panjf2000/ants/v2/CODE_OF_CONDUCT.md | 76 +++++++++++++
.../panjf2000/ants/v2/CONTRIBUTING.md | 14 +++
.../panjf2000/ants/{ => v2}/LICENSE | 0
.../panjf2000/ants/{ => v2}/README.md | 105 ++++++++++++------
.../panjf2000/ants/{ => v2}/README_ZH.md | 99 +++++++++++------
.../panjf2000/ants/{ => v2}/ants.go | 60 ++++++++--
vendor/github.com/panjf2000/ants/v2/go.mod | 3 +
.../panjf2000/ants/v2/internal/spinlock.go | 28 +++++
.../panjf2000/ants/{ => v2}/pool.go | 80 +++++++------
.../panjf2000/ants/{ => v2}/pool_func.go | 88 +++++++--------
.../panjf2000/ants/{ => v2}/worker.go | 8 +-
.../panjf2000/ants/{ => v2}/worker_func.go | 8 +-
vendor/modules.txt | 5 +-
19 files changed, 403 insertions(+), 190 deletions(-)
delete mode 100644 vendor/github.com/panjf2000/ants/go.mod
rename vendor/github.com/panjf2000/ants/{ => v2}/.gitignore (100%)
rename vendor/github.com/panjf2000/ants/{ => v2}/.travis.yml (95%)
create mode 100644 vendor/github.com/panjf2000/ants/v2/CODE_OF_CONDUCT.md
create mode 100644 vendor/github.com/panjf2000/ants/v2/CONTRIBUTING.md
rename vendor/github.com/panjf2000/ants/{ => v2}/LICENSE (100%)
rename vendor/github.com/panjf2000/ants/{ => v2}/README.md (71%)
rename vendor/github.com/panjf2000/ants/{ => v2}/README_ZH.md (81%)
rename vendor/github.com/panjf2000/ants/{ => v2}/ants.go (72%)
create mode 100644 vendor/github.com/panjf2000/ants/v2/go.mod
create mode 100644 vendor/github.com/panjf2000/ants/v2/internal/spinlock.go
rename vendor/github.com/panjf2000/ants/{ => v2}/pool.go (84%)
rename vendor/github.com/panjf2000/ants/{ => v2}/pool_func.go (83%)
rename vendor/github.com/panjf2000/ants/{ => v2}/worker.go (94%)
rename vendor/github.com/panjf2000/ants/{ => v2}/worker_func.go (94%)
diff --git a/go.mod b/go.mod
index ce96c94..5fd7a38 100644
--- a/go.mod
+++ b/go.mod
@@ -15,7 +15,7 @@ require (
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/mattn/go-isatty v0.0.7
github.com/oklog/run v1.0.0
- github.com/panjf2000/ants v0.0.0-20190820151255-b60dfa8c16b0
+ github.com/panjf2000/ants/v2 v2.1.1
github.com/pkg/errors v0.8.1
github.com/rs/zerolog v1.14.3
github.com/ryanuber/columnize v2.1.0+incompatible
diff --git a/go.sum b/go.sum
index b175ecd..c9c38e6 100644
--- a/go.sum
+++ b/go.sum
@@ -100,8 +100,8 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
-github.com/panjf2000/ants v0.0.0-20190820151255-b60dfa8c16b0 h1:otVy5M/CL7sQJRx9MxpFq3feQp7AEgx1Hp4/RPBRqkE=
-github.com/panjf2000/ants v0.0.0-20190820151255-b60dfa8c16b0/go.mod h1:AaACblRPzq35m1g3enqYcxspbbiOJJYaxU2wMpm1cXY=
+github.com/panjf2000/ants/v2 v2.1.1 h1:Or1KjIoVSdiWAh9553KI6vmBoMqEo0lqRcwS9v86+ts=
+github.com/panjf2000/ants/v2 v2.1.1/go.mod h1:1GFm8bV8nyCQvU5K4WvBCTG1/YBFOD2VzjffD8fV55A=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
diff --git a/pkg/autoscale/handler.go b/pkg/autoscale/handler.go
index 5b3e5b1..ba14cc3 100644
--- a/pkg/autoscale/handler.go
+++ b/pkg/autoscale/handler.go
@@ -7,7 +7,7 @@ import (
"github.com/jrasell/sherpa/pkg/policy"
policyBackend "github.com/jrasell/sherpa/pkg/policy/backend"
"github.com/jrasell/sherpa/pkg/scale"
- "github.com/panjf2000/ants"
+ ants "github.com/panjf2000/ants/v2"
"github.com/rs/zerolog"
)
@@ -156,13 +156,7 @@ func (a *AutoScale) setScalingInProgressFalse() {
// createWorkerPool is responsible for building the ants goroutine worker pool with the number of
// threads controlled by the operator configured value.
func (a *AutoScale) createWorkerPool() (*ants.PoolWithFunc, error) {
- return ants.NewPoolWithFunc(
- ants.Options{
- Capacity: a.cfg.ScalingThreads,
- ExpiryDuration: 60 * time.Second,
- PoolFunc: a.workerPoolFunc(),
- },
- )
+ return ants.NewPoolWithFunc(a.cfg.ScalingThreads, a.workerPoolFunc(), ants.WithExpiryDuration(60*time.Second))
}
func (a *AutoScale) workerPoolFunc() func(payload interface{}) {
diff --git a/vendor/github.com/panjf2000/ants/go.mod b/vendor/github.com/panjf2000/ants/go.mod
deleted file mode 100644
index 53277c0..0000000
--- a/vendor/github.com/panjf2000/ants/go.mod
+++ /dev/null
@@ -1 +0,0 @@
-module github.com/panjf2000/ants
diff --git a/vendor/github.com/panjf2000/ants/.gitignore b/vendor/github.com/panjf2000/ants/v2/.gitignore
similarity index 100%
rename from vendor/github.com/panjf2000/ants/.gitignore
rename to vendor/github.com/panjf2000/ants/v2/.gitignore
diff --git a/vendor/github.com/panjf2000/ants/.travis.yml b/vendor/github.com/panjf2000/ants/v2/.travis.yml
similarity index 95%
rename from vendor/github.com/panjf2000/ants/.travis.yml
rename to vendor/github.com/panjf2000/ants/v2/.travis.yml
index 469e02e..494077a 100644
--- a/vendor/github.com/panjf2000/ants/.travis.yml
+++ b/vendor/github.com/panjf2000/ants/v2/.travis.yml
@@ -1,11 +1,11 @@
language: go
go:
- - "1.8.x"
- "1.9.x"
- "1.10.x"
- "1.11.x"
- "1.12.x"
+ - "1.13.x"
before_install:
- go get -t -v ./...
diff --git a/vendor/github.com/panjf2000/ants/v2/CODE_OF_CONDUCT.md b/vendor/github.com/panjf2000/ants/v2/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..2fccd5c
--- /dev/null
+++ b/vendor/github.com/panjf2000/ants/v2/CODE_OF_CONDUCT.md
@@ -0,0 +1,76 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, sex characteristics, gender identity and expression,
+level of experience, education, socio-economic status, nationality, personal
+appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at panjf2000@gmail.com. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see
+https://www.contributor-covenant.org/faq
diff --git a/vendor/github.com/panjf2000/ants/v2/CONTRIBUTING.md b/vendor/github.com/panjf2000/ants/v2/CONTRIBUTING.md
new file mode 100644
index 0000000..6911574
--- /dev/null
+++ b/vendor/github.com/panjf2000/ants/v2/CONTRIBUTING.md
@@ -0,0 +1,14 @@
+# Contributing
+
+## With issues:
+ - Use the search tool before opening a new issue.
+ - Please provide source code and commit sha if you found a bug.
+ - Review existing issues and provide feedback or react to them.
+
+## With pull requests:
+ - Open your pull request against `master`.
+ - Open one pull request for only one feature/proposal, if you have several those, please put them into different PRs, whereas you are allowed to open one pull request with several bug-fixs.
+ - Your pull request should have no more than two commits, if not, you should squash them.
+ - It should pass all tests in the available continuous integrations systems such as TravisCI.
+ - You should add/modify tests to cover your proposed code changes.
+ - If your pull request contains a new feature, please document it on the README.
diff --git a/vendor/github.com/panjf2000/ants/LICENSE b/vendor/github.com/panjf2000/ants/v2/LICENSE
similarity index 100%
rename from vendor/github.com/panjf2000/ants/LICENSE
rename to vendor/github.com/panjf2000/ants/v2/LICENSE
diff --git a/vendor/github.com/panjf2000/ants/README.md b/vendor/github.com/panjf2000/ants/v2/README.md
similarity index 71%
rename from vendor/github.com/panjf2000/ants/README.md
rename to vendor/github.com/panjf2000/ants/v2/README.md
index 466827e..7c153cb 100644
--- a/vendor/github.com/panjf2000/ants/README.md
+++ b/vendor/github.com/panjf2000/ants/v2/README.md
@@ -9,12 +9,13 @@ A goroutine pool for Go
-
+
+
-[中文](README_ZH.md) | [Project Blog](https://taohuawu.club/high-performance-implementation-of-goroutine-pool)
+# [[中文](README_ZH.md)]
Library `ants` implements a goroutine pool with fixed capacity, managing and recycling a massive number of goroutines, allowing developers to limit the number of goroutines in your concurrent programs.
@@ -25,6 +26,7 @@ Library `ants` implements a goroutine pool with fixed capacity, managing and rec
- Friendly interfaces: submitting tasks, getting the number of running goroutines, tuning capacity of pool dynamically, closing pool.
- Handle panic gracefully to prevent programs from crash.
- Efficient in memory usage and it even achieves higher performance than unlimited goroutines in golang.
+- Nonblocking mechanism.
## Tested in the following Golang versions:
@@ -33,6 +35,7 @@ Library `ants` implements a goroutine pool with fixed capacity, managing and rec
- 1.10.x
- 1.11.x
- 1.12.x
+- 1.13.x
## How to install
@@ -42,7 +45,7 @@ go get -u github.com/panjf2000/ants
```
## How to use
-Just take a imagination that your program starts a massive number of goroutines, from which a vast amount of memory will be consumed. To mitigate that kind of situation, all you need to do is to import `ants` package and submit all your tasks to a default pool with fixed capacity, activated when package `ants` is imported:
+Just take a imagination that your program starts a massive number of goroutines, resulting in a huge consumption of memory. To mitigate that kind of situation, all you need to do is to import `ants` package and submit all your tasks to a default pool with fixed capacity, activated when package `ants` is imported:
``` go
package main
@@ -53,7 +56,7 @@ import (
"sync/atomic"
"time"
- "github.com/panjf2000/ants"
+ "github.com/panjf2000/ants/v2"
)
var sum int32
@@ -88,12 +91,12 @@ func main() {
fmt.Printf("running goroutines: %d\n", ants.Running())
fmt.Printf("finish all tasks.\n")
- // Use the pool with a method,
+ // Use the pool with a function,
// set 10 to the capacity of goroutine pool and 1 second for expired duration.
- p, _ := ants.NewPoolWithFunc(ants.Options{Capacity: 10, PoolFunc: func(i interface{}) {
+ p, _ := ants.NewPoolWithFunc(10, func(i interface{}) {
myFunc(i)
wg.Done()
- }})
+ })
defer p.Release()
// Submit tasks one by one.
for i := 0; i < runTimes; i++ {
@@ -114,7 +117,7 @@ import (
"io/ioutil"
"net/http"
- "github.com/panjf2000/ants"
+ "github.com/panjf2000/ants/v2"
)
type Request struct {
@@ -123,7 +126,7 @@ type Request struct {
}
func main() {
- pool, _ := ants.NewPoolWithFunc(ants.Options{Capacity:100, PoolFunc:func(payload interface{}) {
+ pool, _ := ants.NewPoolWithFunc(100000, func(payload interface{}) {
request, ok := payload.(*Request)
if !ok {
return
@@ -136,7 +139,7 @@ func main() {
}(request.Param)
request.Result <- reverseParam
- }})
+ })
defer pool.Release()
http.HandleFunc("/reverse", func(w http.ResponseWriter, r *http.Request) {
@@ -161,13 +164,10 @@ func main() {
}
```
-## Options for ants pool
+## Functional options for ants pool
```go
type Options struct {
- // Capacity of the pool.
- Capacity int
-
// ExpiryDuration set the expired time (second) of every worker.
ExpiryDuration time.Duration
@@ -186,13 +186,46 @@ type Options struct {
// PanicHandler is used to handle panics from each worker goroutine.
// if nil, panics will be thrown out again from worker goroutines.
PanicHandler func(interface{})
+}
+
+func WithOptions(options Options) Option {
+ return func(opts *Options) {
+ *opts = options
+ }
+}
+
+func WithExpiryDuration(expiryDuration time.Duration) Option {
+ return func(opts *Options) {
+ opts.ExpiryDuration = expiryDuration
+ }
+}
+
+func WithPreAlloc(preAlloc bool) Option {
+ return func(opts *Options) {
+ opts.PreAlloc = preAlloc
+ }
+}
+
+func WithMaxBlockingTasks(maxBlockingTasks int) Option {
+ return func(opts *Options) {
+ opts.MaxBlockingTasks = maxBlockingTasks
+ }
+}
- // poolFunc is the function for processing tasks.
- PoolFunc func(interface{})
+func WithNonblocking(nonblocking bool) Option {
+ return func(opts *Options) {
+ opts.Nonblocking = nonblocking
+ }
+}
+
+func WithPanicHandler(panicHandler func(interface{})) Option {
+ return func(opts *Options) {
+ opts.PanicHandler = panicHandler
+ }
}
```
-`ants.Options`contains all configurations of ants pool, which allow you to customize the goroutine pool by setting up each field in it, then passing it to `NewPool`method.
+`ants.Options`contains all optional configurations of ants pool, which allows you to customize the goroutine pool by invoking option functions to set up each configuration in `NewPool`/`NewPoolWithFunc`method.
## Customize limited pool
@@ -200,7 +233,7 @@ type Options struct {
``` go
// Set 10000 the size of goroutine pool
-p, _ := ants.NewPool(ants.Options{Capacity: 10000})
+p, _ := ants.NewPool(10000)
```
## Submit tasks
@@ -221,11 +254,11 @@ Don't worry about the synchronous problems in this case, the method here is thre
## Pre-malloc goroutine queue in pool
-`ants` allows you to pre-allocate memory of goroutine queue in pool, which may get a performance enhancement under some special certain circumstances such as the scenario that requires an pool with ultra-large capacity, meanwhile each task in goroutine lasts for a long time, in this case, pre-mallocing will reduce a lot of costs when re-slicing goroutine queue.
+`ants` allows you to pre-allocate memory of goroutine queue in pool, which may get a performance enhancement under some special certain circumstances such as the scenario that requires a pool with ultra-large capacity, meanwhile each task in goroutine lasts for a long time, in this case, pre-mallocing will reduce a lot of costs when re-slicing goroutine queue.
```go
// ants will pre-malloc the whole capacity of pool when you invoke this method
-p, _ := ants.NewPool(ants.Options{Capacity: AntsSize, PreAlloc: true})
+p, _ := ants.NewPool(100000, ants.WithPreAlloc(true))
```
## Release Pool
@@ -239,36 +272,26 @@ All tasks submitted to `ants` pool will not be guaranteed to be addressed in ord
## Benchmarks
-```
-OS: macOS High Sierra
-Processor: 2.7 GHz Intel Core i5
-Memory: 8 GB 1867 MHz DDR3
-
-Go Version: 1.9
-```
-
- In that benchmark-picture, the first and second benchmarks performed test cases with 1M tasks and the rest of benchmarks performed test cases with 10M tasks, both in unlimited goroutines and `ants` pool, and the capacity of this `ants` goroutine-pool was limited to 50K.
+ In this benchmark-picture, the first and second benchmarks performed test cases with 1M tasks and the rest of benchmarks performed test cases with 10M tasks, both in unlimited goroutines and `ants` pool, and the capacity of this `ants` goroutine-pool was limited to 50K.
- BenchmarkGoroutine-4 represents the benchmarks with unlimited goroutines in golang.
- BenchmarkPoolGroutine-4 represents the benchmarks with a `ants` pool.
-The test data above is a basic benchmark and more detailed benchmarks are about to be uploaded later.
-
### Benchmarks with Pool
![](https://user-images.githubusercontent.com/7496278/51515499-f187c500-1e4e-11e9-80e5-3df8f94fa70f.png)
In above benchmark picture, the first and second benchmarks performed test cases with 1M tasks and the rest of benchmarks performed test cases with 10M tasks, both in unlimited goroutines and `ants` pool, and the capacity of this `ants` goroutine-pool was limited to 50K.
-**As you can see, `ants` can up to 2x faster than goroutines without pool (10M tasks) and it only consumes half the memory comparing with goroutines without pool. (both 1M and 10M tasks)**
+**As you can see, `ants` performs 2 times faster than goroutines without pool (10M tasks) and it only consumes half the memory comparing with goroutines without pool. (both in 1M and 10M tasks)**
### Benchmarks with PoolWithFunc
![](https://user-images.githubusercontent.com/7496278/51515565-1e3bdc80-1e4f-11e9-8a08-452ab91d117e.png)
-### Throughput (it is suitable for scenarios where asynchronous tasks are submitted despite of the final results)
+### Throughput (it is suitable for scenarios where tasks are submitted asynchronously without waiting for the final results)
#### 100K tasks
@@ -284,6 +307,18 @@ In above benchmark picture, the first and second benchmarks performed test cases
### Performance Summary
-![](https://user-images.githubusercontent.com/7496278/52989641-51b65a80-343f-11e9-86c0-e855d97343ea.gif)
+![](https://user-images.githubusercontent.com/7496278/63449727-3ae6d400-c473-11e9-81e3-8b3280d8288a.gif)
+
+**In conclusion, `ants` performs 2~6 times faster than goroutines without a pool and the memory consumption is reduced by 10 to 20 times.**
+
+# License
+
+Source code in `gnet` is available under the MIT [License](/LICENSE).
+
+# Relevant Articles
+
+- [Goroutine 并发调度模型深度解析之手撸一个高性能协程池](https://taohuawu.club/high-performance-implementation-of-goroutine-pool)
+
+# Users of ants (please feel free to add your projects here ~~)
-**In conclusion, `ants` can up to 2x~6x faster than goroutines without a pool and the memory consumption is reduced by 10 to 20 times.**
+[![](https://raw.githubusercontent.com/panjf2000/gnet/master/logo.png)](https://github.com/panjf2000/gnet)
\ No newline at end of file
diff --git a/vendor/github.com/panjf2000/ants/README_ZH.md b/vendor/github.com/panjf2000/ants/v2/README_ZH.md
similarity index 81%
rename from vendor/github.com/panjf2000/ants/README_ZH.md
rename to vendor/github.com/panjf2000/ants/v2/README_ZH.md
index 53b03e9..3cb47b7 100644
--- a/vendor/github.com/panjf2000/ants/README_ZH.md
+++ b/vendor/github.com/panjf2000/ants/v2/README_ZH.md
@@ -9,12 +9,13 @@ A goroutine pool for Go
-
+
+
-[英文](README.md) | [项目博客](https://taohuawu.club/high-performance-implementation-of-goroutine-pool)
+# [[英文](README.md)]
`ants`是一个高性能的协程池,实现了对大规模 goroutine 的调度管理、goroutine 复用,允许使用者在开发并发程序的时候限制协程数量,复用资源,达到更高效执行任务的效果。
@@ -25,6 +26,7 @@ A goroutine pool for Go
- 提供了友好的接口:任务提交、获取运行中的协程数量、动态调整协程池大小
- 优雅处理 panic,防止程序崩溃
- 资源复用,极大节省内存使用量;在大规模批量并发任务场景下比原生 goroutine 并发具有更高的性能
+- 非阻塞机制
## 目前测试通过的Golang版本:
@@ -33,6 +35,7 @@ A goroutine pool for Go
- 1.10.x
- 1.11.x
- 1.12.x
+- 1.13.x
## 安装
@@ -53,7 +56,7 @@ import (
"sync/atomic"
"time"
- "github.com/panjf2000/ants"
+ "github.com/panjf2000/ants/v2"
)
var sum int32
@@ -88,12 +91,12 @@ func main() {
fmt.Printf("running goroutines: %d\n", ants.Running())
fmt.Printf("finish all tasks.\n")
- // Use the pool with a method,
+ // Use the pool with a function,
// set 10 to the capacity of goroutine pool and 1 second for expired duration.
- p, _ := ants.NewPoolWithFunc(ants.Options{Capacity: 10, PoolFunc: func(i interface{}) {
+ p, _ := ants.NewPoolWithFunc(10, func(i interface{}) {
myFunc(i)
wg.Done()
- }})
+ })
defer p.Release()
// Submit tasks one by one.
for i := 0; i < runTimes; i++ {
@@ -114,7 +117,7 @@ import (
"io/ioutil"
"net/http"
- "github.com/panjf2000/ants"
+ "github.com/panjf2000/ants/v2"
)
type Request struct {
@@ -123,7 +126,7 @@ type Request struct {
}
func main() {
- pool, _ := ants.NewPoolWithFunc(ants.Options{Capacity:100, PoolFunc:func(payload interface{}) {
+ pool, _ := ants.NewPoolWithFunc(100000, func(payload interface{}) {
request, ok := payload.(*Request)
if !ok {
return
@@ -136,7 +139,7 @@ func main() {
}(request.Param)
request.Result <- reverseParam
- }})
+ })
defer pool.Release()
http.HandleFunc("/reverse", func(w http.ResponseWriter, r *http.Request) {
@@ -165,9 +168,6 @@ func main() {
```go
type Options struct {
- // Capacity of the pool.
- Capacity int
-
// ExpiryDuration set the expired time (second) of every worker.
ExpiryDuration time.Duration
@@ -186,13 +186,46 @@ type Options struct {
// PanicHandler is used to handle panics from each worker goroutine.
// if nil, panics will be thrown out again from worker goroutines.
PanicHandler func(interface{})
+}
+
+func WithOptions(options Options) Option {
+ return func(opts *Options) {
+ *opts = options
+ }
+}
+
+func WithExpiryDuration(expiryDuration time.Duration) Option {
+ return func(opts *Options) {
+ opts.ExpiryDuration = expiryDuration
+ }
+}
+
+func WithPreAlloc(preAlloc bool) Option {
+ return func(opts *Options) {
+ opts.PreAlloc = preAlloc
+ }
+}
+
+func WithMaxBlockingTasks(maxBlockingTasks int) Option {
+ return func(opts *Options) {
+ opts.MaxBlockingTasks = maxBlockingTasks
+ }
+}
+
+func WithNonblocking(nonblocking bool) Option {
+ return func(opts *Options) {
+ opts.Nonblocking = nonblocking
+ }
+}
- // poolFunc is the function for processing tasks.
- PoolFunc func(interface{})
+func WithPanicHandler(panicHandler func(interface{})) Option {
+ return func(opts *Options) {
+ opts.PanicHandler = panicHandler
+ }
}
```
-你可以根据自己的需求在`ants.Options`中设置各个配置项的值,然后用它来初始化 goroutine pool.
+通过在调用`NewPool`/`NewPoolWithFunc`之时使用各种 optional function,可以设置`ants.Options`中各个配置项的值,然后用它来定制化 goroutine pool.
## 自定义池
@@ -200,7 +233,7 @@ type Options struct {
``` go
// Set 10000 the size of goroutine pool
-p, _ := ants.NewPool(ants.Options{Capacity: 10000})
+p, _ := ants.NewPool(10000)
```
## 任务提交
@@ -226,7 +259,7 @@ pool.Tune(100000) // Tune its capacity to 100000
```go
// ants will pre-malloc the whole capacity of pool when you invoke this function
-p, _ := ants.NewPool(ants.Options{Capacity: AntsSize, PreAlloc: true})
+p, _ := ants.NewPool(100000, ants.WithPreAlloc(true))
```
@@ -239,24 +272,12 @@ pool.Release()
## Benchmarks
-系统参数:
-
-```
-OS: macOS High Sierra
-Processor: 2.7 GHz Intel Core i5
-Memory: 8 GB 1867 MHz DDR3
-
-Go Version: 1.9
-```
-
-
-
-上图中的前两个 benchmark 测试结果是基于100w 任务量的条件,剩下的几个是基于 1000w 任务量的测试结果,`ants`的默认池容量是 5w。
+上图中的前两个 benchmark 测试结果是基于100w 任务量的条件,剩下的几个是基于 1000w 任务量的测试结果,`ants` 的默认池容量是 5w。
- BenchmarkGoroutine-4 代表原生 goroutine
-- BenchmarkPoolGroutine-4 代表使用协程池`ants`
+- BenchmarkPoolGroutine-4 代表使用协程池 `ants`
### Benchmarks with Pool
@@ -286,6 +307,18 @@ Go Version: 1.9
### 性能小结
-![](https://user-images.githubusercontent.com/7496278/52989641-51b65a80-343f-11e9-86c0-e855d97343ea.gif)
+![](https://user-images.githubusercontent.com/7496278/63449727-3ae6d400-c473-11e9-81e3-8b3280d8288a.gif)
+
+**从该 demo 测试吞吐性能对比可以看出,使用`ants`的吞吐性能相较于原生 goroutine 可以保持在 2-6 倍的性能压制,而内存消耗则可以达到 10-20 倍的节省优势。**
+
+# 证书
+
+`gnet` 的源码允许用户在遵循 MIT [开源证书](/LICENSE) 规则的前提下使用。
+
+# 相关文章
+
+- [Goroutine 并发调度模型深度解析之手撸一个高性能协程池](https://taohuawu.club/high-performance-implementation-of-goroutine-pool)
+
+# 谁在使用 ants(欢迎补充 ~~)
-**从该 demo 测试吞吐性能对比可以看出,使用`ants`的吞吐性能相较于原生 goroutine 可以保持在 2-6 倍的性能压制,而内存消耗则可以达到 10-20 倍的节省优势。**
\ No newline at end of file
+[![](https://raw.githubusercontent.com/panjf2000/gnet/master/logo.png)](https://github.com/panjf2000/gnet)
\ No newline at end of file
diff --git a/vendor/github.com/panjf2000/ants/ants.go b/vendor/github.com/panjf2000/ants/v2/ants.go
similarity index 72%
rename from vendor/github.com/panjf2000/ants/ants.go
rename to vendor/github.com/panjf2000/ants/v2/ants.go
index 5031c86..38a0dca 100644
--- a/vendor/github.com/panjf2000/ants/ants.go
+++ b/vendor/github.com/panjf2000/ants/v2/ants.go
@@ -30,11 +30,11 @@ import (
)
const (
- // DEFAULT_ANTS_POOL_SIZE is the default capacity for a default goroutine pool.
- DEFAULT_ANTS_POOL_SIZE = math.MaxInt32
+ // DefaultAntsPoolSize is the default capacity for a default goroutine pool.
+ DefaultAntsPoolSize = math.MaxInt32
- // DEFAULT_CLEAN_INTERVAL_TIME is the interval time to clean up goroutines.
- DEFAULT_CLEAN_INTERVAL_TIME = 1
+ // DefaultCleanIntervalTime is the interval time to clean up goroutines.
+ DefaultCleanIntervalTime = time.Second
// CLOSED represents that the pool is closed.
CLOSED = 1
@@ -77,13 +77,14 @@ var (
}()
// Init a instance pool when importing ants.
- defaultAntsPool, _ = NewPool(Options{Capacity: DEFAULT_ANTS_POOL_SIZE})
+ defaultAntsPool, _ = NewPool(DefaultAntsPoolSize)
)
-type Options struct {
- // Capacity of the pool.
- Capacity int
+// Option represents the optional function.
+type Option func(opts *Options)
+// Options contains all options which will be applied when instantiating a ants pool.
+type Options struct {
// ExpiryDuration set the expired time (second) of every worker.
ExpiryDuration time.Duration
@@ -102,9 +103,48 @@ type Options struct {
// PanicHandler is used to handle panics from each worker goroutine.
// if nil, panics will be thrown out again from worker goroutines.
PanicHandler func(interface{})
+}
+
+// WithOptions accepts the whole options config.
+func WithOptions(options Options) Option {
+ return func(opts *Options) {
+ *opts = options
+ }
+}
+
+// WithExpiryDuration sets up the interval time of cleaning up goroutines.
+func WithExpiryDuration(expiryDuration time.Duration) Option {
+ return func(opts *Options) {
+ opts.ExpiryDuration = expiryDuration
+ }
+}
+
+// WithPreAlloc indicates whether it should malloc for workers.
+func WithPreAlloc(preAlloc bool) Option {
+ return func(opts *Options) {
+ opts.PreAlloc = preAlloc
+ }
+}
+
+// WithMaxBlockingTasks sets up the maximum number of goroutines that are blocked when it reaches the capacity of pool.
+func WithMaxBlockingTasks(maxBlockingTasks int) Option {
+ return func(opts *Options) {
+ opts.MaxBlockingTasks = maxBlockingTasks
+ }
+}
+
+// WithNonblocking indicates that pool will return nil when there is no available workers.
+func WithNonblocking(nonblocking bool) Option {
+ return func(opts *Options) {
+ opts.Nonblocking = nonblocking
+ }
+}
- // PoolFunc is the function for processing tasks.
- PoolFunc func(interface{})
+// WithPanicHandler sets up panic handler.
+func WithPanicHandler(panicHandler func(interface{})) Option {
+ return func(opts *Options) {
+ opts.PanicHandler = panicHandler
+ }
}
// Submit submits a task to pool.
diff --git a/vendor/github.com/panjf2000/ants/v2/go.mod b/vendor/github.com/panjf2000/ants/v2/go.mod
new file mode 100644
index 0000000..201c358
--- /dev/null
+++ b/vendor/github.com/panjf2000/ants/v2/go.mod
@@ -0,0 +1,3 @@
+module github.com/panjf2000/ants/v2
+
+go 1.12
diff --git a/vendor/github.com/panjf2000/ants/v2/internal/spinlock.go b/vendor/github.com/panjf2000/ants/v2/internal/spinlock.go
new file mode 100644
index 0000000..16607ef
--- /dev/null
+++ b/vendor/github.com/panjf2000/ants/v2/internal/spinlock.go
@@ -0,0 +1,28 @@
+// Copyright 2019 Andy Pan. All rights reserved.
+// Use of this source code is governed by an MIT-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "runtime"
+ "sync"
+ "sync/atomic"
+)
+
+type spinLock uint32
+
+func (sl *spinLock) Lock() {
+ for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) {
+ runtime.Gosched()
+ }
+}
+
+func (sl *spinLock) Unlock() {
+ atomic.StoreUint32((*uint32)(sl), 0)
+}
+
+// NewSpinLock instantiates a spin-lock.
+func NewSpinLock() sync.Locker {
+ return new(spinLock)
+}
diff --git a/vendor/github.com/panjf2000/ants/pool.go b/vendor/github.com/panjf2000/ants/v2/pool.go
similarity index 84%
rename from vendor/github.com/panjf2000/ants/pool.go
rename to vendor/github.com/panjf2000/ants/v2/pool.go
index 91b7d7d..3f52a86 100644
--- a/vendor/github.com/panjf2000/ants/pool.go
+++ b/vendor/github.com/panjf2000/ants/v2/pool.go
@@ -26,6 +26,8 @@ import (
"sync"
"sync/atomic"
"time"
+
+ "github.com/panjf2000/ants/v2/internal"
)
// Pool accept the tasks from client, it limits the total of goroutines to a given number by recycling goroutines.
@@ -46,7 +48,7 @@ type Pool struct {
release int32
// lock for synchronous operation.
- lock sync.Mutex
+ lock sync.Locker
// cond for waiting to get a idle worker.
cond *sync.Cond
@@ -89,9 +91,8 @@ func (p *Pool) periodicallyPurge() {
p.lock.Lock()
idleWorkers := p.workers
n := len(idleWorkers)
- i := 0
- for i < n && currentTime.Sub(idleWorkers[i].recycleTime) > p.expiryDuration {
- i++
+ var i int
+ for i = 0; i < n && currentTime.Sub(idleWorkers[i].recycleTime) > p.expiryDuration; i++ {
}
expiredWorkers = append(expiredWorkers[:0], idleWorkers[:i]...)
if i > 0 {
@@ -122,37 +123,42 @@ func (p *Pool) periodicallyPurge() {
}
// NewPool generates an instance of ants pool.
-func NewPool(opts Options) (*Pool, error) {
- if opts.Capacity <= 0 {
+func NewPool(size int, options ...Option) (*Pool, error) {
+ if size <= 0 {
return nil, ErrInvalidPoolSize
}
+ opts := new(Options)
+ for _, option := range options {
+ option(opts)
+ }
+
if expiry := opts.ExpiryDuration; expiry < 0 {
return nil, ErrInvalidPoolExpiry
} else if expiry == 0 {
- opts.ExpiryDuration = time.Duration(DEFAULT_CLEAN_INTERVAL_TIME) * time.Second
+ opts.ExpiryDuration = DefaultCleanIntervalTime
}
- var p *Pool
+ p := &Pool{
+ capacity: int32(size),
+ expiryDuration: opts.ExpiryDuration,
+ nonblocking: opts.Nonblocking,
+ maxBlockingTasks: int32(opts.MaxBlockingTasks),
+ panicHandler: opts.PanicHandler,
+ lock: internal.NewSpinLock(),
+ }
+ p.workerCache = sync.Pool{
+ New: func() interface{} {
+ return &goWorker{
+ pool: p,
+ task: make(chan func(), workerChanCap),
+ }
+ },
+ }
if opts.PreAlloc {
- p = &Pool{
- capacity: int32(opts.Capacity),
- expiryDuration: opts.ExpiryDuration,
- workers: make([]*goWorker, 0, opts.Capacity),
- nonblocking: opts.Nonblocking,
- maxBlockingTasks: int32(opts.MaxBlockingTasks),
- panicHandler: opts.PanicHandler,
- }
- } else {
- p = &Pool{
- capacity: int32(opts.Capacity),
- expiryDuration: opts.ExpiryDuration,
- nonblocking: opts.Nonblocking,
- maxBlockingTasks: int32(opts.MaxBlockingTasks),
- panicHandler: opts.PanicHandler,
- }
+ p.workers = make([]*goWorker, 0, size)
}
- p.cond = sync.NewCond(&p.lock)
+ p.cond = sync.NewCond(p.lock)
// Start a goroutine to clean up expired workers periodically.
go p.periodicallyPurge()
@@ -167,11 +173,11 @@ func (p *Pool) Submit(task func()) error {
if atomic.LoadInt32(&p.release) == CLOSED {
return ErrPoolClosed
}
- if w := p.retrieveWorker(); w == nil {
+ var w *goWorker
+ if w = p.retrieveWorker(); w == nil {
return ErrPoolOverload
- } else {
- w.task <- task
}
+ w.task <- task
return nil
}
@@ -182,7 +188,7 @@ func (p *Pool) Running() int {
// Free returns the available goroutines to work.
func (p *Pool) Free() int {
- return int(atomic.LoadInt32(&p.capacity) - atomic.LoadInt32(&p.running))
+ return p.Cap() - p.Running()
}
// Cap returns the capacity of this pool.
@@ -196,10 +202,6 @@ func (p *Pool) Tune(size int) {
return
}
atomic.StoreInt32(&p.capacity, int32(size))
- diff := p.Running() - size
- for i := 0; i < diff; i++ {
- p.retrieveWorker().task <- nil
- }
}
// Release Closes this pool.
@@ -233,14 +235,7 @@ func (p *Pool) decRunning() {
func (p *Pool) retrieveWorker() *goWorker {
var w *goWorker
spawnWorker := func() {
- if cacheWorker := p.workerCache.Get(); cacheWorker != nil {
- w = cacheWorker.(*goWorker)
- } else {
- w = &goWorker{
- pool: p,
- task: make(chan func(), workerChanCap),
- }
- }
+ w = p.workerCache.Get().(*goWorker)
w.run()
}
@@ -287,12 +282,13 @@ func (p *Pool) retrieveWorker() *goWorker {
// revertWorker puts a worker back into free pool, recycling the goroutines.
func (p *Pool) revertWorker(worker *goWorker) bool {
- if atomic.LoadInt32(&p.release) == CLOSED {
+ if atomic.LoadInt32(&p.release) == CLOSED || p.Running() > p.Cap() {
return false
}
worker.recycleTime = time.Now()
p.lock.Lock()
p.workers = append(p.workers, worker)
+
// Notify the invoker stuck in 'retrieveWorker()' of there is an available worker in the worker queue.
p.cond.Signal()
p.lock.Unlock()
diff --git a/vendor/github.com/panjf2000/ants/pool_func.go b/vendor/github.com/panjf2000/ants/v2/pool_func.go
similarity index 83%
rename from vendor/github.com/panjf2000/ants/pool_func.go
rename to vendor/github.com/panjf2000/ants/v2/pool_func.go
index 3360c62..b174d21 100644
--- a/vendor/github.com/panjf2000/ants/pool_func.go
+++ b/vendor/github.com/panjf2000/ants/v2/pool_func.go
@@ -26,6 +26,8 @@ import (
"sync"
"sync/atomic"
"time"
+
+ "github.com/panjf2000/ants/v2/internal"
)
// PoolWithFunc accept the tasks from client, it limits the total of goroutines to a given number by recycling goroutines.
@@ -46,7 +48,7 @@ type PoolWithFunc struct {
release int32
// lock for synchronous operation.
- lock sync.Mutex
+ lock sync.Locker
// cond for waiting to get a idle worker.
cond *sync.Cond
@@ -92,9 +94,8 @@ func (p *PoolWithFunc) periodicallyPurge() {
p.lock.Lock()
idleWorkers := p.workers
n := len(idleWorkers)
- i := 0
- for i < n && currentTime.Sub(idleWorkers[i].recycleTime) > p.expiryDuration {
- i++
+ var i int
+ for i = 0; i < n && currentTime.Sub(idleWorkers[i].recycleTime) > p.expiryDuration; i++ {
}
expiredWorkers = append(expiredWorkers[:0], idleWorkers[:i]...)
if i > 0 {
@@ -125,44 +126,51 @@ func (p *PoolWithFunc) periodicallyPurge() {
}
// NewPoolWithFunc generates an instance of ants pool with a specific function.
-func NewPoolWithFunc(opts Options) (*PoolWithFunc, error) {
- if opts.Capacity <= 0 {
+func NewPoolWithFunc(size int, pf func(interface{}), options ...Option) (*PoolWithFunc, error) {
+ if size <= 0 {
return nil, ErrInvalidPoolSize
}
- if opts.PoolFunc == nil {
+ if pf == nil {
return nil, ErrLackPoolFunc
}
+ opts := new(Options)
+ for _, option := range options {
+ option(opts)
+ }
+
if expiry := opts.ExpiryDuration; expiry < 0 {
return nil, ErrInvalidPoolExpiry
} else if expiry == 0 {
- opts.ExpiryDuration = time.Duration(DEFAULT_CLEAN_INTERVAL_TIME) * time.Second
+ opts.ExpiryDuration = DefaultCleanIntervalTime
}
- var p *PoolWithFunc
+ p := &PoolWithFunc{
+ capacity: int32(size),
+ expiryDuration: opts.ExpiryDuration,
+ poolFunc: pf,
+ nonblocking: opts.Nonblocking,
+ maxBlockingTasks: int32(opts.MaxBlockingTasks),
+ panicHandler: opts.PanicHandler,
+ lock: internal.NewSpinLock(),
+ }
+ p.workerCache = sync.Pool{
+ New: func() interface{} {
+ return &goWorkerWithFunc{
+ pool: p,
+ args: make(chan interface{}, workerChanCap),
+ }
+ },
+ }
if opts.PreAlloc {
- p = &PoolWithFunc{
- capacity: int32(opts.Capacity),
- expiryDuration: opts.ExpiryDuration,
- poolFunc: opts.PoolFunc,
- workers: make([]*goWorkerWithFunc, 0, opts.Capacity),
- nonblocking: opts.Nonblocking,
- maxBlockingTasks: int32(opts.MaxBlockingTasks),
- panicHandler: opts.PanicHandler,
- }
- } else {
- p = &PoolWithFunc{
- capacity: int32(opts.Capacity),
- expiryDuration: opts.ExpiryDuration,
- poolFunc: opts.PoolFunc,
- nonblocking: opts.Nonblocking,
- maxBlockingTasks: int32(opts.MaxBlockingTasks),
- panicHandler: opts.PanicHandler,
- }
+ p.workers = make([]*goWorkerWithFunc, 0, size)
}
- p.cond = sync.NewCond(&p.lock)
+ p.cond = sync.NewCond(p.lock)
+
+ // Start a goroutine to clean up expired workers periodically.
go p.periodicallyPurge()
+
return p, nil
}
@@ -173,11 +181,11 @@ func (p *PoolWithFunc) Invoke(args interface{}) error {
if atomic.LoadInt32(&p.release) == CLOSED {
return ErrPoolClosed
}
- if w := p.retrieveWorker(); w == nil {
+ var w *goWorkerWithFunc
+ if w = p.retrieveWorker(); w == nil {
return ErrPoolOverload
- } else {
- w.args <- args
}
+ w.args <- args
return nil
}
@@ -188,7 +196,7 @@ func (p *PoolWithFunc) Running() int {
// Free returns a available goroutines to work.
func (p *PoolWithFunc) Free() int {
- return int(atomic.LoadInt32(&p.capacity) - atomic.LoadInt32(&p.running))
+ return p.Cap() - p.Running()
}
// Cap returns the capacity of this pool.
@@ -202,10 +210,6 @@ func (p *PoolWithFunc) Tune(size int) {
return
}
atomic.StoreInt32(&p.capacity, int32(size))
- diff := p.Running() - size
- for i := 0; i < diff; i++ {
- p.retrieveWorker().args <- nil
- }
}
// Release Closed this pool.
@@ -239,14 +243,7 @@ func (p *PoolWithFunc) decRunning() {
func (p *PoolWithFunc) retrieveWorker() *goWorkerWithFunc {
var w *goWorkerWithFunc
spawnWorker := func() {
- if cacheWorker := p.workerCache.Get(); cacheWorker != nil {
- w = cacheWorker.(*goWorkerWithFunc)
- } else {
- w = &goWorkerWithFunc{
- pool: p,
- args: make(chan interface{}, workerChanCap),
- }
- }
+ w = p.workerCache.Get().(*goWorkerWithFunc)
w.run()
}
@@ -293,12 +290,13 @@ func (p *PoolWithFunc) retrieveWorker() *goWorkerWithFunc {
// revertWorker puts a worker back into free pool, recycling the goroutines.
func (p *PoolWithFunc) revertWorker(worker *goWorkerWithFunc) bool {
- if atomic.LoadInt32(&p.release) == CLOSED {
+ if atomic.LoadInt32(&p.release) == CLOSED || p.Running() > p.Cap() {
return false
}
worker.recycleTime = time.Now()
p.lock.Lock()
p.workers = append(p.workers, worker)
+
// Notify the invoker stuck in 'retrieveWorker()' of there is an available worker in the worker queue.
p.cond.Signal()
p.lock.Unlock()
diff --git a/vendor/github.com/panjf2000/ants/worker.go b/vendor/github.com/panjf2000/ants/v2/worker.go
similarity index 94%
rename from vendor/github.com/panjf2000/ants/worker.go
rename to vendor/github.com/panjf2000/ants/v2/worker.go
index b79d9b8..f38e9d2 100644
--- a/vendor/github.com/panjf2000/ants/worker.go
+++ b/vendor/github.com/panjf2000/ants/v2/worker.go
@@ -48,9 +48,8 @@ func (w *goWorker) run() {
w.pool.incRunning()
go func() {
defer func() {
+ w.pool.decRunning()
if p := recover(); p != nil {
- w.pool.decRunning()
- w.pool.workerCache.Put(w)
if w.pool.panicHandler != nil {
w.pool.panicHandler(p)
} else {
@@ -60,17 +59,16 @@ func (w *goWorker) run() {
log.Printf("worker exits from panic: %s\n", string(buf[:n]))
}
}
+ w.pool.workerCache.Put(w)
}()
for f := range w.task {
if f == nil {
- w.pool.decRunning()
- w.pool.workerCache.Put(w)
return
}
f()
if ok := w.pool.revertWorker(w); !ok {
- break
+ return
}
}
}()
diff --git a/vendor/github.com/panjf2000/ants/worker_func.go b/vendor/github.com/panjf2000/ants/v2/worker_func.go
similarity index 94%
rename from vendor/github.com/panjf2000/ants/worker_func.go
rename to vendor/github.com/panjf2000/ants/v2/worker_func.go
index befd966..4c56ae8 100644
--- a/vendor/github.com/panjf2000/ants/worker_func.go
+++ b/vendor/github.com/panjf2000/ants/v2/worker_func.go
@@ -48,9 +48,8 @@ func (w *goWorkerWithFunc) run() {
w.pool.incRunning()
go func() {
defer func() {
+ w.pool.decRunning()
if p := recover(); p != nil {
- w.pool.decRunning()
- w.pool.workerCache.Put(w)
if w.pool.panicHandler != nil {
w.pool.panicHandler(p)
} else {
@@ -60,17 +59,16 @@ func (w *goWorkerWithFunc) run() {
log.Printf("worker with func exits from panic: %s\n", string(buf[:n]))
}
}
+ w.pool.workerCache.Put(w)
}()
for args := range w.args {
if args == nil {
- w.pool.decRunning()
- w.pool.workerCache.Put(w)
return
}
w.pool.poolFunc(args)
if ok := w.pool.revertWorker(w); !ok {
- break
+ return
}
}
}()
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 2a588fc..28af56c 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -48,8 +48,9 @@ github.com/mitchellh/go-homedir
github.com/mitchellh/mapstructure
# github.com/oklog/run v1.0.0
github.com/oklog/run
-# github.com/panjf2000/ants v0.0.0-20190820151255-b60dfa8c16b0
-github.com/panjf2000/ants
+# github.com/panjf2000/ants/v2 v2.1.1
+github.com/panjf2000/ants/v2
+github.com/panjf2000/ants/v2/internal
# github.com/pelletier/go-toml v1.2.0
github.com/pelletier/go-toml
# github.com/pkg/errors v0.8.1