如何人为增加CPU使用率

huangapple go评论67阅读模式
英文:

How to artificially increase CPU usage

问题

我需要一个Go代码片段来增加CPU使用率,这是为了测试在运行我的Go服务的K8s集群中自动扩展。我尝试了使用一个循环计算平方根并打印结果,但它几乎没有利用CPU。

package main

import (
	"fmt"
	"math"
	"time"
)

func main() {
	for i := 0; i < 1000000; i++ {
		num := float64(i)
		num += math.Sqrt(num)
		fmt.Println(num)
		time.Sleep(time.Millisecond * 100) // 控制循环速度
	}
}

如果不是无限循环会更好,因为我还需要停止负载并测试扩展。

英文:

I need a Go code snippet to increase CPU usage, this is to test auto-scaling in a K8s cluster running a pod with my service written in Go. I tried with a loop calculating Sqrt as show below and print the result but it hardly utilizes the CPU.

num += math.Sqrt(num)
fmt.Println(num)

It would be better if it's not an infinite loop since I need to also stop the load and test scaling in.

答案1

得分: 19

你真的不需要任何“CPU密集型”的计算;你只需要避免阻塞操作(比如等待网络连接上的数据或写入文件),并且你需要至少与可用的CPU核心数量一样多的goroutine来执行这些操作(可以使用runtime.NumCPU()查询可用的核心数量)。

请注意,你甚至不需要手动设置可以同时执行的最大CPU数量(runtime.GOMAXPROCS()),因为自Go 1.5版本以来,默认值就是可用核心的数量。

使用fmt.Println()是一个不好的主意,因为它可能会被重定向到文件、网络连接等,因此打印到它可能会阻塞(I/O等待)。

使用一个“无限”循环,除了检查是否到达终止时间外什么都不做。你可以使用一个单独的通道来实现这个,当你想要终止时关闭它,因为从一个关闭的通道接收可以立即进行,产生通道元素类型的零值,而goroutine可以使用select语句检查它,同时还有一个default分支,否则select语句将永远阻塞。

最简单的解决方案:

done := make(chan int)

for i := 0; i < runtime.NumCPU(); i++ {
	go func() {
		for {
			select {
			case <-done:
				return
			default:
			}
		}
	}()
}

time.Sleep(time.Second * 10)
close(done)
英文:

You don't really need any "CPU-intensive" calculations; you just have to avoid blocking operations (such as waiting for data on a network connection or writing to a file) and you need at least as many goroutines doing this as CPU cores you have available (this can be queried using runtime.NumCPU()).

Note that you don't even have to manually set the max number of CPUs that can execute simultaneously (runtime.GOMAXPROCS()), as this defaults to the number of available cores since Go 1.5.

Using fmt.Println() is a bad idea as it may be directed to a file, a network connection etc., and as such, printing to it may block (I/O wait).

Use an "endless" loop which does nothing except check if it's time to abort. You can do this with a single channel, closing it when you want to abort, as receiving on a closed channel can proceed immediately, yielding the zero value of the element type of the channel, and goroutines may check it using the select statement while also having a default branch, else the select statement would just block forever.

Simplest solution:

done := make(chan int)

for i := 0; i &lt; runtime.NumCPU(); i++ {
	go func() {
		for {
			select {
			case &lt;-done:
				return
			default:
			}
		}
	}()
}

time.Sleep(time.Second * 10)
close(done)

答案2

得分: 4

这是一个小片段,它使用所有的核心将.字符写入/dev/null,并在10秒后停止。

在我的情况下,这几乎使用了我Intel Core 2 Duo @ 2.20GHz的100%的资源,所以我不知道在更高配置的环境中执行时会有什么表现,但我猜增加goroutine的数量可能会有所改善。

package main

import (
	"fmt"
	"os"
	"runtime"
	"time"
)

func main() {
	f, err := os.Open(os.DevNull)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	n := runtime.NumCPU()
	runtime.GOMAXPROCS(n)

	for i := 0; i < n; i++ {
		go func() {
			for {
				fmt.Fprintf(f, ".")
			}
		}()
	}

	time.Sleep(10 * time.Second)
}
英文:

Here's a little snippet that writes . characters to /dev/null using all your cores, and stops after 10 seconds.

In my case this uses almost 100% of my Intel Core 2 Duo @ 2.20GHz, so I don't know how it will behave when executed somewhere with higher specs, but I guess increasing the number of goroutines would do.

package main

import (
	&quot;fmt&quot;
	&quot;os&quot;
	&quot;runtime&quot;
	&quot;time&quot;
)

func main() {
	f, err := os.Open(os.DevNull)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	n := runtime.NumCPU()
	runtime.GOMAXPROCS(n)

	for i := 0; i &lt; n; i++ {
		go func() {
			for {
				fmt.Fprintf(f, &quot;.&quot;)
			}
		}()
	}

	time.Sleep(10 * time.Second)
}

答案3

得分: 2

noisypixy的想法是使用所有的核心,但在我的机器上,它只能使所有处理器的负载达到约50%。我认为这是由于打印操作速度慢,但不会占用太多CPU资源。

package main

import (
	"runtime"
	"time"
)

func main() {
	n := runtime.NumCPU()
	runtime.GOMAXPROCS(n)

	quit := make(chan bool)

	for i := 0; i < n; i++ {
		go func() {
			for {
				select {
				case <-quit:
					return
				default:
				}
			}
		}()
	}

	time.Sleep(10 * time.Second)
	for i := 0; i < n; i++ {
		quit <- true
	}
}
英文:

noisypixy has the right idea with using all cores, but on my machine it only managed to hit about 50% load on all processors. I believe this is due to Prints being slow, but not CPU intensive.

package main

import (
	&quot;runtime&quot;
	&quot;time&quot;
)

func main() {
    n := runtime.NumCPU()
    runtime.GOMAXPROCS(n)

    quit := make(chan bool)

	for i := 0; i &lt; n; i++ {
    	go func() {
    		for {
    			select {
	    		case &lt;-quit:
    				return
	    		default:
	    		}
	    	}
	    }()
    }

    time.Sleep(10 * time.Second)
    for i := 0; i &lt; n; i++ {
    	quit &lt;- true
    }
}

huangapple
  • 本文由 发表于 2016年12月11日 03:37:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/41079492.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定