package main

import (
	"sync"
	"time"
)

const (
	ballastSize   = 10 << 20
	garbageSize   = 1 << 20
	garbagePeriod = 100 * time.Millisecond

	stackCount  = 10000
	stackSize   = 10 << 10
	stackPeriod = 5 * time.Second
)

var (
	ballast []byte
	garbage []byte
)

func churn() {
	ballast = make([]byte, ballastSize)

	for {
		time.Sleep(garbagePeriod)
		garbage = make([]byte, garbageSize)
	}
}

func stack(a, b *sync.WaitGroup) {
	for {
		grow(a)
		b.Wait()
	}
}

func grow(a *sync.WaitGroup) byte {
	var s [stackSize]byte
	a.Wait()
	return s[0]
}

func main() {
	go churn()

	var a, b sync.WaitGroup
	a.Add(1)
	for i := 0; i < stackCount; i++ {
		go stack(&a, &b)
	}

	for {
		time.Sleep(stackPeriod / 2)
		b.Add(1)
		a.Add(-1)

		time.Sleep(stackPeriod / 2)
		a.Add(1)
		b.Add(-1)
	}
}
