diff --git a/.github/ISSUE_TEMPLATE/bug-report.yaml b/.github/ISSUE_TEMPLATE/bug-report.yaml index 89b75ae..2a4a59c 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yaml +++ b/.github/ISSUE_TEMPLATE/bug-report.yaml @@ -11,7 +11,7 @@ body: value: | ## Before you go any further - Please read [*How To Ask Questions The Smart Way*](http://www.catb.org/~esr/faqs/smart-questions.html) ( Chinese translation: [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md)) before you file an issue formally. - - Keep in mind that there is always welcome to ask questions on [Gitter](https://gitter.im/ants-pool/ants). + - Keep in mind that there is always welcome to ask questions on [Discord](https://discord.gg/Cuy7KPaWQc). - type: checkboxes id: checklist attributes: diff --git a/.github/ISSUE_TEMPLATE/feature-request.yaml b/.github/ISSUE_TEMPLATE/feature-request.yaml index eadc2d5..0d92e4d 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yaml +++ b/.github/ISSUE_TEMPLATE/feature-request.yaml @@ -11,7 +11,7 @@ body: value: | ## Before you go any further - Please read [*How To Ask Questions The Smart Way*](http://www.catb.org/~esr/faqs/smart-questions.html) ( Chinese translation: [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md)) before you file an issue formally. - - Keep in mind that there is always welcome to ask questions on [Gitter](https://gitter.im/ants-pool/ants). + - Keep in mind that there is always welcome to ask questions on [Discord](https://discord.gg/Cuy7KPaWQc). - type: textarea id: feature-request attributes: diff --git a/.github/ISSUE_TEMPLATE/question.yaml b/.github/ISSUE_TEMPLATE/question.yaml index ed605e3..df18ea7 100644 --- a/.github/ISSUE_TEMPLATE/question.yaml +++ b/.github/ISSUE_TEMPLATE/question.yaml @@ -9,7 +9,7 @@ body: value: | ## Before you go any further - Please read [*How To Ask Questions The Smart Way*](http://www.catb.org/~esr/faqs/smart-questions.html) ( Chinese translation: [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md)) before you file an issue formally. - - Keep in mind that there is always welcome to ask questions on [Gitter](https://gitter.im/ants-pool/ants). + - Keep in mind that there is always welcome to ask questions on [Discord](https://discord.gg/Cuy7KPaWQc). - type: textarea id: question attributes: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 56a7542..c1df467 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -42,20 +42,20 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: go # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). # If this step fails, then you should remove it and run the build manually (see below). - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -69,4 +69,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 \ No newline at end of file + uses: github/codeql-action/analyze@v3 \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 33ff07a..d304abe 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,17 +37,17 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Setup Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: go-version: '^1.16' - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup and run golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.51.2 + version: v1.55.2 args: --timeout 5m -v -E gofumpt -E gocritic -E misspell -E revive -E godot test: needs: lint @@ -60,12 +60,12 @@ jobs: runs-on: ${{ matrix.os}} steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.ref }} - name: Setup Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: go-version: ${{ matrix.go }} @@ -83,7 +83,7 @@ jobs: echo "GO_CACHE=$(go env GOCACHE)" >> $GITHUB_OUTPUT - name: Cache go modules - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ${{ steps.go-env.outputs.GO_CACHE }} @@ -96,11 +96,12 @@ jobs: run: go test -v -race -coverprofile="codecov.report" -covermode=atomic - name: Upload code coverage report to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: file: ./codecov.report flags: unittests name: codecov-ants fail_ci_if_error: true verbose: true - + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/README.md b/README.md index bacefbd..b06a61e 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@
- @@ -122,6 +121,39 @@ func main() { wg.Wait() fmt.Printf("running goroutines: %d\n", p.Running()) fmt.Printf("finish all tasks, result is %d\n", sum) + if sum != 499500 { + panic("the final result is wrong!!!") + } + + // Use the MultiPool and set the capacity of the 10 goroutine pools to unlimited. + // If you use -1 as the pool size parameter, the size will be unlimited. + // There are two load-balancing algorithms for pools: ants.RoundRobin and ants.LeastTasks. + mp, _ := ants.NewMultiPool(10, -1, ants.RoundRobin) + defer mp.ReleaseTimeout(5 * time.Second) + for i := 0; i < runTimes; i++ { + wg.Add(1) + _ = mp.Submit(syncCalculateSum) + } + wg.Wait() + fmt.Printf("running goroutines: %d\n", mp.Running()) + fmt.Printf("finish all tasks.\n") + + // Use the MultiPoolFunc and set the capacity of 10 goroutine pools to (runTimes/10). + mpf, _ := ants.NewMultiPoolWithFunc(10, runTimes/10, func(i interface{}) { + myFunc(i) + wg.Done() + }, ants.LeastTasks) + defer mpf.ReleaseTimeout(5 * time.Second) + for i := 0; i < runTimes; i++ { + wg.Add(1) + _ = mpf.Invoke(int32(i)) + } + wg.Wait() + fmt.Printf("running goroutines: %d\n", mpf.Running()) + fmt.Printf("finish all tasks, result is %d\n", sum) + if sum != 499500*2 { + panic("the final result is wrong!!!") + } } ``` @@ -327,7 +359,7 @@ The source code in `ants` is available under the [MIT License](/LICENSE). The following companies/organizations use `ants` in production. -                         +                           ### open-source software @@ -351,6 +383,8 @@ The open-source projects below do concurrent programming with the help of `ants` - [AdGuardDNS](https://github.com/AdguardTeam/AdGuardDNS): AdGuard DNS is an alternative solution for tracker blocking, privacy protection, and parental control. - [WatchAD2.0](https://github.com/Qihoo360/WatchAD2.0): WatchAD2.0 是 360 信息安全中心开发的一款针对域安全的日志分析与监控系统,它可以收集所有域控上的事件日志、网络流量,通过特征匹配、协议分析、历史行为、敏感操作和蜜罐账户等方式来检测各种已知与未知威胁,功能覆盖了大部分目前的常见内网域渗透手法。 - [vanus](https://github.com/vanus-labs/vanus): Vanus is a Serverless, event streaming system with processing capabilities. It easily connects SaaS, Cloud Services, and Databases to help users build next-gen Event-driven Applications. +- [trpc-go](https://github.com/trpc-group/trpc-go): A pluggable, high-performance RPC framework written in Golang. +- [motan-go](https://github.com/weibocom/motan-go): a remote procedure call (RPC) framework for the rapid development of high-performance distributed services. #### All use cases: diff --git a/README_ZH.md b/README_ZH.md index d3bb007..cefcd87 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -7,7 +7,6 @@
- @@ -122,6 +121,39 @@ func main() { wg.Wait() fmt.Printf("running goroutines: %d\n", p.Running()) fmt.Printf("finish all tasks, result is %d\n", sum) + if sum != 499500 { + panic("the final result is wrong!!!") + } + + // Use the MultiPool and set the capacity of the 10 goroutine pools to unlimited. + // If you use -1 as the pool size parameter, the size will be unlimited. + // There are two load-balancing algorithms for pools: ants.RoundRobin and ants.LeastTasks. + mp, _ := ants.NewMultiPool(10, -1, ants.RoundRobin) + defer mp.ReleaseTimeout(5 * time.Second) + for i := 0; i < runTimes; i++ { + wg.Add(1) + _ = mp.Submit(syncCalculateSum) + } + wg.Wait() + fmt.Printf("running goroutines: %d\n", mp.Running()) + fmt.Printf("finish all tasks.\n") + + // Use the MultiPoolFunc and set the capacity of 10 goroutine pools to (runTimes/10). + mpf, _ := ants.NewMultiPoolWithFunc(10, runTimes/10, func(i interface{}) { + myFunc(i) + wg.Done() + }, ants.LeastTasks) + defer mpf.ReleaseTimeout(5 * time.Second) + for i := 0; i < runTimes; i++ { + wg.Add(1) + _ = mpf.Invoke(int32(i)) + } + wg.Wait() + fmt.Printf("running goroutines: %d\n", mpf.Running()) + fmt.Printf("finish all tasks, result is %d\n", sum) + if sum != 499500*2 { + panic("the final result is wrong!!!") + } } ``` @@ -328,7 +360,7 @@ pool.Reboot() 以下公司/组织在生产环境上使用了 `ants`。 -                         +                           ### 开源软件 @@ -352,6 +384,8 @@ pool.Reboot() - [AdGuardDNS](https://github.com/AdguardTeam/AdGuardDNS): AdGuard DNS is an alternative solution for tracker blocking, privacy protection, and parental control. - [WatchAD2.0](https://github.com/Qihoo360/WatchAD2.0): WatchAD2.0 是 360 信息安全中心开发的一款针对域安全的日志分析与监控系统,它可以收集所有域控上的事件日志、网络流量,通过特征匹配、协议分析、历史行为、敏感操作和蜜罐账户等方式来检测各种已知与未知威胁,功能覆盖了大部分目前的常见内网域渗透手法。 - [vanus](https://github.com/vanus-labs/vanus): Vanus is a Serverless, event streaming system with processing capabilities. It easily connects SaaS, Cloud Services, and Databases to help users build next-gen Event-driven Applications. +- [trpc-go](https://github.com/trpc-group/trpc-go): 一个 Go 实现的可插拔的高性能 RPC 框架。 +- [motan-go](https://github.com/weibocom/motan-go): 一套高性能、易于使用的分布式远程服务调用(RPC)框架。motan-go 是 motan 的 Go 语言实现。 #### 所有案例: diff --git a/ants_benchmark_test.go b/ants_benchmark_test.go index 83cd920..f39b0e6 100644 --- a/ants_benchmark_test.go +++ b/ants_benchmark_test.go @@ -200,3 +200,27 @@ func BenchmarkAntsMultiPoolThroughput(b *testing.B) { } } } + +func BenchmarkParallelAntsPoolThroughput(b *testing.B) { + p, _ := NewPool(PoolCap, WithExpiryDuration(DefaultExpiredTime)) + defer p.Release() + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + _ = p.Submit(demoFunc) + } + }) +} + +func BenchmarkParallelAntsMultiPoolThroughput(b *testing.B) { + p, _ := NewMultiPool(10, PoolCap/10, RoundRobin, WithExpiryDuration(DefaultExpiredTime)) + defer p.ReleaseTimeout(DefaultExpiredTime) //nolint:errcheck + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + _ = p.Submit(demoFunc) + } + }) +} diff --git a/examples/main.go b/examples/main.go index 3e1d9e5..b967098 100644 --- a/examples/main.go +++ b/examples/main.go @@ -63,7 +63,7 @@ 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(10, func(i interface{}) { myFunc(i) @@ -81,4 +81,34 @@ func main() { if sum != 499500 { panic("the final result is wrong!!!") } + + // Use the MultiPool and set the capacity of the 10 goroutine pools to unlimited. + // If you use -1 as the pool size parameter, the size will be unlimited. + // There are two load-balancing algorithms for pools: ants.RoundRobin and ants.LeastTasks. + mp, _ := ants.NewMultiPool(10, -1, ants.RoundRobin) + defer mp.ReleaseTimeout(5 * time.Second) + for i := 0; i < runTimes; i++ { + wg.Add(1) + _ = mp.Submit(syncCalculateSum) + } + wg.Wait() + fmt.Printf("running goroutines: %d\n", mp.Running()) + fmt.Printf("finish all tasks.\n") + + // Use the MultiPoolFunc and set the capacity of 10 goroutine pools to (runTimes/10). + mpf, _ := ants.NewMultiPoolWithFunc(10, runTimes/10, func(i interface{}) { + myFunc(i) + wg.Done() + }, ants.LeastTasks) + defer mpf.ReleaseTimeout(5 * time.Second) + for i := 0; i < runTimes; i++ { + wg.Add(1) + _ = mpf.Invoke(int32(i)) + } + wg.Wait() + fmt.Printf("running goroutines: %d\n", mpf.Running()) + fmt.Printf("finish all tasks, result is %d\n", sum) + if sum != 499500*2 { + panic("the final result is wrong!!!") + } } diff --git a/multipool.go b/multipool.go index 1e8b27b..1de75ae 100644 --- a/multipool.go +++ b/multipool.go @@ -56,6 +56,9 @@ type MultiPool struct { // NewMultiPool instantiates a MultiPool with a size of the pool list and a size // per pool, and the load-balancing strategy. func NewMultiPool(size, sizePerPool int, lbs LoadBalancingStrategy, options ...Option) (*MultiPool, error) { + if lbs != RoundRobin && lbs != LeastTasks { + return nil, ErrInvalidLoadBalancingStrategy + } pools := make([]*Pool, size) for i := 0; i < size; i++ { pool, err := NewPool(sizePerPool, options...) @@ -64,9 +67,6 @@ func NewMultiPool(size, sizePerPool int, lbs LoadBalancingStrategy, options ...O } pools[i] = pool } - if lbs != RoundRobin && lbs != LeastTasks { - return nil, ErrInvalidLoadBalancingStrategy - } return &MultiPool{pools: pools, lbs: lbs}, nil } diff --git a/multipool_func.go b/multipool_func.go index 8101d31..c7d31ff 100644 --- a/multipool_func.go +++ b/multipool_func.go @@ -45,6 +45,9 @@ type MultiPoolWithFunc struct { // NewMultiPoolWithFunc instantiates a MultiPoolWithFunc with a size of the pool list and a size // per pool, and the load-balancing strategy. func NewMultiPoolWithFunc(size, sizePerPool int, fn func(interface{}), lbs LoadBalancingStrategy, options ...Option) (*MultiPoolWithFunc, error) { + if lbs != RoundRobin && lbs != LeastTasks { + return nil, ErrInvalidLoadBalancingStrategy + } pools := make([]*PoolWithFunc, size) for i := 0; i < size; i++ { pool, err := NewPoolWithFunc(sizePerPool, fn, options...) @@ -53,9 +56,6 @@ func NewMultiPoolWithFunc(size, sizePerPool int, fn func(interface{}), lbs LoadB } pools[i] = pool } - if lbs != RoundRobin && lbs != LeastTasks { - return nil, ErrInvalidLoadBalancingStrategy - } return &MultiPoolWithFunc{pools: pools, lbs: lbs}, nil }