Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add generator pool #1

Closed
wants to merge 1 commit into from
Closed

Conversation

Jorropo
Copy link

@Jorropo Jorropo commented Jun 16, 2022

goos: linux
goarch: amd64
cpu: AMD Ryzen 5 3600 6-Core Processor
BenchmarkUnlimitedGoroutines-12    	       3	 407885944 ns/op	96721301 B/op	 2007116 allocs/op
BenchmarkAntsPool-12               	       2	 779131236 ns/op	20097156 B/op	 1064950 allocs/op
BenchmarkGammaZeroPool-12          	       1	1162897642 ns/op	19343432 B/op	 1057008 allocs/op
BenchmarkItogamiPool-12            	       3	 431012905 ns/op	28744213 B/op	 1051633 allocs/op
BenchmarkGenerator-12              	       5	 230959863 ns/op	 4823598 B/op	  100013 allocs/op

It is far faster than other alternatives (including unlimited goroutines).

It allocs far less than other alternatives.

I'll let you benchmark on your arm64 mac m1 but results will hold there too.


Main reasons it's faster than itogami:

  • Itogami has an optimised scheduling interaction calling directly into the runtime. (which is UB and can break at any moment)
    • Generator just say: "what if I doesn't schedule in the first place ?"
  • Itogami has an optimised task queue.
    • Generator just say: "what if I doesn't have a task queue and I ask you for more work instead ?"

@Jorropo Jorropo force-pushed the add-generator-pool branch from 53a137c to 13f8205 Compare June 16, 2022 12:15
@Jorropo
Copy link
Author

Jorropo commented Jun 16, 2022

Also, I don't recommend anyone to use my package. It is so simple you can just reimplement it locally (and that allows you to remove the closures).

That not a new pattern, other pieces of code use it. I belive no one made a lib for it yet (or at least I couldn't find it), because it's so simple it doesn't need one.

It's just to show that goroutines pools are not a fast thing to begin with.

```
goos: linux
goarch: amd64
cpu: AMD Ryzen 5 3600 6-Core Processor
BenchmarkUnlimitedGoroutines-12    	       3	 407885944 ns/op	96721301 B/op	 2007116 allocs/op
BenchmarkAntsPool-12               	       2	 779131236 ns/op	20097156 B/op	 1064950 allocs/op
BenchmarkGammaZeroPool-12          	       1	1162897642 ns/op	19343432 B/op	 1057008 allocs/op
BenchmarkItogamiPool-12            	       3	 431012905 ns/op	28744213 B/op	 1051633 allocs/op
BenchmarkGenerator-12              	       5	 230959863 ns/op	 4823598 B/op	  100013 allocs/op
```

It is far faster than other alternatives.
@Jorropo Jorropo force-pushed the add-generator-pool branch from 13f8205 to 117fd80 Compare June 16, 2022 12:32
@Jorropo
Copy link
Author

Jorropo commented Jun 16, 2022

BTW
If we remove the sleep statement from demofunc (because generator is so fast it actually spend most of it's time sleeping), to purely target the pool overhead. This is 14x faster than unlimited goroutines.
While itogami panics.

BenchmarkUnlimitedGoroutines-12    	       4	 288581981 ns/op
BenchmarkAntsPool-12               	       2	 634643862 ns/op
BenchmarkGammaZeroPool-12          	       2	 677348941 ns/op
BenchmarkGenerator-12              	      51	  20270000 ns/op

@alphadose
Copy link
Owner

alphadose commented Jun 19, 2022

The above benchmarks are unfair because the generator pool in the benchmark code doesn't follow the same allocation scheme as others.
To measure performance under identical circumstances, the generator pool needs to have an API like Submit() and it should be allocated only once at the start of the test

The fair benchmarking code for generator pool should look like

func BenchmarkGeneratorPool(b *testing.B) {
	var wg sync.WaitGroup
	gen := generator.NewPool(PoolSize)
	
	b.ResetTimer()
	b.StartTimer()
	
	for i := 0; i < b.N; i++ {
		wg.Add(RunTimes)
		for j := 0; j < RunTimes; j++ {
			gen.Submit(func() {
				demoFunc()
				wg.Done()
			})
		}
		wg.Wait()
	}
	b.StopTimer()
}

@alphadose alphadose closed this Jun 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants