Skip to content

Instantly share code, notes, and snippets.

@nevir
Last active December 15, 2015 08:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nevir/5229850 to your computer and use it in GitHub Desktop.
Save nevir/5229850 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"runtime"
"time"
)
var NUM_THINGS = 100000
var NUM_RUNS = 5
var PARALLEL_WORKERS = 10
var WORKER_DURATION = 100 * time.Microsecond
// Specific Type Signatures
// ========================
func ConsumeWithGoroutineOnDemand(input []int, numInParallel int, worker func(int)) {
start := time.Now()
var startStats runtime.MemStats
runtime.ReadMemStats(&startStats)
sem := make(chan bool, numInParallel)
done := make(chan bool)
max := len(input)
count := 0
init := time.Now()
for i := 0; i < numInParallel; i++ {
sem <- true
}
for _, item := range input {
<-sem
// A goroutine per item of work; up to `numInParallel`.
go func(item int) {
worker(item)
count++
if count == max {
done <- true
} else {
sem <- true
}
}(item)
}
<-done
timings("ConsumeWithGoroutineOnDemand", &startStats, start, init)
}
func ConsumeWithPrespunWorkers(input []int, numInParallel int, worker func(int)) {
start := time.Now()
var startStats runtime.MemStats
runtime.ReadMemStats(&startStats)
workItems := make(chan int)
done := make(chan bool)
max := len(input)
count := 0
init := time.Now()
for i := 0; i < numInParallel; i++ {
go func() {
for item := range workItems {
worker(item)
count++
if count == max {
done <- true
}
}
}()
}
for _, item := range input {
workItems <- item
}
<-done
timings("ConsumeWithPrespunWorkers", &startStats, start, init)
}
// Benchmark Stuff
// ===============
func timings(name string, startStats *runtime.MemStats, start time.Time, init time.Time) {
finish := time.Now()
var finishStats runtime.MemStats
runtime.ReadMemStats(&finishStats)
pauseTotal := finishStats.PauseTotalNs - startStats.PauseTotalNs
allocs := finishStats.Alloc - startStats.Alloc
totalAllocs := finishStats.TotalAlloc - startStats.TotalAlloc
heapObjects := finishStats.HeapObjects - startStats.HeapObjects
fmt.Printf("%30v() init: %-5v work: %-9v | PauseTotalNs: %-3v Alloc: %-5v TotalAlloc: %-5v HeapObjects: %-3v\n", name, init.Sub(start), finish.Sub(init), pauseTotal, allocs, totalAllocs, heapObjects)
}
func spinnyWorker(thing int) {
stopAt := time.Now().Add(WORKER_DURATION).UnixNano()
for time.Now().UnixNano() < stopAt {
// spin spin spin!
}
}
func sleepyWorker(thing int) {
time.Sleep(WORKER_DURATION)
}
func main() {
things := make([]int, NUM_THINGS)
for i := 0; i < NUM_THINGS; i++ {
things[i] = i + 10
}
for i := 1; i <= NUM_RUNS; i++ {
fmt.Println("=======================================")
fmt.Printf("Spin run %v:\n", i)
ConsumeWithPrespunWorkers(things, PARALLEL_WORKERS, spinnyWorker)
ConsumeWithGoroutineOnDemand(things, PARALLEL_WORKERS, spinnyWorker)
fmt.Printf("Sleep run %v:\n", i)
ConsumeWithPrespunWorkers(things, PARALLEL_WORKERS, sleepyWorker)
ConsumeWithGoroutineOnDemand(things, PARALLEL_WORKERS, sleepyWorker)
fmt.Println("")
}
}
@nevir
Copy link
Author

nevir commented Mar 24, 2013

Interestingly, for the sleepy worker case, the ConsumeWithPrespunWorkers is consistently slower (even though it does a good deal fewer allocations):

=======================================
Spin run 1:
     ConsumeWithPrespunWorkers() init: 2us   work: 10.017635s | PauseTotalNs: 0   Alloc: 6528  TotalAlloc: 6528  HeapObjects: 17 
  ConsumeWithGoroutineOnDemand() init: 7us   work: 10.024236s | PauseTotalNs: 0   Alloc: 6544  TotalAlloc: 6544  HeapObjects: 17 
Sleep run 1:
     ConsumeWithPrespunWorkers() init: 5us   work: 1.411397s | PauseTotalNs: 0   Alloc: 46832 TotalAlloc: 46832 HeapObjects: 15 
  ConsumeWithGoroutineOnDemand() init: 5us   work: 1.354956s | PauseTotalNs: 0   Alloc: 6544  TotalAlloc: 6544  HeapObjects: 17 

=======================================
Spin run 2:
     ConsumeWithPrespunWorkers() init: 12us  work: 10.013365s | PauseTotalNs: 0   Alloc: 4288  TotalAlloc: 4288  HeapObjects: 7  
  ConsumeWithGoroutineOnDemand() init: 5us   work: 10.014742s | PauseTotalNs: 0   Alloc: 6544  TotalAlloc: 6544  HeapObjects: 17 
Sleep run 2:
     ConsumeWithPrespunWorkers() init: 4us   work: 1.391829s | PauseTotalNs: 0   Alloc: 4288  TotalAlloc: 4288  HeapObjects: 7  
  ConsumeWithGoroutineOnDemand() init: 4us   work: 1.352401s | PauseTotalNs: 0   Alloc: 6544  TotalAlloc: 6544  HeapObjects: 17 

=======================================
Spin run 3:
     ConsumeWithPrespunWorkers() init: 14us  work: 10.013346s | PauseTotalNs: 0   Alloc: 4288  TotalAlloc: 4288  HeapObjects: 7  
  ConsumeWithGoroutineOnDemand() init: 17us  work: 10.014324s | PauseTotalNs: 0   Alloc: 6544  TotalAlloc: 6544  HeapObjects: 17 
Sleep run 3:
     ConsumeWithPrespunWorkers() init: 5us   work: 1.410995s | PauseTotalNs: 0   Alloc: 4288  TotalAlloc: 4288  HeapObjects: 7  
  ConsumeWithGoroutineOnDemand() init: 7us   work: 1.354148s | PauseTotalNs: 0   Alloc: 6544  TotalAlloc: 6544  HeapObjects: 17 

=======================================
Spin run 4:
     ConsumeWithPrespunWorkers() init: 12us  work: 10.012657s | PauseTotalNs: 0   Alloc: 4288  TotalAlloc: 4288  HeapObjects: 7  
  ConsumeWithGoroutineOnDemand() init: 4us   work: 10.012414s | PauseTotalNs: 0   Alloc: 6544  TotalAlloc: 6544  HeapObjects: 17 
Sleep run 4:
     ConsumeWithPrespunWorkers() init: 6us   work: 1.409177s | PauseTotalNs: 0   Alloc: 4288  TotalAlloc: 4288  HeapObjects: 7  
  ConsumeWithGoroutineOnDemand() init: 4us   work: 1.352588s | PauseTotalNs: 0   Alloc: 6544  TotalAlloc: 6544  HeapObjects: 17 

=======================================
Spin run 5:
     ConsumeWithPrespunWorkers() init: 12us  work: 10.011348s | PauseTotalNs: 0   Alloc: 4288  TotalAlloc: 4288  HeapObjects: 7  
  ConsumeWithGoroutineOnDemand() init: 4us   work: 10.012908s | PauseTotalNs: 0   Alloc: 6544  TotalAlloc: 6544  HeapObjects: 17 
Sleep run 5:
     ConsumeWithPrespunWorkers() init: 4us   work: 1.405323s | PauseTotalNs: 0   Alloc: 4288  TotalAlloc: 4288  HeapObjects: 7  
  ConsumeWithGoroutineOnDemand() init: 6us   work: 1.351524s | PauseTotalNs: 0   Alloc: 6544  TotalAlloc: 6544  HeapObjects: 17 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment