summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Magefile.go6
-rw-r--r--cmd/anelephantinachinashop/main.go4
-rw-r--r--go.mod2
-rw-r--r--internal/cpu/helpers.go10
-rw-r--r--internal/cpu/stresser.go26
-rw-r--r--internal/cpu/types.go26
-rw-r--r--internal/cpu/worker.go34
-rw-r--r--internal/run.go2
8 files changed, 82 insertions, 28 deletions
diff --git a/Magefile.go b/Magefile.go
index 015f0f1..e344a3f 100644
--- a/Magefile.go
+++ b/Magefile.go
@@ -1,6 +1,6 @@
//go:build mage
-// Package main provides build targets for anelephantinachinashop.
+// Package main provides build targets for rampage.
// Targets follow the same style as other projects: Default builds, Test runs tests,
// Bench runs benchmarks, Install copies binary to GOPATH/bin.
package main
@@ -14,7 +14,7 @@ import (
"github.com/magefile/mage/sh"
)
-const binaryName = "anelephantinachinashop"
+const binaryName = "rampage"
// Default builds the project.
func Default() {
@@ -23,7 +23,7 @@ func Default() {
// Build compiles the binary.
func Build() error {
- return sh.RunV("go", "build", "-o", binaryName, "./cmd/anelephantinachinashop")
+ return sh.RunV("go", "build", "-o", binaryName, "./cmd/rampage")
}
// Test runs all unit tests.
diff --git a/cmd/anelephantinachinashop/main.go b/cmd/anelephantinachinashop/main.go
index 398b595..8b14dff 100644
--- a/cmd/anelephantinachinashop/main.go
+++ b/cmd/anelephantinachinashop/main.go
@@ -5,8 +5,8 @@ import (
"fmt"
"log"
- "codeberg.org/snonux/anelephantinachinashop/internal"
- "codeberg.org/snonux/anelephantinachinashop/internal/config"
+ "codeberg.org/snonux/rampage/internal"
+ "codeberg.org/snonux/rampage/internal/config"
)
func main() {
diff --git a/go.mod b/go.mod
index 53a1c66..352dcb7 100644
--- a/go.mod
+++ b/go.mod
@@ -1,4 +1,4 @@
-module codeberg.org/snonux/anelephantinachinashop
+module codeberg.org/snonux/rampage
go 1.26.2
diff --git a/internal/cpu/helpers.go b/internal/cpu/helpers.go
index 9fcc6b9..138cf8c 100644
--- a/internal/cpu/helpers.go
+++ b/internal/cpu/helpers.go
@@ -11,6 +11,16 @@ func (s *Stresser) randomIntensity() int {
return s.rand.Intn(s.config.IntensityMax-s.config.IntensityMin+1) + s.config.IntensityMin
}
+func (s *Stresser) determineCPUCount() int {
+ if s.config.ChaosEnabled {
+ return s.rand.Intn(s.config.MaxCPUs-s.config.MinCPUs+1) + s.config.MinCPUs
+ }
+ if s.config.Workers > 0 {
+ return s.config.Workers
+ }
+ return s.config.MaxCPUs
+}
+
func (s *Stresser) getRandomMode() Mode {
return allModes[s.rand.Intn(len(allModes))]
}
diff --git a/internal/cpu/stresser.go b/internal/cpu/stresser.go
index 906467a..62ae3b7 100644
--- a/internal/cpu/stresser.go
+++ b/internal/cpu/stresser.go
@@ -13,12 +13,13 @@ import (
// Stresser uses pointer receivers because it contains a sync.Mutex
// and shared mutable state that must not be copied.
type Stresser struct {
- config Config
- cancel context.CancelFunc
- wg sync.WaitGroup
- mu sync.Mutex
- current Mode
- rand *rand.Rand
+ config Config
+ cancel context.CancelFunc
+ wg sync.WaitGroup
+ mu sync.Mutex
+ current Mode
+ currentCPUs int
+ rand *rand.Rand
}
func New(cfg Config) *Stresser {
@@ -34,6 +35,11 @@ func New(cfg Config) *Stresser {
if cfg.Mode == "" {
cfg.Mode = ModePrime
}
+ if !cfg.ChaosEnabled && cfg.MinCPUs <= 0 {
+ cfg.MinCPUs = cfg.Workers
+ cfg.MaxCPUs = cfg.Workers
+ }
+ cfg.normalize()
return &Stresser{
config: cfg,
rand: rand.New(rand.NewSource(time.Now().UnixNano())),
@@ -44,8 +50,12 @@ func (s *Stresser) Start() {
ctx, cancel := context.WithCancel(context.Background())
s.cancel = cancel
- s.wg.Add(s.config.Workers)
- for i := 0; i < s.config.Workers; i++ {
+ s.mu.Lock()
+ s.currentCPUs = s.determineCPUCount()
+ s.mu.Unlock()
+
+ s.wg.Add(s.currentCPUs)
+ for i := 0; i < s.currentCPUs; i++ {
go s.worker(ctx, i)
}
diff --git a/internal/cpu/types.go b/internal/cpu/types.go
index 58da0a9..45f6ff5 100644
--- a/internal/cpu/types.go
+++ b/internal/cpu/types.go
@@ -1,7 +1,10 @@
// Package cpu provides CPU stress testing with multiple algorithms and chaos modes.
package cpu
-import "time"
+import (
+ "runtime"
+ "time"
+)
// types.go defines the configuration types and mode constants for CPU stress testing.
@@ -18,7 +21,6 @@ const (
ModeEncrypt Mode = "encrypt"
ModeSort Mode = "sort"
ModeBusy Mode = "busy"
- ModeRandom Mode = "random"
)
var allModes = []Mode{
@@ -42,4 +44,24 @@ type Config struct {
ChaosInterval time.Duration
IntensityMin int
IntensityMax int
+ MinCPUs int
+ MaxCPUs int
+}
+
+func (c *Config) normalize() {
+ if c.MinCPUs <= 0 {
+ c.MinCPUs = 1
+ }
+ if c.MaxCPUs <= 0 {
+ c.MaxCPUs = runtime.NumCPU()
+ }
+ if c.MinCPUs > runtime.NumCPU() {
+ c.MinCPUs = runtime.NumCPU()
+ }
+ if c.MaxCPUs > runtime.NumCPU() {
+ c.MaxCPUs = runtime.NumCPU()
+ }
+ if c.MinCPUs > c.MaxCPUs {
+ c.MinCPUs, c.MaxCPUs = c.MaxCPUs, c.MinCPUs
+ }
}
diff --git a/internal/cpu/worker.go b/internal/cpu/worker.go
index 06f6812..b11dc9a 100644
--- a/internal/cpu/worker.go
+++ b/internal/cpu/worker.go
@@ -12,10 +12,6 @@ func (s *Stresser) worker(ctx context.Context, id int) {
defer s.wg.Done()
mode := s.config.Mode
- if s.config.ChaosEnabled {
- mode = s.getRandomMode()
- }
-
intensity := s.randomIntensity()
ticker := time.NewTicker(10 * time.Millisecond)
@@ -31,13 +27,10 @@ func (s *Stresser) worker(ctx context.Context, id int) {
mode = s.current
s.mu.Unlock()
intensity = s.randomIntensity()
+ s.sleepWithJitter(1, 50)
}
s.executeStress(ctx, mode, intensity)
-
- if s.config.ChaosEnabled {
- s.sleepWithJitter(1, 50)
- }
}
}
}
@@ -53,11 +46,33 @@ func (s *Stresser) chaosController(ctx context.Context) {
case <-ticker.C:
s.mu.Lock()
s.current = s.getRandomMode()
+ newCPUCount := s.determineCPUCount()
+ if newCPUCount != s.currentCPUs {
+ s.adjustWorkers(ctx, newCPUCount)
+ }
s.mu.Unlock()
}
}
}
+func (s *Stresser) adjustWorkers(ctx context.Context, newCount int) {
+ if newCount > s.currentCPUs {
+ for i := s.currentCPUs; i < newCount; i++ {
+ s.wg.Add(1)
+ go s.worker(ctx, i)
+ }
+ } else if newCount < s.currentCPUs {
+ s.cancel()
+ s.wg.Wait()
+ ctx, s.cancel = context.WithCancel(context.Background())
+ for i := 0; i < newCount; i++ {
+ s.wg.Add(1)
+ go s.worker(ctx, i)
+ }
+ }
+ s.currentCPUs = newCount
+}
+
func (s *Stresser) executeStress(ctx context.Context, mode Mode, intensity int) {
switch mode {
case ModePrime:
@@ -80,8 +95,5 @@ func (s *Stresser) executeStress(ctx context.Context, mode Mode, intensity int)
s.stressSort(ctx, intensity)
case ModeBusy:
s.stressBusy(ctx, intensity)
- case ModeRandom:
- randomMode := allModes[s.rand.Intn(len(allModes))]
- s.executeStress(ctx, randomMode, intensity)
}
}
diff --git a/internal/run.go b/internal/run.go
index e3bb597..358fe94 100644
--- a/internal/run.go
+++ b/internal/run.go
@@ -1,6 +1,6 @@
package internal
-import "codeberg.org/snonux/anelephantinachinashop/internal/config"
+import "codeberg.org/snonux/rampage/internal/config"
func Run(conf config.Config) error {
return nil