🐜🐜🐜 ants is a high-performance and low-cost goroutine pool in Go, inspired by fasthttp./ ants 是一个高性能且低损耗的 goroutine 池。

A goroutine pool for Go


English | 🇨🇳 中文

📖 Introduction

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.

🚀 Features:

  • Managing and recycling a massive number of goroutines automatically
  • Purging overdue goroutines periodically
  • Abundant APIs: submitting tasks, getting the number of running goroutines, tuning capacity of pool dynamically, releasing pool, rebooting 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:

  • 1.8.x
  • 1.9.x
  • 1.10.x
  • 1.11.x
  • 1.12.x
  • 1.13.x
  • 1.14.x

💡 How ants works

Flow Diagram

ants-flowchart-en

Activity Diagrams

🧰 How to install

For ants v1

go get -u github.com/panjf2000/ants

For ants v2 (with GO111MODULE=on)

go get -u github.com/panjf2000/ants/v2

🛠 How to use

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:

package main

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"

	"github.com/panjf2000/ants/v2"
)

var sum int32

func myFunc(i interface{}) {
	n := i.(int32)
	atomic.AddInt32(&sum, n)
	fmt.Printf("run with %d\n", n)
}

func demoFunc() {
	time.Sleep(10 * time.Millisecond)
	fmt.Println("Hello World!")
}

func main() {
	defer ants.Release()

	runTimes := 1000

	// Use the common pool.
	var wg sync.WaitGroup
	syncCalculateSum := func() {
		demoFunc()
		wg.Done()
	}
	for i := 0; i < runTimes; i++ {
		wg.Add(1)
		_ = ants.Submit(syncCalculateSum)
	}
	wg.Wait()
	fmt.Printf("running goroutines: %d\n", ants.Running())
	fmt.Printf("finish all tasks.\n")

	// 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)
		wg.Done()
	})
	defer p.Release()
	// Submit tasks one by one.
	for i := 0; i < runTimes; i++ {
		wg.Add(1)
		_ = p.Invoke(int32(i))
	}
	wg.Wait()
	fmt.Printf("running goroutines: %d\n", p.Running())
	fmt.Printf("finish all tasks, result is %d\n", sum)
}

Functional options for ants pool

// 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 is a period for the scavenger goroutine to clean up those expired workers,
	// the scavenger scans all workers every `ExpiryDuration` and clean up those workers that haven't been
	// used for more than `ExpiryDuration`.
	ExpiryDuration time.Duration

	// PreAlloc indicates whether to make memory pre-allocation when initializing Pool.
	PreAlloc bool

	// Max number of goroutine blocking on pool.Submit.
	// 0 (default value) means no such limit.
	MaxBlockingTasks int

	// When Nonblocking is true, Pool.Submit will never be blocked.
	// ErrPoolOverload will be returned when Pool.Submit cannot be done at once.
	// When Nonblocking is true, MaxBlockingTasks is inoperative.
	Nonblocking bool

	// PanicHandler is used to handle panics from each worker goroutine.
	// if nil, panics will be thrown out again from worker goroutines.
	PanicHandler func(interface{})

	// Logger is the customized logger for logging info, if it is not set,
	// default standard logger from log package is used.
	Logger Logger
}

// 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
	}
}

// WithPanicHandler sets up panic handler.
func WithPanicHandler(panicHandler func(interface{})) Option {
	return func(opts *Options) {
		opts.PanicHandler = panicHandler
	}
}

// WithLogger sets up a customized logger.
func WithLogger(logger Logger) Option {
	return func(opts *Options) {
		opts.Logger = logger
	}
}

ants.Optionscontains 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/NewPoolWithFuncmethod.

Customize limited pool

ants also supports customizing the capacity of pool. You can invoke the NewPool method to instantiate a pool with a given capacity, as following:

// Set 10000 the size of goroutine pool
p, _ := ants.NewPool(10000)

Submit tasks

Tasks can be submitted by calling ants.Submit(func())

ants.Submit(func(){})

Tune pool capacity in runtime

You can tune the capacity of ants pool in runtime with Tune(int):

pool.Tune(1000) // Tune its capacity to 1000
pool.Tune(100000) // Tune its capacity to 100000

Don't worry about the synchronous problems in this case, the method here is thread-safe (or should be called goroutine-safe).

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 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 memory allocation in goroutine queue.

// ants will pre-malloc the whole capacity of pool when you invoke this method
p, _ := ants.NewPool(100000, ants.WithPreAlloc(true))

Release Pool

pool.Release()

Reboot Pool

// A pool that has been released can be still used once you invoke the Reboot().
pool.Reboot()

⚙️ About sequence

All tasks submitted to ants pool will not be guaranteed to be addressed in order, because those tasks scatter among a series of concurrent workers, thus those tasks would be executed concurrently.

🧲 Benchmarks

In this benchmark result, 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.

Benchmarks with Pool

In above benchmark result, 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 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

Throughput (it is suitable for scenarios where tasks are submitted asynchronously without waiting for the final results)

100K tasks

1M tasks

10M tasks

📊 Performance Summary

In conclusion, ants performs 2~6 times faster than goroutines without a pool and the memory consumption is reduced by 10 to 20 times.

👏 Contributors

Please read our Contributing Guidelines before opening a PR and thank you to all the developers who already made contributions to ants!

📄 License

Source code in ants is available under the MIT License.

📚 Relevant Articles

🖥 User cases

Please feel free to add your projects here~~

     

🔋 JetBrains OS licenses

ants had been being developed with GoLand under the free JetBrains Open Source license(s) granted by JetBrains s.r.o., hence I would like to express my thanks here.

💰 Backers

Support us with a monthly donation and help us continue our activities.

💎 Sponsors

Become a bronze sponsor with a monthly donation of $10 and get your logo on our README on Github.

☕️ Buy me a coffee

Please be sure to leave your name, Github account or other social media accounts when you donate by the following means so that I can add it to the list of donors as a token of my appreciation.

        

Donors

Patrick Othmer Jimmy ChenZhen Mai Yang 王开帅 Unger Alejandro

Owner
Andy Pan
A front-line programmer based in South China. I mostly write server-side code. Also a modern agnostic.
Andy Pan
Comments
  • Checksum mismatch for go 1.13

    Checksum mismatch for go 1.13

    Expect (go version go1.12.9 darwin/amd64):

    → go mod tidy -v
    go: downloading github.com/panjf2000/ants v1.2.0
    go: extracting github.com/panjf2000/ants v1.2.0
    

    Actual (go version go1.13 darwin/amd64)

    → go mod tidy -v
    verifying github.com/panjf2000/[email protected]: checksum mismatch
            downloaded: h1:Ufw4aDz9RqH1RVblx2W9L9Uv5vSX5apbX5+peR7LQ5k=
            sum.golang.org: h1:pMQ1/XpSgnWx3ro4y1xr/uA3jXUsTuAaU3Dm0JjwggE=
    
    SECURITY ERROR
    This download does NOT match the one reported by the checksum server.
    The bits may have been replaced on the origin server, or an attacker may
    have intercepted the download attempt.
    
    For more information, see 'go help module-auth'.
    

    UPD: mb this issue will be useful - https://github.com/golang/go/issues/33665


    UPD: how resolve issue step by step (macOS):

    • sudo go clean -modcache
    • git checkout go.sum
    • go mod tidy -v

    UPD for Linux:

    • cd /another/path
    • go clean -modcache
    • cd /project/path
    • go mod tidy
  • add loop queue

    add loop queue


    name: Pull request about: 抽象出worker队列的实现,使用原先和循环队列实现这个接口 title: '' labels: '' assignees: ''

    1. Are you opening this pull request for bug-fixs, optimizations or new feature?

    抽象了 worker 队列,实现了两种队列的方式,也可以方便的新加队列实现,只要符合 WorkerQueue 即可

    2. Please describe how these code changes achieve your intention.

    1. 抽象woker队列为WorkerQueue 的 interface{}
    2. 模仿之前的方式实现了 SliceQueue 队列,还是使用了 slice
    3. 新加了循环队列 LoopQueue,也是使用 slice 实现,但是会减少内存的copy操作(原先会在periodicallyPurge有slice拷贝的操作)
    4. 修改了在查询超时时间时,使用二分查找的算法。

    潘少,目前我修改了 pool。如果潘少觉得这个方案可行,我可以再把 PoolWithFunc 按照这种方式修改。

    3. Please link to the relevant issues (if any).

    4. Which documentation changes (if any) need to be made/updated because of this PR?

    4. Checklist

    • [x] I have squashed all insignificant commits.
    • [ ] I have commented my code for explaining package types, values, functions, and non-obvious lines.
    • [x] I have written unit tests and verified that all tests passes (if needed).
    • [ ] I have documented feature info on the README (only when this PR is adding a new feature).
    • [ ] (optional) I am willing to help maintain this change if there are issues with it later.
  • optimize memory allocation, change the default pool param and add the log of panic stack.

    optimize memory allocation, change the default pool param and add the log of panic stack.

    Hi, I am using it on my online server which almost need 5 million goroutines on each go service. I'm divided into 10 small pools, because a pool of five million will slow down the speed associated with the slice. I made some small optimizations, I hope this is useful. optimize memory allocation, change the default pool param and add the log of panic stack. btw, the default value DEFAULT_CLEAN_INTERVAL_TIME, one second is too short-lived. when the pool size is too large , Performance will drop .

  • 支持 unlimited 池子大小

    支持 unlimited 池子大小

    Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 考虑一个情况,当池子运行的函数本身,又需要调用这个池子投放新的任务时,是有死锁的可能的。从使用层面上这个问题很难避免,但是如果池子本身不限制大小,就能避免死锁。

    Describe the solution you'd like A clear and concise description of what you want to happen. 支持不限制池子大小的功能。

    Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered. 这很难,需要使用者小心谨慎地使用池子,保证没有同一个池子的嵌套。

    Additional context Add any other context or screenshots about the feature request here. 限制并发数的功能完全可以在上层实现,所以没什么损失。

  • how to wait for completion

    how to wait for completion

    I need graceful shutdown of my app with ants.PoolWithFunc so i need firstly forbid new tasks, and second wait for completion of already running. How can i do that with ants ?

  • Invoke decRunning() when revertWorker() returns false

    Invoke decRunning() when revertWorker() returns false

    Signed-off-by: Cholerae Hu [email protected]


    name: Pull request about: Propose changes to the code title: '' labels: '' assignees: ''

    1. Are you opening this pull request for bug-fixs, optimizations or new feature?

    2. Please describe how these code changes achieve your intention.

    3. Please link to the relevant issues (if any).

    4. Which documentation changes (if any) need to be made/updated because of this PR?

    4. Checklist

    • [ ] I have squashed all insignificant commits.
    • [ ] I have commented my code for explaining package types, values, functions, and non-obvious lines.
    • [ ] I have written unit tests and verified that all tests passes (if needed).
    • [ ] I have documented feature info on the README (only when this PR is adding a new feature).
    • [ ] (optional) I am willing to help maintain this change if there are issues with it later.
  • 期望暴露个 blockingNum 的统计数量

    期望暴露个 blockingNum 的统计数量

    目前有: p.Running() p.Free() p.Cap()

    在并不想放开并发数的场景下,高峰时, p.Free() 可能较长时间为 0, 此时很希望知道排队任务长度,即 blockingNum 数量或剩余排队数量 options.MaxBlockingTasks - blockingNum

  • 请教下怎么判断每个worker的任务是否执行完毕呢?

    请教下怎么判断每个worker的任务是否执行完毕呢?

    作者你好,在README中,预先知道了需要执行的task个数,利用sync.WaitGroup去等待所有的task执行完毕

    想请教下,在预先不知道task个数的情况下,怎么去知道所有的Task都执行完了呢?,伪代码如下:

    
    type Args struct {
        ID       int
        Name string
    }
    
    func Task(args interface{}){
        param := args.(Args)
        fmt.Printf("param: %#v\n", param)
    }
    
    func main() {
        defer ants.Release()
        
        p, _ = ants.NewPoolWithFunc(10, Task)
        
        defer p.Release()
    
        for _, model := range queryResult {    
            args := Args {
                 Name: model.Name,
                 ID:       model.ID,
            }
            p.Invoke(args)
        }
        //等待所有的Task执行完毕后再结束 ?
    }
    
  • Use pool as a queue

    Use pool as a queue

    Is your feature request related to a problem? Please describe. I have a limited pool (sized pool), but when I reach the capacity of the pool, Submit() returns an error (ErrPoolOverload) which means the pool is full and no workers available. Even if i set Nonblocking to true in [Option].(https://gowalker.org/github.com/panjf2000/ants#Options)

    func main() {
    	p, _ := ants.NewPool(2, ants.WithNonblocking(true))
    
    	for i := 0; i < 5; i++ {
    		err := p.Submit(func() {
    			fmt.Println("Testing wait for 1 second...")
    			time.Sleep(1 * time.Second)
    		})
    		if err != nil {
    			fmt.Println("Error: " + err.Error())
    		}
    	}
    
    	time.Sleep(500 * time.Second) // Only for test and block main(), something like waitgroup!
    }
    

    This code returns:

    Error: too many goroutines blocked on submit or Nonblocking is set
    Error: too many goroutines blocked on submit or Nonblocking is set
    Error: too many goroutines blocked on submit or Nonblocking is set
    Something is here, waiting..
    Something is here, waiting..
    

    Describe the solution you'd like I think it's better to have something like a (second) queue in ants. tasks submit without any error and complete one-by-one. In other words, Submit() should be non-blocking but it shouldn't return ErrPoolOverload error even if capacity is full, and should continue receiving tasks. I'm not sure if this feature exists in ants or not.

    Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.

    Additional context go keyword can do that:

    p, _ := ants.NewPool(2, ants.WithNonblocking(false))
    
    for i := 0; i < 5; i++ {
        go p.Submit(func() {
            fmt.Println("Testing wait for 1 second...")
            time.Sleep(1 * time.Second)
        })
    }
    

    But i think there must be a better way.

  • 业务逻辑 panic 问题

    业务逻辑 panic 问题

    `package main

    import ( "fmt" "net" "sync" "time"

    "github.com/panjf2000/ants/v2"
    

    )

    func doPortScan(i interface{}) {

    port := i.(int32)
    
    _, err := net.DialTimeout("tcp", fmt.Sprintf("192.168.20.1:%d", port), time.Second*1)
    if err != nil {
    	return
    }
    
    fmt.Printf("Port  %d is open\n", port)
    

    }

    func main() { defer ants.Release()

    runTimes := 65535
    
    // Use the common pool.
    var wg sync.WaitGroup
    
    
    // Use the pool with a method,
    // set 10 to the capacity of goroutine pool and 1 second for expired duration.
    p, _ := ants.NewPoolWithFunc(300, func(i interface{}) {
    	doPortScan(i)
    	wg.Done()
    })
    defer p.Release()
    // Submit tasks one by one.
    for i := 0; i < runTimes; i++ {
    	wg.Add(1)
    
    	_ = p.Invoke(int32(i))
    }
    wg.Wait()
    fmt.Printf("running goroutines: %d\n", p.Running())
    

    } 崩溃时的现象如下: goroutine 543 [runnable]: github.com/panjf2000/ants/v2.(*goWorkerWithFunc).run.func1(0xc000255e00) /Users/mac/go/src/github.com/panjf2000/ants/worker_func.go:65 +0x85 created by github.com/panjf2000/ants/v2.(*goWorkerWithFunc).run /Users/mac/go/src/github.com/panjf2000/ants/worker_func.go:49 +0x4c

    goroutine 544 [runnable]: syscall.syscall(0x108b820, 0x25, 0xc00048800c, 0x10, 0xffffffffffffffff, 0xffffffffffffffff, 0x24) /usr/local/go/src/runtime/sys_darwin.go:63 +0x2e syscall.connect(0x25, 0xc00048800c, 0x10, 0x0, 0x0) /usr/local/go/src/syscall/zsyscall_darwin_amd64.go:91 +0x5c syscall.Connect(0x25, 0x1158f40, 0xc000488000, 0x111ac80, 0x1) /usr/local/go/src/syscall/syscall_unix.go:251 +0x62 net.(*netFD).connect(0xc0000e2180, 0x115a280, 0xc0003ff200, 0x0, 0x0, 0x1158f40, 0xc000488000, 0x0, 0x0, 0x0, ...) /usr/local/go/src/net/fd_unix.go:70 +0x7b net.(*netFD).dial(0xc0000e2180, 0x115a280, 0xc0003ff200, 0x115a7a0, 0x0, 0x115a7a0, 0xc000255e90, 0x0, 0x1, 0xc000061890) /usr/local/go/src/net/sock_posix.go:149 +0xff net.socket(0x115a280, 0xc0003ff200, 0x1133ff4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x115a7a0, 0x0, ...) /usr/local/go/src/net/sock_posix.go:70 +0x1c0 net.internetSocket(0x115a280, 0xc0003ff200, 0x1133ff4, 0x3, 0x115a7a0, 0x0, 0x115a7a0, 0xc000255e90, 0x1, 0x0, ...) /usr/local/go/src/net/ipsock_posix.go:141 +0x141 net.(*sysDialer).doDialTCP(0xc0000e2100, 0x115a280, 0xc0003ff200, 0x0, 0xc000255e90, 0x110a680, 0x123ab20, 0x0) /usr/local/go/src/net/tcpsock_posix.go:65 +0xc2 net.(*sysDialer).dialTCP(0xc0000e2100, 0x115a280, 0xc0003ff200, 0x0, 0xc000255e90, 0xc034fda0d3, 0x121ffc0, 0xc000061ad0) /usr/local/go/src/net/tcpsock_posix.go:61 +0xd7 net.(*sysDialer).dialSingle(0xc0000e2100, 0x115a280, 0xc0003ff200, 0x11593c0, 0xc000255e90, 0x0, 0x0, 0x0, 0x0) /usr/local/go/src/net/dial.go:578 +0x36e net.(*sysDialer).dialSerial(0xc0000e2100, 0x115a280, 0xc0003ff200, 0xc0000b38a0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0) /usr/local/go/src/net/dial.go:546 +0x221 net.(*Dialer).DialContext(0xc000061e40, 0x115a240, 0xc0000ce008, 0x1133ff4, 0x3, 0xc0000ce6f0, 0x10, 0x0, 0x0, 0x0, ...) /usr/local/go/src/net/dial.go:424 +0x666 net.(*Dialer).Dial(...) /usr/local/go/src/net/dial.go:347 net.DialTimeout(0x1133ff4, 0x3, 0xc0000ce6f0, 0x10, 0x3b9aca00, 0xc0000ce6f0, 0x10, 0x0, 0x0) /usr/local/go/src/net/dial.go:333 +0xb5 main.doPortScan(0x10fe540, 0xc0000ce6d4) /Users/mac/go/src/github.com/panjf2000/ants/examples/main.go:42 +0xd8 main.main.func1(0x10fe540, 0xc0000ce6d4) /Users/mac/go/src/github.com/panjf2000/ants/examples/main.go:90 +0x3e github.com/panjf2000/ants/v2.(*goWorkerWithFunc).run.func1(0xc000255e30) /Users/mac/go/src/github.com/panjf2000/ants/worker_func.go:69 +0xbd created by github.com/panjf2000/ants/v2.(*goWorkerWithFunc).run /Users/mac/go/src/github.com/panjf2000/ants/worker_func.go:49 +0x4c exit status 2`

  • 频繁通过pool.Tune方法来实现动态增加/减少协程的数量

    频繁通过pool.Tune方法来实现动态增加/减少协程的数量

    大概的代码逻辑,在一个定时器内进行了通道任务的数量的统计,通过这个通道的任务数量在一定的时间,来通过pool.Tune方法调整协程池的数量, 但是经过一段时间后,通过poll.*里面提供的方法去统计当前有,多少协程和空闲协程,会出现一定的负数,

    pool.Tune(100)//通道任务有200个,开启100个协程处理

    pool.Tune(500)//通道任务大于1000个,调整协程数量为500

    pool.Tune(10)// 通道任务小于100,就把任务调整为10协程 以此类推来实现 协程的动态调整, 假如直接从500下调到10 会有什么不可以预估的问题吗? (后续贴代码)

  • fix(sec): upgrade gopkg.in/yaml.v3 to 3.0.0

    fix(sec): upgrade gopkg.in/yaml.v3 to 3.0.0

    What happened?

    There are 1 security vulnerabilities found in gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b

    What did I do?

    Upgrade gopkg.in/yaml.v3 from v3.0.0-20210107192922-496545a6307b to 3.0.0 for vulnerability fix

    What did you expect to happen?

    Ideally, no insecure libs should be used.

    The specification of the pull request

    PR Specification from OSCS Signed-off-by:pen4[email protected]

  • call ReleaseTimeout  return ErrTimeout operation timed out, coroutine not released

    call ReleaseTimeout return ErrTimeout operation timed out, coroutine not released

    Describe the bug A clear and concise description of what the bug is. call ReleaseTimeout return ErrTimeout operation timed out, coroutine not released

    @ 0x4040d96 0x4050fbc 0x4820fb6 0x40738e1

    0x4820fb5 github.com/panjf2000/ants/v2.(*Pool).purgePeriodically+0x115 /Users/eleme/go/pkg/mod/github.com/panjf2000/ants/[email protected]/pool.go:77

    To Reproduce Steps to reproduce the behavior:

    1. Go to '...'
    2. Click on '....'
    3. Scroll down to '....'
    4. See error

    Expected behavior A clear and concise description of what you expected to happen.

    Error messages/Trace logs If applicable, add some logs to help explain your problem.

    System info (please complete the following information):

    • OS: [e.g. linux, macOS]
    • Go Version: [e.g. 1.12]
    • ants version: [e.g. v2.2.2]

    Additional context Add any other context about the problem here.

  • Multiple Arguments Pool Function

    Multiple Arguments Pool Function

    … Invoke function without explicitly creating an array


    name: Pull request about: Propose changes to the code title: 'Multiple arguments pool func' labels: '' assignees: ''

    1. Are you opening this pull request for bug-fixs, optimizations or new feature? Optimizations

    2. Please describe how these code changes achieve your intention.

    To schedule a function with multiple arguments got a little bit ugly when creating an array to pass as an argument, then casting the interface{} to an array again and retrieving the single args. This slight change helps the developer to easily invoke its function passing multiple arguments and receiving directly the array of args. This of course means that single arg functions still have to parse the arg with arg[0]

    3. Please link to the relevant issues (if any).

    4. Which documentation changes (if any) need to be made/updated because of this PR?

    Mainly just the code used as an example, the updated README is included with the PR

    4. Checklist

    • [x] I have squashed all insignificant commits.
    • [x] I have commented my code for explaining package types, values, functions, and non-obvious lines.
    • [x] I have written unit tests and verified that all tests passes (if needed).
    • [x] I have documented feature info on the README (only when this PR is adding a new feature).
    • [x] (optional) I am willing to help maintain this change if there are issues with it later.
  • [Feature] Introduce the Future(like java) into ants.

    [Feature] Introduce the Future(like java) into ants.

    Is your feature request related to a problem? Please describe. 在业务开发的场景中,多线程异步查询然后聚合结果的场景十分常见。java里面有submit方法可以返回一个Future对象给用户去阻塞获取业务执行结果,是否也可以在ants中引入同样的功能。

    Describe the solution you'd like ants新增Future,已经类似java的submit方法。

    Describe alternatives you've considered no

    Additional context 如果有必要的话,我想尝试一下加这个功能。

  • 关于pool使用的自旋锁的性能问题

    关于pool使用的自旋锁的性能问题

    我看到pool用的是自己实现的自旋锁,而不是mutex,有点好奇性能,然后做了下性能测试:

    自旋锁版:
    goos: linux
    goarch: amd64
    pkg: github.com/panjf2000/ants/v2
    cpu: Intel(R) Xeon(R) Platinum 8269CY CPU @ 2.50GHz
    BenchmarkGoroutines-2                 10         113619133 ns/op         8000001 B/op     100000 allocs/op
    BenchmarkAntsPool-2                    9         114800650 ns/op         2349845 B/op     110335 allocs/op
    PASS
    ok      github.com/panjf2000/ants/v2    82.687s
    
    
    mutex版:
    goos: linux
    goarch: amd64
    pkg: github.com/panjf2000/ants/v2
    cpu: Intel(R) Xeon(R) Platinum 8269CY CPU @ 2.50GHz
    BenchmarkGoroutines-2                 10         120711594 ns/op         8014833 B/op     100154 allocs/op
    BenchmarkAntsPool-2                    9         118364808 ns/op         2388001 B/op     110733 allocs/op
    PASS
    ok      github.com/panjf2000/ants/v2    82.723s
    
    

    这样看来用mutex和自旋锁基本没什么差别,想问一下这是什么原因,为什么这个项目需要使用自己实现的自旋锁呢?求潘少指点

Minimalistic and High-performance goroutine worker pool written in Go

pond Minimalistic and High-performance goroutine worker pool written in Go Motivation This library is meant to provide a simple way to limit concurren

Dec 22, 2022
golang worker pool , Concurrency limiting goroutine pool

golang worker pool 中文说明 Concurrency limiting goroutine pool. Limits the concurrency of task execution, not the number of tasks queued. Never blocks su

Dec 19, 2022
🐝 A Highly Performant and easy to use goroutine pool for Go
🐝 A Highly Performant and easy to use goroutine pool for Go

gohive Package gohive implements a simple and easy to use goroutine pool for Go Features Pool can be created with a specific size as per the requireme

Sep 26, 2022
Queue is a Golang library for spawning and managing a Goroutine pool

Queue is a Golang library for spawning and managing a Goroutine pool, Alloowing you to create multiple worker according to limit CPU number of machine.

Jan 9, 2023
Queue is a Golang library for spawning and managing a Goroutine pool

Queue is a Golang library for spawning and managing a Goroutine pool, Alloowing you to create multiple worker according to limit CPU number of machine.

Jan 2, 2023
Lightweight Goroutine pool

grpool Lightweight Goroutine pool Clients can submit jobs. Dispatcher takes job, and sends it to first available worker. When worker is done with proc

Dec 6, 2022
A goroutine pool for Go
A goroutine pool for Go

Tunny is a Golang library for spawning and managing a goroutine pool, allowing you to limit work coming from any number of goroutines with a synchrono

Dec 31, 2022
Concurrency limiting goroutine pool

workerpool Concurrency limiting goroutine pool. Limits the concurrency of task execution, not the number of tasks queued. Never blocks submitting task

Dec 28, 2022
goroutine pool in golang

goroutine pool in golang

Nov 1, 2021
Golang Implementation of Worker Pool/ Thread Pool

Golang Implementation of Worker Pool/ Thread Pool

Jun 18, 2022
Go-miningcore-pool - Miningcore Pool written in GOlang

Go-Miningcore-Pool (COMING SOON) Miningcore Pool written in GOlang 0x01 Configur

Apr 24, 2022
Go-ldap-pool - A simple connection pool for go-ldap

Basic connection pool for go-ldap This little library use the go-ldap library an

Dec 17, 2022
Work pool channlege - An url hash retriever worker pool for getting hash digest for a collection of urls

Code challenge The aim of this project is to provide an url hash retriever worke

Feb 16, 2022
A simple and useful goroutine concurrent library.

Taskgroup A simple and useful goroutine concurrent library. Installation go get github.com/anthhub/taskgroup

May 19, 2021
Provides some convenient API, includes Goid(), AllGoid(), and LocalStorage, which is a goroutine's local storage, just like ThreadLocal in other languages.

routine 中文版 routine encapsulates and provides some easy-to-use, high-performance goroutine context access interfaces, which can help you access corout

Dec 30, 2022
A cross goroutine storage tool with very simple implementation and function.

Simple-goroutine-local is a cross goroutine storage tool with very simple implementation and function (the concept is similar to Java ThreadLocal). Ge

Jan 13, 2022
Routines was a fixed number thread pool to process the user task, and it would respawn a corresponding new thread when panic

Routines Routines was a fixed number thread pool to process the user task, and it would respawn a corresponding new thread when panic. It supports the

Dec 16, 2021
Worker pool library with auto-scaling, backpressure, and easy composability of pools into pipelines

workerpool Worker pool library with auto-scaling, backpressure, and easy composability of pools into pipelines. Uses Go 1.18 generics. Notable differe

Oct 5, 2022
errgroup with goroutine worker limits

neilotoole/errgroup neilotoole/errgroup is a drop-in alternative to Go's wonderful sync/errgroup but limited to N goroutines. This is useful for inter

Dec 15, 2022