为了账号安全,请及时绑定邮箱和手机立即绑定

注意进入 Go 循环

注意进入 Go 循环

Go
呼啦一阵风 2022-09-12 16:59:53
我已经编写了代码来获取CPU内核的使用百分比。如果一个内核的 CPU 使用率低于 50%,我将运行压力测试代码,以将使用率百分比提高到高于 50%。我必须为所有CPU内核应用此策略。这是我的完整代码:package mainimport (    "fmt"    "io/ioutil"    "net/http"    "os"    "strconv"    "strings"    "time"    "github.com/dhoomakethu/stress/utils"    strip "github.com/grokify/html-strip-tags-go")func main() {    url := "http://localhost:8080/getCPU"    resp := Get(url)    //remove htlm tag    stripped := strip.StripTags(resp)    s := strings.Split(stripped, "%")    var j []int    for i := 0; i < len(s)-1; i++ {        number, _ := strconv.Atoi(s[i])        if number < 50 {            j = append(j, i)        }    }    fmt.Println(j)    sampleInterval := 100 * time.Millisecond    cpuload := 1.0    duration := 300.0    for a := 0; a < len(j)/2; a++ {        cpucore := j[a]        runCpuLoader(sampleInterval, cpuload, duration, cpucore)    }}//GETfunc Get(url string) string {    response, err := http.Get(url)    if err != nil {        fmt.Printf("%s", err)        os.Exit(1)    } else {        defer response.Body.Close()        contents, err := ioutil.ReadAll(response.Body)        if err != nil {            fmt.Printf("%s", err)            os.Exit(1)        }        return string(contents)    }    return ""}// stress cpufunc runCpuLoader(sampleInterval time.Duration, cpuload float64, duration float64, cpu int)   {    controller := utils.NewCpuLoadController(sampleInterval, cpuload)    monitor := utils.NewCpuLoadMonitor(float64(cpu), sampleInterval)    actuator := utils.NewCpuLoadGenerator(controller, monitor, time.Duration(duration))    utils.StartCpuLoadController(controller)    utils.StartCpuMonitor(monitor)    utils.RunCpuLoader(actuator)    utils.StopCpuLoadController(controller)    utils.StopCpuMonitor(monitor)}在这段代码中for a := 0; a < len(j)/2; a++ {    cpucore := j[a]    runCpuLoader(sampleInterval, cpuload, duration, cpucore)   }}我希望代码并发运行压力测试增加 CPU 使用率的百分比。但该函数的持续时间为 5 分钟,因此它不能作为并发运行。runCpuLoader(sampleInterval, cpuload, duration, cpucore)
查看完整描述

1 回答

?
德玛西亚99

TA贡献1770条经验 获得超3个赞

您应该完成围棋之旅,并特别关注围棋例程以及查看等待组。我将在这里简要介绍适用的概念。

关键字go

在Go中,同时运行函数非常容易。鉴于以下代码,我只需要在 前面添加前缀,使其与程序的其余部分同时运行。goblockingCode

func blockingCode() {

    time.Sleep(time.Second)

    fmt.Println("finishing blocking")

}


func main() {

    fmt.Println("starting main")

    go blockingCode()

    fmt.Println("finishing main")

}

你会注意到关于这一点的几件事:

  • 如果我删除了前缀,该函数将被阻止,您将看到所有三个打印语句,最后两个比第一个打印语句晚一秒(去游乐场)。go

  • 如果我重新添加前缀,该函数不会阻塞,但您不会看到 print 语句。这是因为主函数(主 go 例程)在完成之前终止。这就是等待组发挥作用的地方。gofmt.Println("finishing blocking")blockingCode

WaitGroup

要等待多个戈鲁丁完成,我们可以使用一个等待组。https://gobyexample.com/waitgroups

将等待组视为原子计数器,其中调用阻塞直到计数器为 0。生成 go 例程时,会递增计数器 (),在完成 go 例程时,会取消递增计数器 ()。下面是支持等待组的代码。去游乐场wg.Waitwg.Addwg.Done

func blockingCode(wg *sync.WaitGroup) {

    defer wg.Done()

    time.Sleep(time.Second)

    fmt.Println("finishing blocking")

}


func main() {

    wg := sync.WaitGroup{}

    fmt.Println("starting main")

    wg.Add(1)

    go blockingCode(&wg)

    wg.Wait()

    fmt.Println("finishing main")

}

现在,这会产生与我们上面看到的完全相同的行为 - 该函数将阻塞,您将看到所有三个print语句,最后两个比第一个延迟一秒钟打印 - 那么为什么我们首先将其并发?不同之处在于,我们现在可以同时运行许多事情,而不是按顺序运行很多事情。在这种情况下,我们没有看到并发的好处的原因是因为我们只同时做一件事。


让我们调整示例以运行多次。您会注意到,脚本运行所需的时间几乎相同,即使我们调用的 blockCode 需要整整一秒钟才能运行,三次,如果我们删除关键字和等待组,我们会看到此代码至少需要三秒钟才能运行 go Playground。blockingCodego


func blockingCode(wg *sync.WaitGroup) {

    defer wg.Done()

    time.Sleep(time.Second)

    fmt.Println("finishing blocking")

}


func main() {

    wg := sync.WaitGroup{}

    fmt.Println("starting main")

    wg.Add(1)

    go blockingCode(&wg)

    wg.Add(1)

    go blockingCode(&wg)

    wg.Add(1)

    go blockingCode(&wg)

    wg.Wait()

    fmt.Println("finishing main")

}

您的示例

您选择如何处理并发行为很大程度上取决于应用程序的细节,但是像这样的东西应该实现我在这里提供的并发概念,并允许您与加载程序同时运行监视器。


func main() {

    // ...

    wg := sync.WaitGroup{}

    for a := 0; a < len(j)/2; a++ {

        cpucore := j[a]

        wg.Add(1)

        go runCpuLoader(&wg, sampleInterval, cpuload, duration, cpucore)

    }

    wg.Wait()

}


func runCpuLoader(wg *sync.WaitGroup, sampleInterval time.Duration, cpuload float64, duration float64, cpu int) {

    defer wg.Done()

    // ...

}


查看完整回答
反对 回复 2022-09-12
  • 1 回答
  • 0 关注
  • 82 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信