【发布时间】:2018-06-18 21:44:14
【问题描述】:
我知道[1]。通过几行代码,我只想从CPU使用率最高的前n个进程中提取当前的CPU使用率。 top 的前 5 行或多或少。使用 github.com/shirou/gopsutil/process 这很简单:
// file: gotop.go
package main
import (
"log"
"time"
"sort"
"github.com/shirou/gopsutil/process"
)
type ProcInfo struct{
Name string
Usage float64
}
type ByUsage []ProcInfo
func (a ByUsage) Len() int { return len(a) }
func (a ByUsage) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByUsage) Less(i, j int) bool {
return a[i].Usage > a[j].Usage
}
func main() {
for {
processes, _ := process.Processes()
var procinfos []ProcInfo
for _, p := range processes{
a, _ := p.CPUPercent()
n, _ := p.Name()
procinfos = append(procinfos, ProcInfo{n, a})
}
sort.Sort(ByUsage(procinfos))
for _, p := range procinfos[:5]{
log.Printf(" %s -> %f", p.Name, p.Usage)
}
time.Sleep(3 * time.Second)
}
}
虽然此实现中的刷新率 gotop 像 top 一样是 3 秒,但 gotop 大约有 3 秒。像 top 那样获得这些值对 CPU 使用率的要求要高 5 倍。有什么技巧可以更有效地读取 5 个最消耗量的进程吗?我还试图找到 top 的实现,看看那里是如何实现的。
psutils 是造成这种减速的原因吗?我发现在 GO 中也实现了 cpustat。但即使是sudo ./cpustat -i 3000 -s 1 似乎也没有top 高效。
主要动机是通过相当少量的计算工作来监控当前机器的使用情况,以便它可以在后台作为服务运行。
看来,连htop都是only reading/proc/stat。
编辑 正如 cmets 中提出的,这里是分析时的结果
Showing top 10 nodes out of 46 (cum >= 70ms)
flat flat% sum% cum cum%
40ms 40.00% 40.00% 40ms 40.00% syscall.Syscall
10ms 10.00% 50.00% 30ms 30.00% github.com/shirou/gopsutil/process.(*Process).fillFromStatusWithContext
10ms 10.00% 60.00% 30ms 30.00% io/ioutil.ReadFile
10ms 10.00% 70.00% 10ms 10.00% runtime.slicebytetostring
10ms 10.00% 80.00% 20ms 20.00% strings.FieldsFunc
10ms 10.00% 90.00% 10ms 10.00% syscall.Syscall6
10ms 10.00% 100% 10ms 10.00% unicode.IsSpace
0 0% 100% 10ms 10.00% bytes.(*Buffer).ReadFrom
0 0% 100% 70ms 70.00% github.com/shirou/gopsutil/process.(*Process).CPUPercent
0 0% 100% 70ms 70.00% github.com/shirou/gopsutil/process.(*Process).CPUPercentWithContext
似乎系统调用需要很长时间。一个树转储在这里: https://gist.github.com/PatWie/4fa528b7d7b1d0b5c1b665c056671477
这会将问题更改为:
- 系统调用是问题吗?
- top 程序是否有任何 c 源代码?我刚刚找到了htop的实现
- 有简单的解决方法吗?我考虑用 c 写它,然后把它包装起来。
【问题讨论】:
-
请对其进行分析,以便我们确定哪个部分是瓶颈。
-
只是一个想法:
top是一个古老的(阅读:一遍又一遍地优化,即使完全重写,iirc)并用 C 编写(没有 GC 等)。与编程语言一样:Go 对 一些 事物非常有用,而不是对所有事物。 -
我添加了分析的结果。我的结论正确吗?另外,我没有找到
top的实现。 -
看来,golang 确实非常低效,或者至少是库
github.com/shirou/gopsutil/process对于我的用例。我最终直接在 c 中实现它并通过 cgo 调用它,请参阅github.com/PatWie/cpuinfo