Chương trình My Go cần biết phần trăm sử dụng CPU hiện tại của tất cả các quy trình của hệ thống và người dùng.Sử dụng CPU với golang
Làm cách nào để có được điều đó?
Chương trình My Go cần biết phần trăm sử dụng CPU hiện tại của tất cả các quy trình của hệ thống và người dùng.Sử dụng CPU với golang
Làm cách nào để có được điều đó?
Tôi gặp sự cố tương tự và không bao giờ tìm thấy triển khai nhẹ. Đây là một phiên bản rút gọn của giải pháp của tôi để trả lời câu hỏi cụ thể của bạn. Tôi lấy mẫu tệp /proc/stat
giống như tylerl đề xuất. Bạn sẽ nhận thấy rằng tôi đợi 3 giây giữa các mẫu để phù hợp với đầu ra của đầu, nhưng tôi cũng đã có kết quả tốt với 1 hoặc 2 giây. Tôi chạy mã tương tự trong một vòng lặp trong một thói quen đi, sau đó tôi truy cập vào việc sử dụng CPU khi tôi cần nó từ thói quen đi khác.
Bạn cũng có thể phân tích đầu ra của top -n1 | grep -i cpu
để sử dụng CPU, nhưng nó chỉ lấy mẫu trong nửa giây trên hộp linux của tôi và nó đã tắt trong khi tải nặng. đầu thường xuyên dường như để phù hợp rất chặt chẽ khi tôi đồng bộ nó và chương trình sau đây:
package main
import (
"fmt"
"io/ioutil"
"strconv"
"strings"
"time"
)
func getCPUSample() (idle, total uint64) {
contents, err := ioutil.ReadFile("/proc/stat")
if err != nil {
return
}
lines := strings.Split(string(contents), "\n")
for _, line := range(lines) {
fields := strings.Fields(line)
if fields[0] == "cpu" {
numFields := len(fields)
for i := 1; i < numFields; i++ {
val, err := strconv.ParseUint(fields[i], 10, 64)
if err != nil {
fmt.Println("Error: ", i, fields[i], err)
}
total += val // tally up all the numbers to get total ticks
if i == 4 { // idle is the 5th field in the cpu line
idle = val
}
}
return
}
}
return
}
func main() {
idle0, total0 := getCPUSample()
time.Sleep(3 * time.Second)
idle1, total1 := getCPUSample()
idleTicks := float64(idle1 - idle0)
totalTicks := float64(total1 - total0)
cpuUsage := 100 * (totalTicks - idleTicks)/totalTicks
fmt.Printf("CPU usage is %f%% [busy: %f, total: %f]\n", cpuUsage, totalTicks-idleTicks, totalTicks)
}
Nó có vẻ như tôi được phép liên kết đến việc thực hiện đầy đủ mà tôi đã viết trên bitbucket; nếu không, hãy xóa nó đi. Nó chỉ hoạt động trên linux cho đến nay, mặc dù: systemstat.go
Bạn có thể sử dụng gói os.exec
để thực hiện lệnh ps
và nhận kết quả.
Dưới đây là một chương trình ban hành lệnh ps aux
, phân tích kết quả và in sử dụng CPU của tất cả các quy trình trên Linux:
package main
import (
"bytes"
"log"
"os/exec"
"strconv"
"strings"
)
type Process struct {
pid int
cpu float64
}
func main() {
cmd := exec.Command("ps", "aux")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
processes := make([]*Process, 0)
for {
line, err := out.ReadString('\n')
if err!=nil {
break;
}
tokens := strings.Split(line, " ")
ft := make([]string, 0)
for _, t := range(tokens) {
if t!="" && t!="\t" {
ft = append(ft, t)
}
}
log.Println(len(ft), ft)
pid, err := strconv.Atoi(ft[1])
if err!=nil {
continue
}
cpu, err := strconv.ParseFloat(ft[2], 64)
if err!=nil {
log.Fatal(err)
}
processes = append(processes, &Process{pid, cpu})
}
for _, p := range(processes) {
log.Println("Process ", p.pid, " takes ", p.cpu, " % of the CPU")
}
}
Xin vui lòng, khi bạn downvote, dành thời gian để giải thích lý do tại sao ... –
Phân tích chuỗi từ một đầu ra lệnh không phải là một giải pháp tuyệt vời vì lệnh có thể thay đổi và nó cũng nặng trên cpu/mem/etc. –
@EricAnderson Bạn có nhận thấy câu trả lời được chấp nhận (viết hơn một năm sau khi tôi) trả lời không? Bạn đã chọn chỉ trả lời câu hỏi đầu tiên để cung cấp giải pháp cho câu hỏi? –
Cơ chế cho việc sử dụng CPU là hệ điều hành phụ thuộc, vì những con số có ý nghĩa hơi những thứ khác nhau cho các hạt nhân OS khác nhau.
Trên Linux, bạn có thể truy vấn hạt nhân để nhận thống kê mới nhất bằng cách đọc các tệp giả trong hệ thống tệp /proc/
. Chúng được tạo khi đang di chuyển khi bạn đọc chúng để phản ánh trạng thái hiện tại của máy.
Cụ thể, tệp /proc/<pid>/stat
cho mỗi quy trình chứa thông tin kế toán quy trình được liên kết. Nó được ghi lại trong proc(5). Bạn quan tâm cụ thể đến các trường utime
, stime
, cutime
và cstime
(bắt đầu từ trường thứ 14).
Bạn có thể tính tỷ lệ phần trăm dễ dàng đủ: chỉ cần đọc các số, chờ một khoảng thời gian và đọc lại. Lấy sự khác biệt, chia cho khoảng thời gian bạn chờ đợi và mức trung bình của bạn. Đây chính là điều mà chương trình top
thực hiện (cũng như tất cả các chương trình khác thực hiện cùng một dịch vụ). Ghi nhớ rằng bạn có thể có hơn 100% sử dụng CPU nếu bạn có nhiều hơn 1 CPU.
Nếu bạn chỉ muốn một bản tóm tắt toàn hệ thống, báo cáo được ghi trong /proc/stat
- tính mức trung bình của bạn bằng cùng một kỹ thuật, nhưng bạn chỉ phải đọc một tệp.
Kiểm tra gói này http://github.com/c9s/goprocinfo, gói goprocinfo thực hiện công cụ phân tích cú pháp cho bạn.
stat, err := linuxproc.ReadStat("/proc/stat")
if err != nil {
t.Fatal("stat read fail")
}
for _, s := range stat.CPUStats {
// s.User
// s.Nice
// s.System
// s.Idle
// s.IOWait
}
Thư viện tuyệt vời, cảm ơn. Nó làm nhiều hơn thế! – lzap
Dưới đây là một giải pháp độc lập hệ điều hành sử dụng Cgo để khai thác clock() chức năng được cung cấp bởi C standard library:
//#include <time.h>
import "C"
import "time"
var startTime = time.Now()
var startTicks = C.clock()
func CpuUsagePercent() float64 {
clockSeconds := float64(C.clock()-startTicks)/float64(C.CLOCKS_PER_SEC)
realSeconds := time.Since(startTime).Seconds()
return clockSeconds/realSeconds * 100
}
Bạn có thể đơn giản hóa 'time.Now(). Sub (startTime)' thành 'time.Since (startTime)'. –
Cảm ơn đề xuất, ví dụ được cập nhật. –
Sidenote: 'clock()' chỉ cho thời gian của quá trình xử lý hiện tại. –
Gần đây tôi đã thực hiện đo đạc sử dụng CPU từ Raspberry Pi (Raspbian OS) và sử dụng github.com/c9s/goprocinfo kết hợp với những gì được đề xuất ở đây:
ý tưởng này xuất phát từ các mã htop
nguồn và là phải có hai phép đo (trước/hiện tại) để tính toán việc sử dụng CPU:
func calcSingleCoreUsage(curr, prev linuxproc.CPUStat) float32 {
PrevIdle := prev.Idle + prev.IOWait
Idle := curr.Idle + curr.IOWait
PrevNonIdle := prev.User + prev.Nice + prev.System + prev.IRQ + prev.SoftIRQ + prev.Steal
NonIdle := curr.User + curr.Nice + curr.System + curr.IRQ + curr.SoftIRQ + curr.Steal
PrevTotal := PrevIdle + PrevNonIdle
Total := Idle + NonIdle
// fmt.Println(PrevIdle, Idle, PrevNonIdle, NonIdle, PrevTotal, Total)
// differentiate: actual value minus the previous one
totald := Total - PrevTotal
idled := Idle - PrevIdle
CPU_Percentage := (float32(totald) - float32(idled))/float32(totald)
return CPU_Percentage
}
Để biết thêm bạn cũng có thể kiểm tra https://github.com/tgogos/rpi_cpu_memory
mà ngôn ngữ và hệ điều hành bạn sử dụng? –
Tôi sử dụng Go (từ golang.org) trong Linux, nhưng tôi muốn sử dụng thứ gì đó di động cho * nix khác nếu có thể. –