Skip to content

Instantly share code, notes, and snippets.

@matthewoestreich
Last active September 24, 2020 21:09
Show Gist options
  • Save matthewoestreich/b5f021cd525a909693d9af2c1ec34180 to your computer and use it in GitHub Desktop.
Save matthewoestreich/b5f021cd525a909693d9af2c1ec34180 to your computer and use it in GitHub Desktop.
How to create and use worker pools - learning about goroutines + channels
package main
/**
* Each worker calculates fibonacci sequence for N int in order to show how worker pools can be utilized.
*
* Instructions:
* UNCOMMENT `DemoCreateSingleWorker()` OR `DemoCreateOneWorkerPerCPUCore()`
* FOR BEST RESULTS, ONLY UNCOMMENT ONE AT A TIME
*
* BE WARNED THIS CAN GET PRETTY INTENSE ON YOUR CPU AFTER LIKE 2 MIN
*/
import (
"fmt"
"runtime"
)
func main() {
totalJobs := 100
jobsPipe := make(chan int, totalJobs)
resultsPipe := make(chan int, totalJobs)
DemoCreateSingleWorker(jobsPipe, resultsPipe, totalJobs)
// DemoCreateOneWorkerPerCPUCore(jobsPipe, resultsPipe, totalJobs)
}
// fibonacci implemented terribly
func fib(n int) int {
if n <= 1 {
return n
}
return fib(n-1) + fib(n-2)
}
// worker defines our worker func. as long as there is a job in the
// queue we continue to pick up the 'next' job
func worker(jobs <-chan int, results chan<- int) {
for n := range jobs {
results <- fib(n)
}
}
// fillQueue fills up our jobs channel
func fillQueue(jobs chan<- int, numJobs int) {
for i := 0; i < numJobs; i++ {
jobs <- i
}
}
// takeJobFromQueueAndDo takes a job off the 'stack' and invokes it (idk if that's proper terminology?)
func takeJobFromQueueAndDo(results <-chan int, numJobs int) {
for j := 0; j < numJobs; j++ {
fmt.Printf("Taking job %d\n", j)
fmt.Println(<-results)
}
}
// DemoCreateOneWorkerPerCPUCore creates as many workers as there are CPU cores on the current machine
func DemoCreateOneWorkerPerCPUCore(jobs chan int, results chan int, numJobs int) {
defer close(jobs)
// Create as many workers as there are CPU cores on the current machine
for i := 0; i < runtime.NumCPU(); i++ {
go worker(jobs, results)
}
fillQueue(jobs, numJobs)
takeJobFromQueueAndDo(results, numJobs)
}
// DemoCreateSingleWorker creates one worker to pick jobs off the queue
func DemoCreateSingleWorker(jobs chan int, results chan int, numJobs int) {
defer close(jobs)
go worker(jobs, results)
fillQueue(jobs, numJobs)
takeJobFromQueueAndDo(results, numJobs)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment