Why ?
Limiting the number of goroutines in Go is essential for several reasons, primarily related to resource management and performance optimization. Here are the key points:
-
Resource Management: Limiting goroutines prevents excessive consumption of system resources like CPU and memory, avoiding crashes or slowdowns.
-
Compliance with Rate Limits: Many APIs impose rate limits; controlling goroutines ensures adherence to these constraints, preventing service disruptions.
-
Improved Throughput: A controlled number of goroutines optimizes CPU usage and context switching, enhancing overall application throughput.
-
Reduced Latency: Fewer concurrent operations minimize contention for shared resources, leading to faster task completion .
-
Preventing Deadlocks: Limiting goroutines can help avoid deadlocks in complex applications where multiple goroutines depend on shared resources.
Solution 1:
package main
import ( "fmt" "runtime" "time")
func main() { maxGoroutines := 2 guard := make(chan struct{}, maxGoroutines)
for i := 0; i < 50; i++ { guard <- struct{}{} go func(n int) { worker(n) <-guard }(i) }}
func worker(i int) { time.Sleep(time.Second * 10) // processing time for the task fmt.Println(runtime.NumGoroutine()) // print number or running current goroutines fmt.Println("doing work on", i)}
Solution 2:
package main
import ( "fmt" "time")
const LIMIT = 25
func main() { sem := make(chan int, LIMIT) for { sem <- 1 // will block if there is LIMIT ints in sem go func() { time.Sleep(time.Second * 10) // processing time for the task fmt.Println("doing work") <-sem // removes an int from sem, allowing another to proceed }() }}
Links: