66 "math"
77 "math/rand"
88 "slices"
9+ "strings"
910 "sync"
1011 "sync/atomic"
1112 "testing"
@@ -69,6 +70,7 @@ type NodeFactory func(id string, config BenchmarkConfig) NodeSimulator
6970// StandardNode implements the original SimulatedNode logic (real-time metric synchronization)
7071type StandardNode struct {
7172 * nodemanager.Node
73+
7274 mu sync.RWMutex
7375 sandboxes map [string ]* LiveSandbox
7476 totalPlacements int64
@@ -103,6 +105,7 @@ func (n *StandardNode) PlaceSandbox(sbx *LiveSandbox) bool {
103105 // Check capacity with overcommit (Original Logic)
104106 if metrics .CpuAllocated + uint32 (sbx .RequestedCPU ) > metrics .CpuCount * 4 {
105107 atomic .AddInt64 (& n .rejectedPlacements , 1 )
108+
106109 return false
107110 }
108111
@@ -118,6 +121,7 @@ func (n *StandardNode) PlaceSandbox(sbx *LiveSandbox) bool {
118121 })
119122 n .sandboxes [sbx .ID ] = sbx
120123 atomic .AddInt64 (& n .totalPlacements , 1 )
124+
121125 return true
122126}
123127
@@ -151,12 +155,14 @@ func (n *StandardNode) GetUtilization() (float64, float64) {
151155 if metrics .MemoryTotalBytes > 0 {
152156 memUtil = (float64 (metrics .MemoryUsedBytes ) / float64 (metrics .MemoryTotalBytes )) * 100
153157 }
158+
154159 return cpuUtil , memUtil
155160}
156161
157162func (n * StandardNode ) GetSandboxCount () int {
158163 n .mu .RLock ()
159164 defer n .mu .RUnlock ()
165+
160166 return len (n .sandboxes )
161167}
162168
@@ -174,6 +180,7 @@ type LaggyNode struct {
174180
175181func NewLaggyNode (id string , config BenchmarkConfig ) NodeSimulator {
176182 base := NewStandardNode (id , config ).(* StandardNode )
183+
177184 return & LaggyNode {
178185 StandardNode : base ,
179186 }
@@ -189,6 +196,7 @@ func (n *LaggyNode) PlaceSandbox(sbx *LiveSandbox) bool {
189196 metrics := n .Node .Metrics ()
190197 if n .realCpuAllocated + uint32 (sbx .RequestedCPU ) > metrics .CpuCount * 4 {
191198 atomic .AddInt64 (& n .rejectedPlacements , 1 )
199+
192200 return false
193201 }
194202
@@ -282,6 +290,7 @@ func createSimulatedNodes(config BenchmarkConfig, factory NodeFactory) []NodeSim
282290 for i := range config .NumNodes {
283291 nodes [i ] = factory (fmt .Sprintf ("node-%d" , i ), config )
284292 }
293+
285294 return nodes
286295}
287296
@@ -291,6 +300,7 @@ func toNodeManagerNodes(simNodes []NodeSimulator) []*nodemanager.Node {
291300 for i , n := range simNodes {
292301 nodes [i ] = n .GetNode ()
293302 }
303+
294304 return nodes
295305}
296306
@@ -300,7 +310,7 @@ func runBenchmark(b *testing.B, algorithm Algorithm, config BenchmarkConfig, nod
300310
301311 parentCtx := b .Context ()
302312 if parentCtx == nil {
303- parentCtx = context .Background ()
313+ parentCtx = context .Background ()
304314 }
305315 ctx , cancel := context .WithTimeout (parentCtx , config .BenchmarkDuration )
306316 defer cancel ()
@@ -411,8 +421,8 @@ func runBenchmark(b *testing.B, algorithm Algorithm, config BenchmarkConfig, nod
411421 placementStart := time .Now ()
412422 node , err := PlaceSandbox (ctx , algorithm , nodes , nil , & orchestratorgrpc.SandboxCreateRequest {Sandbox : & orchestratorgrpc.SandboxConfig {
413423 SandboxId : sbx .ID ,
414- Vcpu : sbx .RequestedCPU ,
415- RamMb : sbx .RequestedMemory ,
424+ Vcpu : sbx .RequestedCPU ,
425+ RamMb : sbx .RequestedMemory ,
416426 }}, machineinfo.MachineInfo {}, false , nil )
417427
418428 placementTime := time .Since (placementStart )
@@ -610,13 +620,13 @@ func BenchmarkPlacementDistribution(b *testing.B) {
610620 // Scenario config: “thundering herd” test under extremely high concurrency
611621 // Use LaggyNode to simulate metric reporting delay: Orchestrator always sees stale metrics
612622 config := BenchmarkConfig {
613- NumNodes : 10 , // Fewer nodes to make load hotspots more apparent
614- SandboxStartRate : 20 , // 20 requests per second (burst traffic)
615- AvgSandboxCPU : 1 , // 1 vCPU per Sandbox
616- AvgSandboxMemory : 1024 , // 1024 MiB
617- CPUVariance : 0.0 , // Fixed spec for easier distribution observation
623+ NumNodes : 10 , // Fewer nodes to make load hotspots more apparent
624+ SandboxStartRate : 20 , // 20 requests per second (burst traffic)
625+ AvgSandboxCPU : 1 , // 1 vCPU per Sandbox
626+ AvgSandboxMemory : 1024 , // 1024 MiB
627+ CPUVariance : 0.0 , // Fixed spec for easier distribution observation
618628 MemoryVariance : 0.0 ,
619- ActualUsageRatio : 1.0 , // Assume full utilization
629+ ActualUsageRatio : 1.0 , // Assume full utilization
620630 ActualUsageVariance : 0.0 ,
621631 SandboxDuration : 1 * time .Minute , // Long enough to ensure no release during test
622632 BenchmarkDuration : 25 * time .Second , // Run long enough to trigger at least one heartbeat sync (20s ticker)
@@ -684,9 +694,7 @@ func BenchmarkPlacementDistribution(b *testing.B) {
684694
685695 // 4. Concurrently generate Sandbox requests
686696 var wg sync.WaitGroup
687- wg .Add (1 )
688- go func () {
689- defer wg .Done ()
697+ wg .Go (func () {
690698 ticker := time .NewTicker (time .Second / time .Duration (config .SandboxStartRate ))
691699 defer ticker .Stop ()
692700
@@ -708,14 +716,12 @@ func BenchmarkPlacementDistribution(b *testing.B) {
708716
709717 wg .Add (1 )
710718 go func (s * LiveSandbox ) {
711- defer wg .Done ()
712-
713719 // Execute placement algorithm
714720 node , err := PlaceSandbox (ctx , alg .algo , nodes , nil , & orchestratorgrpc.SandboxCreateRequest {
715721 Sandbox : & orchestratorgrpc.SandboxConfig {
716722 SandboxId : s .ID ,
717- Vcpu : s .RequestedCPU ,
718- RamMb : s .RequestedMemory ,
723+ Vcpu : s .RequestedCPU ,
724+ RamMb : s .RequestedMemory ,
719725 },
720726 }, machineinfo.MachineInfo {}, false , nil )
721727
@@ -728,7 +734,7 @@ func BenchmarkPlacementDistribution(b *testing.B) {
728734 }(sbx )
729735 }
730736 }
731- }( )
737+ })
732738
733739 <- ctx .Done ()
734740 wg .Wait ()
@@ -748,6 +754,7 @@ func BenchmarkPlacementDistribution(b *testing.B) {
748754
749755 if totalCount == 0 {
750756 b .Log ("No sandboxes placed." )
757+
751758 return
752759 }
753760
@@ -759,9 +766,9 @@ func BenchmarkPlacementDistribution(b *testing.B) {
759766 barLen = int (float64 (count ) / float64 (maxCount ) * 40 ) // Max 40 characters
760767 }
761768
762- bar := ""
763- for k := 0 ; k < barLen ; k ++ {
764- bar += "█"
769+ var bar strings. Builder
770+ for range barLen {
771+ bar . WriteString ( "█" )
765772 }
766773
767774 // Force Sync before printing to ensure we see the final real values
@@ -770,7 +777,7 @@ func BenchmarkPlacementDistribution(b *testing.B) {
770777 }
771778 cpuUtil , _ := n .GetUtilization ()
772779
773- b .Logf ("Node %02d |%s| %d (CPU: %.1f%%)" , i , fmt .Sprintf ("%-40s" , bar ), count , cpuUtil )
780+ b .Logf ("Node %02d |%s| %d (CPU: %.1f%%)" , i , fmt .Sprintf ("%-40s" , bar . String () ), count , cpuUtil )
774781 }
775782
776783 // Calculate distribution statistics (CV coefficient of variation)
@@ -788,4 +795,4 @@ func BenchmarkPlacementDistribution(b *testing.B) {
788795 b .Logf ("Stats: Total=%d, Avg=%.1f, StdDev=%.2f, Imbalance(CV)=%.3f" , totalCount , avg , stdDev , cv )
789796 })
790797 }
791- }
798+ }
0 commit comments