Skip to content

Instantly share code, notes, and snippets.

@roohitavaf
Created October 29, 2023 19:27
Show Gist options
  • Save roohitavaf/efc72eec0be4b80ebb9abe915689e7e4 to your computer and use it in GitHub Desktop.
Save roohitavaf/efc72eec0be4b80ebb9abe915689e7e4 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"math/rand"
"runtime"
"sync"
"time"
)
type Parameters struct {
serversNum, workload, serverCapacity int
serverAvailability float64
}
func calculateAvailability(samplesNum uint64, params Parameters) float64 {
numCPU := runtime.NumCPU()
fmt.Printf("Using %v CPUs\n", numCPU)
wg := new(sync.WaitGroup)
availabilityChannel := make(chan float64, numCPU)
for c := 0; c < numCPU; c++ {
wg.Add(1)
go calculateAvailabilitySingleCore(samplesNum/uint64(numCPU), params, availabilityChannel, wg)
}
wg.Wait()
close(availabilityChannel)
var availabilities []float64
for availability := range availabilityChannel {
availabilities = append(availabilities, availability)
}
return aggregate(availabilities)
}
func calculateAvailabilitySingleCore(samplesNum uint64, params Parameters, availabilityChannel chan<- float64, wg *sync.WaitGroup) {
defer wg.Done()
samples := make([]float64, samplesNum)
for i := uint64(0); i < samplesNum; i++ {
state := make([]bool, params.serversNum)
for s := 0; s < params.serversNum; s++ {
state[s] = isServerAvailable(params.serverAvailability)
}
samples[i] = min(1, float64(computeCapacity(state, params.serverCapacity))/float64(params.workload))
}
result := aggregate(samples)
fmt.Printf("Partial result: %v\n", result)
availabilityChannel <- result
}
func isServerAvailable(availability float64) bool {
source := rand.NewSource(time.Now().UnixNano())
randomGenerator := rand.New(source)
randomValue := randomGenerator.Float64()
return randomValue < availability
}
func computeCapacity(state []bool, serverCapacity int) int {
capacity := 0
for _, isAvailable := range state {
if isAvailable {
capacity += serverCapacity
}
}
return capacity
}
func aggregate(samples []float64) float64 {
if len(samples) == 0 {
return 0.0
}
sum := float64(0.0)
for i := 0; i < len(samples); i++ {
sum += samples[i]
}
return sum / float64(len(samples))
}
func main() {
serverCapacity := 6 //6 kqps
serverAvailability := float64(0.99) //MTTF/(MTTR + MTTF)
serversNum := 8
workload := serversNum * serverCapacity * 70 / 100 //we want to have a 30% headroom
samplesNum := uint64(1000000)
result := calculateAvailability(samplesNum, Parameters{serversNum, workload, serverCapacity, serverAvailability})
fmt.Printf("Result: %v\n", result)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment