Skip to content

Commit 85722a6

Browse files
committed
update README.md
1 parent 606b6a3 commit 85722a6

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

README.md

+138
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,143 @@
1+
![structured concurrency schema](https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fwww.thedevtavern.com%2Fstatic%2F671edc5ec17e1522393f07c0f7b42465%2F9bec7%2Fbanner.png&f=1&nofb=1&ipt=3295434f2f3b02cfff98cc60776bf62cf519268dc90982d7d98a3caff5544dce&ipo=images)
2+
13
# `conc` - Structured concurrency for Go
24

5+
[![Go doc](https://pkg.go.dev/badge/github.com/negrel/conc)](https://pkg.go.dev/github.com/negrel/conc)
6+
[![go report card](https://goreportcard.com/badge/github.com/negrel/conc)](https://goreportcard.com/report/github.com/negrel/conc)
7+
[![license card](https://img.shields.io/github/license/negrel/conc)](./LICENSE)
8+
[![PRs welcome card](https://img.shields.io/badge/PRs-Welcome-brightgreen)](https://github.com/negrel/conc/pulls)
9+
![Go version card](https://img.shields.io/github/go-mod/go-version/negrel/conc)
10+
11+
`conc` is a **structured concurrency** library for Go that provides a safer,
12+
more intuitive approach to concurrent programming.
13+
14+
By emphasizing proper resource management, error handling, and execution flow,
15+
`conc` helps developers write concurrent code that is less error-prone, easier
16+
to reason about, and aligned with established best practices.
17+
18+
```sh
19+
go get github.com/negrel/conc
20+
```
21+
22+
## Predictable code flow
23+
24+
`conc` is based on `nursery` as described in [this blog post](https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/).
25+
26+
27+
Idea behind nursery is that routines are scoped to a block that returns when
28+
all goroutines are done. This way, code flow remains sequential outside before
29+
and after the block. Here is an example:
30+
31+
```go
32+
func main() {
33+
conc.Block(func(n conc.Nursery) error {
34+
// Spawn a goroutine.
35+
n.Go(func() error {
36+
return nil
37+
})
38+
39+
// Spawn another goroutine.
40+
n.Go(func() error {
41+
time.Sleep(2 * time.Second)
42+
return nil
43+
})
44+
45+
// Sleep before returning.
46+
time.Sleep(time.Second)
47+
return nil
48+
})
49+
// Once block returns (here after 2 seconds), you're guaranteed that there is no
50+
// goroutine leak.
51+
// ...
52+
}
53+
```
54+
55+
Here is the definition of the `Nursery` interface:
56+
57+
```go
58+
type Nursery interface {
59+
context.Context
60+
Go(func() error)
61+
}
62+
```
63+
64+
It is a simple extension to [`context.Context`](https://pkg.go.dev/context#Context) that allows spawning routines.
65+
66+
[`Block`](https://pkg.go.dev/github.com/negrel/conc#Block) and
67+
[`Nursery`](https://pkg.go.dev/github.com/negrel/conc#Nursery) are the core of
68+
the entire library.
69+
70+
## Explicit goroutines "leak"
71+
72+
Now, let's say you want to write a function spawning routines that outlives it.
73+
You can pass `Nursery` as a parameter making the leak explicit:
74+
75+
```go
76+
func workHard(n conc.Nursery) {
77+
n.Go(func() error {
78+
return longWork(n)
79+
})
80+
81+
n.Go(func() error {
82+
return longerWork(n)
83+
})
84+
}
85+
```
86+
87+
## And more...
88+
89+
* Graceful panics and errors handling
90+
* Context integration for deadlines and cancellation
91+
* Limit maximum number of goroutine used by a block
92+
* Goroutines are pool allocated to improve efficiency
93+
* Dependency free
94+
95+
## Performance
96+
97+
Here, an operation means spawning 100 goroutines:
98+
99+
```sh
100+
$ cd bench/
101+
$ go test -v -bench=./... -benchmem ./...
102+
goos: linux
103+
goarch: amd64
104+
pkg: github.com/negrel/conc/bench
105+
cpu: AMD Ryzen 7 7840U w/ Radeon 780M Graphics
106+
BenchmarkNursery
107+
BenchmarkNursery/EmptyBlock
108+
BenchmarkNursery/EmptyBlock-16 1367210 914.3 ns/op 625 B/op 11 allocs/op
109+
BenchmarkNursery/WithRoutines/NoWork
110+
BenchmarkNursery/WithRoutines/NoWork-16 26823 43909 ns/op 1514 B/op 65 allocs/op
111+
BenchmarkNursery/WithRoutines/Nested/NoWork
112+
BenchmarkNursery/WithRoutines/Nested/NoWork-16 18189 69416 ns/op 3623 B/op 147 allocs/op
113+
BenchmarkNursery/WithRoutines/1msWork
114+
BenchmarkNursery/WithRoutines/1msWork-16 940 1300306 ns/op 11941 B/op 211 allocs/op
115+
BenchmarkNursery/WithRoutines/1-10msWork
116+
BenchmarkNursery/WithRoutines/1-10msWork-16 123 9681105 ns/op 12427 B/op 292 allocs/op
117+
BenchmarkNursery/WithRoutines/Error
118+
BenchmarkNursery/WithRoutines/Error-16 26767 44257 ns/op 1485 B/op 65 allocs/op
119+
BenchmarkSourceGraphConc
120+
BenchmarkSourceGraphConc/EmptyPool
121+
BenchmarkSourceGraphConc/EmptyPool-16 13450243 85.45 ns/op 176 B/op 2 allocs/op
122+
BenchmarkSourceGraphConc/WithRoutines/NoWork
123+
BenchmarkSourceGraphConc/WithRoutines/NoWork-16 48522 23928 ns/op 1835 B/op 84 allocs/op
124+
BenchmarkSourceGraphConc/WithRoutines/1msWork
125+
BenchmarkSourceGraphConc/WithRoutines/1msWork-16 966 1239140 ns/op 13776 B/op 302 allocs/op
126+
BenchmarkSourceGraphConc/WithRoutines/1-10msWork
127+
BenchmarkSourceGraphConc/WithRoutines/1-10msWork-16 123 9625635 ns/op 14030 B/op 372 allocs/op
128+
BenchmarkGo
129+
BenchmarkGo/WithRoutines/NoWork
130+
BenchmarkGo/WithRoutines/NoWork-16 84024 14240 ns/op 1600 B/op 100 allocs/op
131+
BenchmarkGo/WithRoutines/Nested/NoWork
132+
BenchmarkGo/WithRoutines/Nested/NoWork-16 81360 14497 ns/op 3199 B/op 199 allocs/op
133+
BenchmarkGo/WithRoutines/1msWork
134+
BenchmarkGo/WithRoutines/1msWork-16 59904 18651 ns/op 11215 B/op 200 allocs/op
135+
BenchmarkGo/WithRoutines/1-10msWork
136+
BenchmarkGo/WithRoutines/1-10msWork-16 51703 21088 ns/op 11069 B/op 190 allocs/op
137+
PASS
138+
ok github.com/negrel/conc/bench 22.347s
139+
```
140+
3141
## Contributing
4142

5143
If you want to contribute to `conc` to add a feature or improve the code contact

0 commit comments

Comments
 (0)