From b42d098a991f62d87af698177241568cb0707f8f Mon Sep 17 00:00:00 2001 From: Caleb Bassi Date: Tue, 15 May 2018 11:10:30 -0700 Subject: [PATCH] Switch to custom process info retrieval * Switch from gopsutil to using 'ps' for process info retrieval. * Much faster now since we are getting all info in a batch. * Should hopefully fix the issue on OSX where process info retrieval was taking too long. * CPU percentage reporting should also be imporoved, since it is more realtime. --- src/psutil/process.go | 37 +++++++++++++++++++++++++++++ src/widgets/proc.go | 54 +++++++++++++++---------------------------- 2 files changed, 55 insertions(+), 36 deletions(-) create mode 100644 src/psutil/process.go diff --git a/src/psutil/process.go b/src/psutil/process.go new file mode 100644 index 00000000..fcb683e6 --- /dev/null +++ b/src/psutil/process.go @@ -0,0 +1,37 @@ +package psutil + +import ( + // "fmt" + "os/exec" + "strconv" + "strings" +) + +// Process represents each process. +type Process struct { + PID int + Command string + CPU float64 + Mem float64 +} + +func Processes() []Process { + output, _ := exec.Command("ps", "-acxo", "pid,comm,pcpu,pmem").Output() + strOutput := strings.TrimSpace(string(output)) + processes := []Process{} + for _, line := range strings.Split(strOutput, "\n")[1:] { + split := strings.Fields(line) + // fmt.Println(split) + pid, _ := strconv.Atoi(split[0]) + cpu, _ := strconv.ParseFloat(split[2], 64) + mem, _ := strconv.ParseFloat(split[3], 64) + process := Process{ + PID: pid, + Command: split[1], + CPU: cpu, + Mem: mem, + } + processes = append(processes, process) + } + return processes +} diff --git a/src/widgets/proc.go b/src/widgets/proc.go index ca252753..001f41ab 100644 --- a/src/widgets/proc.go +++ b/src/widgets/proc.go @@ -7,9 +7,9 @@ import ( "strconv" "time" + "github.com/cjbassi/gotop/src/psutil" ui "github.com/cjbassi/termui" psCPU "github.com/shirou/gopsutil/cpu" - psProc "github.com/shirou/gopsutil/process" ) const ( @@ -17,21 +17,13 @@ const ( DOWN = "▼" ) -// Process represents each process. -type Process struct { - PID int32 - Command string - CPU float64 - Mem float32 -} - type Proc struct { *ui.Table - cpuCount int + cpuCount float64 interval time.Duration sortMethod string - groupedProcs []Process - ungroupedProcs []Process + groupedProcs []psutil.Process + ungroupedProcs []psutil.Process group bool KeyPressed chan bool DefaultColWidths []int @@ -42,7 +34,7 @@ func NewProc(keyPressed chan bool) *Proc { self := &Proc{ Table: ui.NewTable(), interval: time.Second, - cpuCount: cpuCount, + cpuCount: float64(cpuCount), sortMethod: "c", group: true, KeyPressed: keyPressed, @@ -72,21 +64,11 @@ func NewProc(keyPressed chan bool) *Proc { } func (self *Proc) update() { - psProcesses, _ := psProc.Processes() - processes := make([]Process, len(psProcesses)) - for i, psProcess := range psProcesses { - pid := psProcess.Pid - command, _ := psProcess.Name() - cpu, _ := psProcess.CPUPercent() - mem, _ := psProcess.MemoryPercent() - - processes[i] = Process{ - pid, - command, - cpu / float64(self.cpuCount), - mem, - } + processes := psutil.Processes() + for _, process := range processes { + process.CPU /= self.cpuCount } + self.ungroupedProcs = processes self.groupedProcs = Group(processes) @@ -233,19 +215,19 @@ func (self *Proc) keyBinds() { // Group groupes a []Process based on command name. // The first field changes from PID to count. // CPU and Mem are added together for each Process. -func Group(P []Process) []Process { - groupedP := make(map[string]Process) +func Group(P []psutil.Process) []psutil.Process { + groupedP := make(map[string]psutil.Process) for _, process := range P { val, ok := groupedP[process.Command] if ok { - groupedP[process.Command] = Process{ + groupedP[process.Command] = psutil.Process{ val.PID + 1, val.Command, val.CPU + process.CPU, val.Mem + process.Mem, } } else { - groupedP[process.Command] = Process{ + groupedP[process.Command] = psutil.Process{ 1, process.Command, process.CPU, @@ -254,7 +236,7 @@ func Group(P []Process) []Process { } } - groupList := make([]Process, len(groupedP)) + groupList := make([]psutil.Process, len(groupedP)) var i int for _, val := range groupedP { groupList[i] = val @@ -265,7 +247,7 @@ func Group(P []Process) []Process { } // FieldsToStrings converts a []Process to a [][]string -func FieldsToStrings(P []Process) [][]string { +func FieldsToStrings(P []psutil.Process) [][]string { strings := make([][]string, len(P)) for i, p := range P { strings[i] = make([]string, 4) @@ -292,7 +274,7 @@ func (self *Proc) Kill() { // []Process Sorting // ///////////////////////////////////////////////////////////////////////////////// -type ProcessByCPU []Process +type ProcessByCPU []psutil.Process // Len implements Sort interface func (P ProcessByCPU) Len() int { @@ -309,7 +291,7 @@ func (P ProcessByCPU) Less(i, j int) bool { return P[i].CPU < P[j].CPU } -type ProcessByPID []Process +type ProcessByPID []psutil.Process // Len implements Sort interface func (P ProcessByPID) Len() int { @@ -326,7 +308,7 @@ func (P ProcessByPID) Less(i, j int) bool { return P[i].PID < P[j].PID } -type ProcessByMem []Process +type ProcessByMem []psutil.Process // Len implements Sort interface func (P ProcessByMem) Len() int {