Open AskAlexSharov opened 1 month ago
meh - need to think about this
I write a simple benchmark test, here's the benchmark result:
CPU Cores: 10
Tasks number: 1000
=== CPU-Bound Task Benchmark ===
1 goroutines: 335.22075ms
10 goroutines: 39.401667ms
100 goroutines: 38.951541ms
1000 goroutines: 39.360083ms
2000 goroutines: 40.008459ms
=== I/O-Bound Task Benchmark ===
1 goroutines: 10.976698875s
10 goroutines: 1.10276125s
100 goroutines: 109.47375ms
1000 goroutines: 12.514292ms
2000 goroutines: 12.588917ms
so we can infer that:
for above examples, there's one i/o-bound task connectWithAllPeers
, others are cpu-bound.
maybe this could help.
I would add one more thing here, we could have more goroutines than CPUs for just fairness. Also, goroutines don't mean CPU threads, we still have restricted number of OS threads, goroutines are just mapped on those and scheduling/mapping overhead for goroutines is not a big deal.
So, associating goroutines with OS threads and their scheduling wouldn't be a good start for refactoring most of the code.
I will look into those places and check if we are unnecessarily starting goroutines though.
Found many patterns like:
Examples:
getDutiesProposer
connectWithAllPeers
batchVerifyAttestations
VerifyAgainstIdentifiersAndInsertIntoTheBlobStore
This pattern spawns unlimited amount of goroutines. All "unlimited" things are bad - because:
let's replace it by next pattern:
Can set any limit you like.