以下の内容はhttps://devlights.hatenablog.com/entry/2025/05/07/073000より取得しました。


Goメモ-571 (gopsutilを利用してCPU使用率を取得)(cpu.Percent, cpu.PercentWithContext)

関連記事

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。

たまにCPU使用率やメモリ使用量を取得して評価する必要があったりします。

シェルスクリプトなどでちょこっと作成して流したりするのが一番多いのですが、Goで作成したいときもあったりします。

そういう場合、gopsutilというとても便利なライブラリが以下で公開されています。

github.com

Pythonの psutil をGoに移植してくださっているライブラリ。

とても使いやすいです。

サンプル(CPU使用率)

main.go

package main

import (
    "context"
    "errors"
    "flag"
    "log"
    "math"
    "runtime"
    "time"

    "github.com/shirou/gopsutil/v4/cpu"
)

type (
    Args struct {
        perCpu  bool
        spinCpu bool
    }
)

var (
    args Args
)

func init() {
    flag.BoolVar(&args.perCpu, "percpu", false, "per-cpu")
    flag.BoolVar(&args.spinCpu, "spincpu", false, "spin-cpu")
}

func main() {
    log.SetFlags(log.Ltime)
    flag.Parse()

    if err := run(); err != nil {
        log.Fatal(err)
    }
}

func run() error {
    type (
        cpuval struct {
            val []int
            err error
        }
    )
    var (
        interval = 1 * time.Second
        percpu   = args.perCpu
        cpuCh    = make(chan *cpuval)
        ctx, cxl = context.WithTimeout(context.Background(), 6*time.Second)
    )
    defer cxl()
    defer close(cpuCh)

    // 必要であれば無駄にCPUを回す
    if args.spinCpu {
        go spinCpu(ctx)
    }

    // CPU使用率を取得
    go func(ctx context.Context, ch chan<- *cpuval) {
        for {
            select {
            case <-ctx.Done():
                return
            default:
                v, err := cpu.PercentWithContext(ctx, interval, percpu)

                vals := make([]int, len(v))
                for i, f := range v {
                    vals[i] = int(f)
                }

                cpuCh <- &cpuval{vals, err}
            }
        }
    }(ctx, cpuCh)

    // 出力
    for v := range cpuCh {
        if v.err != nil {
            if errors.Is(v.err, context.DeadlineExceeded) {
                return nil
            }
            return v.err
        }

        log.Printf("%v\n", v.val)
    }

    return nil
}

func spinCpu(ctx context.Context) {
    for range runtime.NumCPU() {
        go func(ctx context.Context) {
            for {
                select {
                case <-ctx.Done():
                    return
                default:
                    for i := range 100000 {
                        _ = math.Sqrt(float64(i * i))
                    }
                    time.Sleep(1 * time.Microsecond)
                }
            }
        }(ctx)
    }
}

実行結果

$ task
task: [default] go build -o app .
task: [default] ./app
06:01:48 [4]
06:01:49 [6]
06:01:50 [8]
06:01:51 [6]
06:01:52 [10]
task: [default] ./app -percpu
06:01:54 [4 5]
06:01:55 [5 6]
06:01:56 [6 7]
06:01:57 [8 9]
06:01:58 [2 3]
task: [default] ./app -percpu -spincpu
06:02:00 [83 85]
06:02:01 [84 82]
06:02:02 [85 82]
06:02:03 [84 82]
06:02:04 [85 81]

本来の値は float64 で取得できますが、出力時に長いので int に丸めています。

参考情報

try-golang/examples/psutil/cpu/percent at main · devlights/try-golang · GitHub

Goのおすすめ書籍


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。




以上の内容はhttps://devlights.hatenablog.com/entry/2025/05/07/073000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14