|
9 | 9 | "runtime" |
10 | 10 | "strconv" |
11 | 11 | "strings" |
12 | | - "syscall" |
| 12 | + "sync" |
13 | 13 | "time" |
14 | 14 |
|
15 | 15 | log "github.com/sirupsen/logrus" |
@@ -89,10 +89,7 @@ func (cli *cli) executeCommand(command string) error { |
89 | 89 | leakMem() |
90 | 90 | } else if command == "leak cpu" { |
91 | 91 | log.Info("Leaking CPU") |
92 | | - err := leakCpu() |
93 | | - if err != nil { |
94 | | - return fmt.Errorf("error on leaking CPU: %s", err) |
95 | | - } |
| 92 | + leakCpu() |
96 | 93 | } else if strings.HasPrefix(command, "request ") { |
97 | 94 | url, _ := strings.CutPrefix(command, "request ") |
98 | 95 | log.Infof("Requesting URL '%s'", url) |
@@ -177,36 +174,60 @@ func leakMem() { |
177 | 174 | } |
178 | 175 | } |
179 | 176 |
|
180 | | -func leakCpu() error { |
| 177 | +func leakCpu() { |
181 | 178 |
|
182 | | - // TODO is this really the smartest way to create a CPU leak? |
| 179 | + var waitGroup sync.WaitGroup |
| 180 | + ticker := time.NewTicker(1 * time.Second) |
| 181 | + defer ticker.Stop() |
183 | 182 |
|
184 | | - writer, err := os.Open(os.DevNull) |
185 | | - if err != nil { |
186 | | - log.Errorf("Error on opening /dev/null: %s", err) |
187 | | - return err |
| 183 | + for range ticker.C { |
| 184 | + numGoroutines := runtime.NumGoroutine() |
| 185 | + fmt.Printf("Current number of goroutines: %d\n", numGoroutines) |
| 186 | + |
| 187 | + // Spawn a new goroutine every second |
| 188 | + waitGroup.Add(1) |
| 189 | + go cpuIntensiveTask(&waitGroup, numGoroutines+1) |
188 | 190 | } |
189 | | - defer writer.Close() |
190 | | - n := runtime.NumCPU() |
191 | | - runtime.GOMAXPROCS(n) |
192 | | - |
193 | | - for i := 0; i < n; i++ { |
194 | | - go func() { |
195 | | - for { |
196 | | - var usage syscall.Rusage |
197 | | - err = syscall.Getrusage(syscall.RUSAGE_SELF, &usage) |
198 | | - if err != nil { |
199 | | - log.Errorf("Error on cpu usage: %s", err) |
200 | | - } |
201 | | - log.Infof("User CPU Time: %v\n", usage.Utime) |
202 | | - log.Infof("System CPU Time: %v\n", usage.Stime) |
203 | | - fmt.Fprintf(writer, ".") |
204 | | - } |
205 | | - }() |
| 191 | +} |
| 192 | + |
| 193 | +func cpuIntensiveTask(waitGroup *sync.WaitGroup, id int) { |
| 194 | + defer waitGroup.Done() |
| 195 | + fmt.Printf("Goroutine %d started\n", id) |
| 196 | + for i := 0; i < 1e9; i++ { |
| 197 | + // Perform some CPU-intensive computation |
| 198 | + _ = i * i |
206 | 199 | } |
207 | | - |
208 | | - // TODO do I need this? |
209 | | - // time.Sleep(10 * time.Second) |
210 | | - return nil |
211 | | - |
| 200 | + fmt.Printf("Goroutine %d finished\n", id) |
212 | 201 | } |
| 202 | + |
| 203 | + // // TODO is this really the smartest way to create a CPU leak? |
| 204 | + |
| 205 | + // writer, err := os.Open(os.DevNull) |
| 206 | + // if err != nil { |
| 207 | + // log.Errorf("Error on opening /dev/null: %s", err) |
| 208 | + // return err |
| 209 | + // } |
| 210 | + // defer writer.Close() |
| 211 | + // n := runtime.NumCPU() |
| 212 | + // runtime.GOMAXPROCS(n) |
| 213 | + |
| 214 | + // for i := 0; i < n; i++ { |
| 215 | + // go func() { |
| 216 | + // for { |
| 217 | + // var usage syscall.Rusage |
| 218 | + // err = syscall.Getrusage(syscall.RUSAGE_SELF, &usage) |
| 219 | + // if err != nil { |
| 220 | + // log.Errorf("Error on cpu usage: %s", err) |
| 221 | + // } |
| 222 | + // log.Infof("User CPU Time: %v\n", usage.Utime) |
| 223 | + // log.Infof("System CPU Time: %v\n", usage.Stime) |
| 224 | + // fmt.Fprintf(writer, ".") |
| 225 | + // } |
| 226 | + // }() |
| 227 | + // } |
| 228 | + |
| 229 | + // // TODO do I need this? |
| 230 | + // // time.Sleep(10 * time.Second) |
| 231 | + // return nil |
| 232 | + |
| 233 | +// } |
0 commit comments