Skip to content

Commit 938b1f7

Browse files
authored
Merge pull request #3 from FishGoddess/develop
v0.2.0-alpha
2 parents d269bf0 + 619906c commit 938b1f7

18 files changed

Lines changed: 683 additions & 23 deletions

FUTURE.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
## ✒ 未来版本的新特性 (Features in future versions)
22

3+
### v0.2.x
4+
5+
* [x] 增加异步任务执行器
6+
* [x] 支持轮询调度策略
7+
* [ ] 支持随机调度策略
8+
* [ ] 支持任务数量优先调度策略
9+
* [ ] 支持任务时间优先调度策略
10+
* [x] 支持设置 worker 任务队列大小
11+
* [x] 支持设置 panic 处理函数
12+
* [x] 支持自定义 sync.Locker 实现
13+
* [ ] 完善单元测试,将覆盖率提高到 95% 以上
14+
315
### v0.1.0
416

517
* [x] 增加支持退避策略的自旋锁
6-
* [ ] 增加轻量协程库
718

819
### v0.0.1
920

HISTORY.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
## ✒ 历史版本的特性介绍 (Features in old versions)
22

3+
### v0.2.0-alpha
4+
5+
> 此版本发布于 2025-06-25
6+
7+
* 增加异步任务执行器
8+
* 支持轮询调度策略
9+
* 支持设置 worker 任务队列大小
10+
* 支持设置 panic 处理函数
11+
* 支持自定义 sync.Locker 实现
12+
* 单元测试覆盖率提高到 94%
13+
314
### v0.1.0
415

516
> 此版本发布于 2025-06-21

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
all: test
44

55
test:
6-
go test -cover ./...
6+
go test -v -cover ./...
7+
8+
bench:
9+
go test -v ./_examples/performance_test.go -run=none -bench=. -benchmem -benchtime=1s
710

811
fmt:
912
go fmt ./...

README.en.md

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,23 @@
55
[![Coverage](_icons/coverage.svg)](./_icons/coverage.svg)
66
![Test](https://github.com/FishGoddess/goes/actions/workflows/test.yml/badge.svg)
77

8-
**Goes** is a easy-to-use and lightweight lib for limiting goroutines.
8+
**Goes** is a easy-to-use and lightweight lib for executing async tasks.
99

1010
[阅读中文版的文档](./README.md)
1111

1212
### 🥇 Features
1313

14-
* Spin lock with backoff strategy.
15-
* Limiter only limits the number of simultaneous goroutines, not reuses goroutines.
14+
* Supports spin lock with backoff strategy.
15+
* Limits the number of simultaneous goroutines and not reuses them by Limiter.
16+
* Limits the number of simultaneous goroutines and reuses them by Executor.
1617

1718
_Check [HISTORY.md](./HISTORY.md) and [FUTURE.md](./FUTURE.md) to know about more information._
1819

1920
### 🚀 How to use
2021

22+
```bash
2123
$ go get -u github.com/FishGoddess/goes
24+
```
2225

2326
```go
2427
package main
@@ -31,21 +34,57 @@ import (
3134
)
3235

3336
func main() {
37+
// Limits the number of simultaneous goroutines and not reuses them.
3438
limiter := goes.NewLimiter(4)
3539

36-
for i := 0; i < 100; i++ {
40+
for i := 0; i < 20; i++ {
3741
limiter.Go(func() {
38-
fmt.Println(time.Now())
39-
time.Sleep(100 * time.Millisecond)
42+
fmt.Println("limiter --> ", time.Now())
43+
time.Sleep(time.Second)
4044
})
4145
}
4246

4347
limiter.Wait()
48+
49+
// Limits the number of simultaneous goroutines and reuses them.
50+
executor := goes.NewExecutor(4)
51+
defer executor.Close()
52+
53+
for i := 0; i < 20; i++ {
54+
executor.Submit(func() {
55+
fmt.Println("executor --> ", time.Now())
56+
time.Sleep(time.Second)
57+
})
58+
}
4459
}
4560
```
4661

4762
_Check more examples in [_examples](./_examples)._
4863

64+
### 🔨 Benchmarks
65+
66+
```bash
67+
$ make bench
68+
```
69+
70+
```bash
71+
goos: linux
72+
goarch: amd64
73+
cpu: AMD EPYC 7K62 48-Core Processor
74+
75+
BenchmarkLimiter-2 2417040 498.5 ns/op 24 B/op 1 allocs/op
76+
BenchmarkExecutor-2 23793781 49.9 ns/op 0 B/op 0 allocs/op
77+
BenchmarkAntsPool-2 4295964 271.7 ns/op 0 B/op 0 allocs/op
78+
79+
BenchmarkLimiterTime-2: num is 1000000, cost is 300.936441ms
80+
BenchmarkExecutorTime-2: num is 1000000, cost is 51.350509ms
81+
BenchmarkAntsPoolTime-2: num is 999744, cost is 346.972287ms
82+
```
83+
84+
> Obviously, goes.Executor is 5x faster than ants.Pool which has more features, so try goes if you prefer a lightweight and faster executor.
85+
86+
> Benchmarks: [_examples/performance_test.go](./_examples/performance_test.go).
87+
4988
### 👥 Contributing
5089

5190
If you find that something is not working as expected please open an _**issue**_.

README.md

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,23 @@
55
[![Coverage](_icons/coverage.svg)](./_icons/coverage.svg)
66
![Test](https://github.com/FishGoddess/goes/actions/workflows/test.yml/badge.svg)
77

8-
**Goes** 是一个简单易用且轻量的协程数限制库
8+
**Goes** 是一个简单易用且轻量的异步任务执行库
99

1010
[Read me in English](./README.en.md)
1111

1212
### 🥇 功能特性
1313

14-
* 支持退避策略的自旋锁。
15-
* Limiter 只限制同时执行的协程数,不复用协程。
14+
* 内置退避策略的自旋锁。
15+
* 支持只限制同时执行的协程数,但不复用协程,使用 Limiter。
16+
* 支持限制同时执行的协程数,且复用协程,使用 Executor。
1617

1718
_历史版本的特性请查看 [HISTORY.md](./HISTORY.md)。未来版本的新特性和计划请查看 [FUTURE.md](./FUTURE.md)_
1819

1920
### 🚀 使用方式
2021

22+
```bash
2123
$ go get -u github.com/FishGoddess/goes
24+
```
2225

2326
```go
2427
package main
@@ -31,21 +34,57 @@ import (
3134
)
3235

3336
func main() {
37+
// Limits the number of simultaneous goroutines and not reuses them.
3438
limiter := goes.NewLimiter(4)
3539

36-
for i := 0; i < 100; i++ {
40+
for i := 0; i < 20; i++ {
3741
limiter.Go(func() {
38-
fmt.Println(time.Now())
39-
time.Sleep(100 * time.Millisecond)
42+
fmt.Println("limiter --> ", time.Now())
43+
time.Sleep(time.Second)
4044
})
4145
}
4246

4347
limiter.Wait()
48+
49+
// Limits the number of simultaneous goroutines and reuses them.
50+
executor := goes.NewExecutor(4)
51+
defer executor.Close()
52+
53+
for i := 0; i < 20; i++ {
54+
executor.Submit(func() {
55+
fmt.Println("executor --> ", time.Now())
56+
time.Sleep(time.Second)
57+
})
58+
}
4459
}
4560
```
4661

4762
_更多使用案例请查看 [_examples](./_examples) 目录。_
4863

64+
### 🔨 性能测试
65+
66+
```bash
67+
$ make bench
68+
```
69+
70+
```bash
71+
goos: linux
72+
goarch: amd64
73+
cpu: AMD EPYC 7K62 48-Core Processor
74+
75+
BenchmarkLimiter-2 2417040 498.5 ns/op 24 B/op 1 allocs/op
76+
BenchmarkExecutor-2 23793781 49.9 ns/op 0 B/op 0 allocs/op
77+
BenchmarkAntsPool-2 4295964 271.7 ns/op 0 B/op 0 allocs/op
78+
79+
BenchmarkLimiterTime-2: num is 1000000, cost is 300.936441ms
80+
BenchmarkExecutorTime-2: num is 1000000, cost is 51.350509ms
81+
BenchmarkAntsPoolTime-2: num is 999744, cost is 346.972287ms
82+
```
83+
84+
> 很明显,goes.Executor 的性能比功能更丰富的 ants.Pool 要高出 5 倍左右,所以当你需要一个很轻量且高性能的异步任务执行器时,可以尝试下 goes。
85+
86+
> 测试文件:[_examples/performance_test.go](./_examples/performance_test.go)
87+
4988
### 👥 贡献者
5089

5190
如果您觉得 goes 缺少您需要的功能,请不要犹豫,马上参与进来,发起一个 _**issue**_

_examples/basic.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,26 @@ import (
1212
)
1313

1414
func main() {
15+
// Limits the number of simultaneous goroutines and not reuses them.
1516
limiter := goes.NewLimiter(4)
1617

17-
for i := 0; i < 100; i++ {
18+
for i := 0; i < 20; i++ {
1819
limiter.Go(func() {
19-
fmt.Println(time.Now())
20-
time.Sleep(100 * time.Millisecond)
20+
fmt.Println("limiter --> ", time.Now())
21+
time.Sleep(time.Second)
2122
})
2223
}
2324

2425
limiter.Wait()
26+
27+
// Limits the number of simultaneous goroutines and reuses them.
28+
executor := goes.NewExecutor(4)
29+
defer executor.Close()
30+
31+
for i := 0; i < 20; i++ {
32+
executor.Submit(func() {
33+
fmt.Println("executor --> ", time.Now())
34+
time.Sleep(time.Second)
35+
})
36+
}
2537
}

_examples/performance_test.go

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// Copyright 2025 FishGoddess. All rights reserved.
2+
// Use of this source code is governed by a MIT style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
import (
8+
"sync/atomic"
9+
"testing"
10+
"time"
11+
12+
"github.com/FishGoddess/goes"
13+
//"github.com/panjf2000/ants/v2"
14+
)
15+
16+
const (
17+
limit = 256
18+
workerNum = limit
19+
size = limit
20+
timeLoop = 100_0000
21+
)
22+
23+
func bench(num *uint32) {
24+
atomic.AddUint32(num, 1)
25+
}
26+
27+
// go test -v -run=none -bench=^BenchmarkLimiter$ -benchmem -benchtime=1s
28+
func BenchmarkLimiter(b *testing.B) {
29+
limiter := goes.NewLimiter(limit)
30+
31+
num := uint32(0)
32+
f := func() {
33+
bench(&num)
34+
}
35+
36+
b.RunParallel(func(pb *testing.PB) {
37+
for pb.Next() {
38+
limiter.Go(f)
39+
}
40+
})
41+
42+
limiter.Wait()
43+
b.Logf("num is %d", num)
44+
}
45+
46+
// go test -v -run=none -bench=^BenchmarkLimiterTime$ -benchmem -benchtime=1s
47+
func BenchmarkLimiterTime(b *testing.B) {
48+
limiter := goes.NewLimiter(limit)
49+
50+
num := uint32(0)
51+
f := func() {
52+
bench(&num)
53+
}
54+
55+
beginTime := time.Now()
56+
for range timeLoop {
57+
limiter.Go(f)
58+
}
59+
60+
limiter.Wait()
61+
62+
cost := time.Since(beginTime)
63+
b.Logf("num is %d, cost is %s", num, cost)
64+
}
65+
66+
// go test -v -run=none -bench=^BenchmarkExecutor$ -benchmem -benchtime=1s
67+
func BenchmarkExecutor(b *testing.B) {
68+
executor := goes.NewExecutor(workerNum)
69+
70+
num := uint32(0)
71+
task := func() {
72+
bench(&num)
73+
}
74+
75+
b.RunParallel(func(pb *testing.PB) {
76+
for pb.Next() {
77+
executor.Submit(task)
78+
}
79+
})
80+
81+
executor.Close()
82+
b.Logf("num is %d", num)
83+
}
84+
85+
// go test -v -run=none -bench=^BenchmarkExecutorTime$ -benchmem -benchtime=1s
86+
func BenchmarkExecutorTime(b *testing.B) {
87+
executor := goes.NewExecutor(size)
88+
89+
num := uint32(0)
90+
task := func() {
91+
bench(&num)
92+
}
93+
94+
beginTime := time.Now()
95+
for range timeLoop {
96+
executor.Submit(task)
97+
}
98+
99+
executor.Close()
100+
101+
cost := time.Since(beginTime)
102+
b.Logf("num is %d, cost is %s", num, cost)
103+
}
104+
105+
// // go test -v -run=none -bench=^BenchmarkAntsPool$ -benchmem -benchtime=1s
106+
// func BenchmarkAntsPool(b *testing.B) {
107+
// pool, _ := ants.NewPool(size)
108+
//
109+
// num := uint32(0)
110+
// task := func() {
111+
// bench(&num)
112+
// }
113+
//
114+
// b.RunParallel(func(pb *testing.PB) {
115+
// for pb.Next() {
116+
// pool.Submit(task)
117+
// }
118+
// })
119+
//
120+
// pool.Release()
121+
// b.Logf("num is %d", num)
122+
// }
123+
//
124+
// // go test -v -run=none -bench=^BenchmarkAntsPoolTime$ -benchmem -benchtime=1s
125+
// func BenchmarkAntsPoolTime(b *testing.B) {
126+
// pool, _ := ants.NewPool(size)
127+
//
128+
// num := uint32(0)
129+
// task := func() {
130+
// bench(&num)
131+
// }
132+
//
133+
// beginTime := time.Now()
134+
// for range timeLoop {
135+
// pool.Submit(task)
136+
// }
137+
//
138+
// pool.Release()
139+
//
140+
// cost := time.Since(beginTime)
141+
// b.Logf("num is %d, cost is %s", num, cost)
142+
// }

0 commit comments

Comments
 (0)