Commit 63d7bbfc authored by liming6's avatar liming6
Browse files

feature 添加展示进程信息功能

parent 9608d37d
package backend package backend
import ( import (
"get-container/docker"
"get-container/gpu" "get-container/gpu"
"get-container/utils"
"maps"
"os"
"strconv"
"sync" "sync"
"time"
"github.com/shirou/gopsutil/v4/process"
) )
/* /*
...@@ -10,9 +18,30 @@ import ( ...@@ -10,9 +18,30 @@ import (
*/ */
var ( var (
MapIdDCU = sync.Map{} // 记录dcu信息 MapIdDCU = sync.Map{} // 记录dcu信息
DockerPidInfo *DockerProcessMap = nil
User = ""
HostName = ""
) )
func init() {
i, err := docker.ContainerInfo.GetProcessIdInDocker(false)
if err != nil || i == nil {
DockerPidInfo = &DockerProcessMap{lock: sync.RWMutex{}, pids: make(map[int32]bool)}
return
}
DockerPidInfo = &DockerProcessMap{lock: sync.RWMutex{}, pids: maps.Clone(i)}
HostName, _ = os.Hostname()
uid := os.Getuid()
u, err := utils.GetSysUserById(uid)
if err == nil && u != nil {
User = u.Name
} else {
User = strconv.Itoa(uid)
}
}
type DCUInfo struct { type DCUInfo struct {
Id int Id int
Name string // full Name string // full
...@@ -167,3 +196,108 @@ func GetDCUInfo() map[int]DCUInfo { ...@@ -167,3 +196,108 @@ func GetDCUInfo() map[int]DCUInfo {
}) })
return result return result
} }
type DockerProcessMap struct {
lock sync.RWMutex
pids map[int32]bool
}
func (dpm *DockerProcessMap) GetPidInfo() map[int32]bool {
rl := dpm.lock.RLocker()
rl.Lock()
defer rl.Unlock()
return maps.Clone(dpm.pids)
}
// Update 重新获取数据,这是一个耗时的操作
func (dpm *DockerProcessMap) Update() map[int32]bool {
i, err := docker.ContainerInfo.GetProcessIdInDocker(true)
if err != nil || i == nil {
dpm.pids = make(map[int32]bool)
return make(map[int32]bool)
}
dpm.pids = maps.Clone(i)
return maps.Clone(i)
}
type DCUProcessInfo struct {
DCU int // 使用的dcu号
DCUMem string // 使用的dcu内存容量
SDMA int
Info ProcessInfo // 通用进程信息
}
type ProcessInfo struct {
Pid int32 // 进程号
User string // 用户名或uid
CPU float64 // CPU使用率
Mem float32 // 内存使用率
Time string // 占用的CPU时间
Cmd string // 命令
InDocker bool // 是否在docker容器里
}
func getProcessInfo(pids []int32) map[int32]ProcessInfo {
result := make(map[int32]ProcessInfo)
if len(pids) == 0 {
return result
}
dockerPids := DockerPidInfo.GetPidInfo()
for _, pid := range pids {
p, err := process.NewProcess(int32(pid))
if err != nil {
continue
}
item := ProcessInfo{Pid: p.Pid}
item.User, _ = p.Username()
item.CPU, _ = p.CPUPercent()
item.Mem, _ = p.MemoryPercent()
t, err := p.Times()
if err == nil {
item.Time = (time.Duration((t.System+t.User)*1000.0) * time.Millisecond).String()
}
item.Cmd, _ = p.Cmdline()
a, b := dockerPids[item.Pid]
item.InDocker = a && b
result[p.Pid] = item
}
return result
}
// GetDCUProcessInfo 返回值的key为dcu index
func GetDCUProcessInfo() map[int][]DCUProcessInfo {
result := make(map[int][]DCUProcessInfo)
info, err := gpu.GetDCUPidInfo()
if err != nil {
return result
}
pids := make([]int32, 0)
for _, v := range info {
pids = append(pids, v.Pid)
}
pinfo := getProcessInfo(pids)
for _, v := range info {
index := make([]int, 0)
for _, i := range v.HCUIndex {
ii, err := strconv.Atoi(i)
if err != nil {
continue
}
index = append(index, ii)
}
for _, i := range index {
l, have := result[i]
if !have {
result[i] = make([]DCUProcessInfo, 0)
l = result[i]
}
item := DCUProcessInfo{DCU: i}
item.Info = pinfo[v.Pid]
item.DCUMem = v.VRamUsed.HumanReadStr(1)
item.SDMA = v.SDMAUsed
l = append(l, item)
result[i] = l
}
}
return result
}
...@@ -16,13 +16,13 @@ const ( ...@@ -16,13 +16,13 @@ const (
// ModelMsg 模型信息,在父组件和各个子组件间共享信息 // ModelMsg 模型信息,在父组件和各个子组件间共享信息
type ModelMsg struct { type ModelMsg struct {
t time.Time // 当前时间 t time.Time // 当前时间
index uint64 // update次数 index uint64 // update次数
Version *gpu.HYVersionInfo // gpu版本相关信息 Version *gpu.HYVersionInfo // gpu版本相关信息
MyVersion string MyVersion string
DCUInfo map[int]backend.DCUInfo // DCU全量信息 DCUInfo map[int]backend.DCUInfo // DCU全量信息
// DCUPidInfo []gpu.DCUPidInfo // 使用dcu的进程信息 DCUPidInfo map[int][]backend.DCUProcessInfo // 使用dcu的进程信息
systemInfo *utils.SysInfo // 系统信息 systemInfo *utils.SysInfo // 系统信息
} }
type TickMsg time.Time type TickMsg time.Time
...@@ -33,9 +33,9 @@ type ModelMain struct { ...@@ -33,9 +33,9 @@ type ModelMain struct {
Header *ModelHeader Header *ModelHeader
DCUInfo *ModelDCUInfo DCUInfo *ModelDCUInfo
SysLoad *ModelSysLoad SysLoad *ModelSysLoad
// ProcessInfo *ModelProcess ProcessInfo *ModelProcessInfo
index uint64 // 记录update次数的值 index uint64 // 记录update次数的值
modelMsg *ModelMsg // 记录模型信息 modelMsg *ModelMsg // 记录模型信息
} }
func NewModelMain(width, height int) ModelMain { func NewModelMain(width, height int) ModelMain {
...@@ -45,6 +45,7 @@ func NewModelMain(width, height int) ModelMain { ...@@ -45,6 +45,7 @@ func NewModelMain(width, height int) ModelMain {
result.Header = &ModelHeader{} result.Header = &ModelHeader{}
result.DCUInfo = &ModelDCUInfo{width: width, height: height, info: make(map[int]backend.DCUInfo)} result.DCUInfo = &ModelDCUInfo{width: width, height: height, info: make(map[int]backend.DCUInfo)}
result.SysLoad = NewModelSysLoad(width) result.SysLoad = NewModelSysLoad(width)
result.ProcessInfo = NewModelProcessInfo(width)
return result return result
} }
...@@ -78,7 +79,9 @@ func (m *ModelMain) Init() tea.Cmd { ...@@ -78,7 +79,9 @@ func (m *ModelMain) Init() tea.Cmd {
if c := m.SysLoad.Init(); c != nil { if c := m.SysLoad.Init(); c != nil {
cmds = append(cmds, c) cmds = append(cmds, c)
} }
if c := m.ProcessInfo.Init(); c != nil {
cmds = append(cmds, c)
}
m.modelMsg = &modelMsg m.modelMsg = &modelMsg
// 将调用初始化方法 // 将调用初始化方法
cmds = append(cmds, tickCmd(), sendMsgCmd(&modelMsg)) cmds = append(cmds, tickCmd(), sendMsgCmd(&modelMsg))
...@@ -98,24 +101,28 @@ func (m *ModelMain) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) { ...@@ -98,24 +101,28 @@ func (m *ModelMain) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) {
header, _ := m.Header.Update(m.modelMsg) header, _ := m.Header.Update(m.modelMsg)
dcuInfo, _ := m.DCUInfo.Update(m.modelMsg) dcuInfo, _ := m.DCUInfo.Update(m.modelMsg)
sysLoad, _ := m.SysLoad.Update(m.modelMsg) sysLoad, _ := m.SysLoad.Update(m.modelMsg)
pidinfo, _ := m.ProcessInfo.Update(m.modelMsg)
m.Header = header.(*ModelHeader) m.Header = header.(*ModelHeader)
m.DCUInfo = dcuInfo.(*ModelDCUInfo) m.DCUInfo = dcuInfo.(*ModelDCUInfo)
m.SysLoad = sysLoad.(*ModelSysLoad) m.SysLoad = sysLoad.(*ModelSysLoad)
m.ProcessInfo = pidinfo.(*ModelProcessInfo)
return m, tickCmd() return m, tickCmd()
case ModelMsg: // 初始化 case ModelMsg: // 初始化
header, _ := m.Header.Update(m.modelMsg) header, _ := m.Header.Update(m.modelMsg)
dcuInfo, _ := m.DCUInfo.Update(m.modelMsg) dcuInfo, _ := m.DCUInfo.Update(m.modelMsg)
sysLoad, _ := m.SysLoad.Update(m.modelMsg) sysLoad, _ := m.SysLoad.Update(m.modelMsg)
pidinfo, _ := m.ProcessInfo.Update(m.modelMsg)
m.Header = header.(*ModelHeader) m.Header = header.(*ModelHeader)
m.DCUInfo = dcuInfo.(*ModelDCUInfo) m.DCUInfo = dcuInfo.(*ModelDCUInfo)
m.SysLoad = sysLoad.(*ModelSysLoad) m.SysLoad = sysLoad.(*ModelSysLoad)
m.ProcessInfo = pidinfo.(*ModelProcessInfo)
return m, nil return m, nil
} }
return m, nil return m, nil
} }
func (m *ModelMain) View() string { func (m *ModelMain) View() string {
return m.Header.View() + m.DCUInfo.View() + m.SysLoad.View() + "\n" return m.Header.View() + m.DCUInfo.View() + m.SysLoad.View() + m.ProcessInfo.Header + m.ProcessInfo.View() + "\n"
} }
var myBorder = lipgloss.Border{ var myBorder = lipgloss.Border{
...@@ -150,6 +157,7 @@ func initModelInfo(model *ModelMsg) error { ...@@ -150,6 +157,7 @@ func initModelInfo(model *ModelMsg) error {
} }
model.DCUInfo = backend.GetDCUInfo() model.DCUInfo = backend.GetDCUInfo()
model.systemInfo, err = utils.GetSysInfo() model.systemInfo, err = utils.GetSysInfo()
model.DCUPidInfo = backend.GetDCUProcessInfo()
return err return err
} }
...@@ -164,4 +172,5 @@ func updateModelInfo(modelMsg *ModelMsg, index uint64, t time.Time) { ...@@ -164,4 +172,5 @@ func updateModelInfo(modelMsg *ModelMsg, index uint64, t time.Time) {
} }
modelMsg.DCUInfo = backend.GetDCUInfo() modelMsg.DCUInfo = backend.GetDCUInfo()
modelMsg.systemInfo, _ = utils.GetSysInfo() modelMsg.systemInfo, _ = utils.GetSysInfo()
modelMsg.DCUPidInfo = backend.GetDCUProcessInfo()
} }
package tui
import (
"fmt"
"get-container/cmd/dcutop/backend"
"maps"
"strings"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
type ModelProcessInfo struct {
Header string
Title string
DoubleMiddleLine string
MiddleLine string
BottomLine string
NoProceseLine string // 没有进程时显示的行
Cache map[int][]backend.DCUProcessInfo
width int
style lipgloss.Style
}
const (
Processes = " Processes:"
ModelProcessInfoTitle = " DCU PID USER DCU-MEM SDMA %CPU %MEM TIME Command"
ModelProcessInfoNoPro = " No running processes found"
)
func NewModelProcessInfo(width int) *ModelProcessInfo {
result := ModelProcessInfo{width: width, Cache: make(map[int][]backend.DCUProcessInfo), style: lipgloss.NewStyle()}
return &result
}
func (m *ModelProcessInfo) Init() tea.Cmd {
sb := strings.Builder{}
sb.WriteString(myBorder.Left)
sb.WriteString(Processes)
uah := fmt.Sprintf("%s@%s ", m.style.Foreground(lipgloss.Color("#edff2cff")).SetString(backend.User).String(),
m.style.Foreground(lipgloss.Color("#a3ff2bff")).SetString(backend.HostName).String())
space := strings.Repeat(" ", m.width-lipgloss.Width(Processes)-lipgloss.Width(uah)-2)
sb.WriteString(space)
sb.WriteString(uah)
sb.WriteString(myBorder.Right)
sb.WriteByte('\n')
m.Header = sb.String()
sb.Reset()
sb.WriteString(myBorder.Left)
sb.WriteString(ModelProcessInfoTitle)
sb.WriteString(strings.Repeat(" ", m.width-2-lipgloss.Width(ModelProcessInfoTitle)))
sb.WriteString(myBorder.Right)
sb.WriteByte('\n')
m.Title = sb.String()
m.DoubleMiddleLine = "╞" + strings.Repeat("═", m.width-2) + "╡\n"
m.MiddleLine = myBorder.MiddleLeft + strings.Repeat("─", m.width-2) + myBorder.MiddleRight + "\n"
m.BottomLine = myBorder.BottomLeft + strings.Repeat("═", m.width-2) + myBorder.BottomRight
m.NoProceseLine = myBorder.Left + ModelProcessInfoNoPro + strings.Repeat(" ", m.width-2-lipgloss.Width(ModelProcessInfoNoPro)) + myBorder.Right + "\n"
return nil
}
func (m *ModelProcessInfo) View() string {
haveProcess := false
lines := make([]string, 0)
sb := strings.Builder{}
for index := range 64 {
processes, have := m.Cache[index]
if !have {
continue
}
for _, process := range processes {
haveProcess = true
sb.WriteString(myBorder.Left)
sb.WriteString(FormatStr(fmt.Sprintf("%d", process.DCU), 4, lipgloss.Right))
sb.WriteByte(' ')
sb.WriteString(FormatStr(fmt.Sprintf("%d", process.Info.Pid), 6, lipgloss.Right))
sb.WriteByte(' ')
sb.WriteString(FormatStr(process.Info.User, 9, lipgloss.Right))
sb.WriteByte(' ')
sb.WriteString(FormatStr(process.DCUMem, 8, lipgloss.Right))
sb.WriteByte(' ')
sb.WriteString(FormatStr(fmt.Sprintf("%d", process.SDMA), 4, lipgloss.Right))
sb.WriteByte(' ')
sb.WriteString(FormatStr(fmt.Sprintf("%.1f", process.Info.CPU), 5, lipgloss.Right))
sb.WriteByte(' ')
sb.WriteString(FormatStr(fmt.Sprintf("%.1f", process.Info.Mem), 5, lipgloss.Right))
sb.WriteByte(' ')
sb.WriteString(FormatStr(process.Info.Time, 9, lipgloss.Right))
sb.WriteString(" ")
w := m.width - lipgloss.Width(sb.String()) - 2
tw := lipgloss.Width(process.Info.Cmd)
if w >= tw {
sb.WriteString(process.Info.Cmd)
sb.WriteString(strings.Repeat(" ", w-tw))
} else {
sb.WriteString(FormatStr(process.Info.Cmd, w-2, lipgloss.Left))
sb.WriteString("..")
}
sb.WriteByte(' ')
sb.WriteString(myBorder.Right)
sb.WriteByte('\n')
lines = append(lines, sb.String())
sb.Reset()
}
lines = append(lines, m.MiddleLine)
}
if !haveProcess {
return m.Title + m.DoubleMiddleLine + m.NoProceseLine + m.BottomLine
}
sb.WriteString(m.Title)
sb.WriteString(m.DoubleMiddleLine)
for _, v := range lines[:len(lines)-1] {
sb.WriteString(v)
}
sb.WriteString(m.BottomLine)
return sb.String()
}
func (m *ModelProcessInfo) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := inputMsg.(type) {
case *ModelMsg:
clear(m.Cache)
maps.Copy(m.Cache, msg.DCUPidInfo)
}
return m, nil
}
...@@ -128,7 +128,7 @@ func (m *ModelSysLoad) View() string { ...@@ -128,7 +128,7 @@ func (m *ModelSysLoad) View() string {
memUsed := utils.MemorySize{Num: m.current.MemUsed, Unit: utils.Byte} memUsed := utils.MemorySize{Num: m.current.MemUsed, Unit: utils.Byte}
load := fmt.Sprintf(" Load Average: %.2f %.2f %.2f", m.current.Load1, m.current.Load5, m.current.Load15) load := fmt.Sprintf(" Load Average: %.2f %.2f %.2f", m.current.Load1, m.current.Load5, m.current.Load15)
mem := fmt.Sprintf(" MEM: %s (%.1f%%)", memUsed.HumanReadStr(), m.current.MemUsedPercent) mem := fmt.Sprintf(" MEM: %s (%.1f%%)", memUsed.HumanReadStr(1), m.current.MemUsedPercent)
dcuMem := fmt.Sprintf(" AVG DCU MEM: %.1f%%", m.current.DCUMemUsageAvg) dcuMem := fmt.Sprintf(" AVG DCU MEM: %.1f%%", m.current.DCUMemUsageAvg)
dcu := fmt.Sprintf(" AVG DCU UTL: %.1f%%", m.current.DCUUsageAvg) dcu := fmt.Sprintf(" AVG DCU UTL: %.1f%%", m.current.DCUUsageAvg)
......
...@@ -3,11 +3,11 @@ package tui ...@@ -3,11 +3,11 @@ package tui
import ( import (
"fmt" "fmt"
"get-container/cmd/dcutop/tchart" "get-container/cmd/dcutop/tchart"
"strings"
"testing" "testing"
"time" "time"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
"github.com/emirpasic/gods/v2/maps/linkedhashmap"
"github.com/emirpasic/gods/v2/trees/binaryheap" "github.com/emirpasic/gods/v2/trees/binaryheap"
) )
...@@ -97,19 +97,11 @@ func TestBinaryHeap(t *testing.T) { ...@@ -97,19 +97,11 @@ func TestBinaryHeap(t *testing.T) {
} }
} }
func TestLinkedHashMap(t *testing.T) { func TestNewModelProcessInfo(t *testing.T) {
m := linkedhashmap.New[time.Time, int]() m := NewModelProcessInfo(130)
now := time.Now() t.Logf("\n%s", m.Header)
for i := range 5 { for l := range strings.SplitSeq(m.Header, "\n") {
m.Put(now.Add(time.Duration(i)*time.Second), 5-i) t.Log(lipgloss.Width(l))
}
mi := m.Iterator()
for {
if mi.Next() {
t.Logf("%v: %d", mi.Key(), mi.Value())
} else {
break
}
} }
t.Log(m.Size()) t.Logf("\n%s", m.View())
} }
...@@ -7,13 +7,14 @@ import ( ...@@ -7,13 +7,14 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/client"
"os" "os"
"regexp" "regexp"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/client"
) )
/** /**
...@@ -45,66 +46,64 @@ type ContainersInfo struct { ...@@ -45,66 +46,64 @@ type ContainersInfo struct {
} }
type ContainerPsInfo struct { type ContainerPsInfo struct {
Pid uint64 Pid int32
Ppid uint64 Ppid uint64
Uid string Uid string
Cmd []string Cmd string
} }
func ParsePsInfo(topInfo map[string]container.TopResponse) (map[string]ContainerPsInfo, error) { func ParsePsInfo(topInfo map[string]container.TopResponse) (map[string][]ContainerPsInfo, error) {
if topInfo == nil { if topInfo == nil {
return nil, errors.New("topInfo is nil") return nil, errors.New("topInfo is nil")
} }
result := make(map[string]ContainerPsInfo) result := make(map[string][]ContainerPsInfo)
indexMap, t := make(map[string]int), 0
for cid, topResp := range topInfo { for cid, topResp := range topInfo {
indexMap, t := make(map[string]int), 0
result[cid] = make([]ContainerPsInfo, 0)
for index, key := range topResp.Titles { for index, key := range topResp.Titles {
switch strings.TrimSpace(strings.ToLower(key)) { switch strings.TrimSpace(strings.ToLower(key)) {
case "pid": case "pid":
indexMap[key] = index indexMap["pid"] = index
t++ t++
break
case "ppid": case "ppid":
indexMap[key] = index indexMap["ppid"] = index
t++ t++
break
case "uid": case "uid":
indexMap[key] = index indexMap["uid"] = index
t++ t++
break
case "cmd": case "cmd":
indexMap[key] = index indexMap["cmd"] = index
t++ t++
break
default: default:
break
} }
if t >= 4 { if t >= 4 {
break break
} }
} }
item := ContainerPsInfo{} for _, fields := range topResp.Processes {
if v, ok := indexMap["pid"]; ok { item := ContainerPsInfo{}
pid, err := strconv.ParseUint(topResp.Processes[v][0], 10, 64) if v, ok := indexMap["pid"]; ok {
if err != nil { pid, err := strconv.ParseUint(fields[v], 10, 64)
return nil, err if err != nil {
return nil, err
}
item.Pid = int32(pid)
} }
item.Pid = pid if v, ok := indexMap["ppid"]; ok {
} ppid, err := strconv.ParseUint(fields[v], 10, 64)
if v, ok := indexMap["ppid"]; ok { if err != nil {
ppid, err := strconv.ParseUint(topResp.Processes[v][0], 10, 64) return nil, err
if err != nil { }
return nil, err item.Ppid = ppid
} }
item.Ppid = ppid if v, ok := indexMap["uid"]; ok {
} item.Uid = fields[v]
if v, ok := indexMap["uid"]; ok { }
item.Uid = topResp.Processes[v][0] if v, ok := indexMap["cmd"]; ok {
} item.Cmd = fields[v]
if v, ok := indexMap["cmd"]; ok { }
item.Cmd = topResp.Processes[v] result[cid] = append(result[cid], item)
} }
result[cid] = item
} }
return result, nil return result, nil
} }
...@@ -148,6 +147,31 @@ func initContainerInfo() error { ...@@ -148,6 +147,31 @@ func initContainerInfo() error {
return nil return nil
} }
// GetProcessIdInDocker 获取所用容器的进程信息
func (info *ContainersInfo) GetProcessIdInDocker(update bool) (map[int32]bool, error) {
result := make(map[int32]bool)
if update {
err := info.Update()
if err != nil {
return result, err
}
}
rl := info.lock.RLocker()
rl.Lock()
i, err := ParsePsInfo(info.topInfo)
rl.Unlock()
rl = nil
if err != nil {
return result, err
}
for _, v := range i {
for _, k := range v {
result[k.Pid] = true
}
}
return result, nil
}
// FindContainerIdByPid 根据pid获取该进程属于哪个docker容器,返回容器id,如果为nil,表示找不到容器id // FindContainerIdByPid 根据pid获取该进程属于哪个docker容器,返回容器id,如果为nil,表示找不到容器id
func FindContainerIdByPid(pid uint64, method FindCIDMethod) (*string, error) { func FindContainerIdByPid(pid uint64, method FindCIDMethod) (*string, error) {
switch method { switch method {
...@@ -161,7 +185,7 @@ func FindContainerIdByPid(pid uint64, method FindCIDMethod) (*string, error) { ...@@ -161,7 +185,7 @@ func FindContainerIdByPid(pid uint64, method FindCIDMethod) (*string, error) {
} }
func FindContainerIdByPidBatch(pids []uint64, method FindCIDMethod) (map[uint64]string, error) { func FindContainerIdByPidBatch(pids []uint64, method FindCIDMethod) (map[uint64]string, error) {
if pids == nil || len(pids) == 0 { if len(pids) == 0 {
return nil, nil return nil, nil
} }
switch method { switch method {
......
...@@ -2,9 +2,11 @@ package docker ...@@ -2,9 +2,11 @@ package docker
import ( import (
"context" "context"
"github.com/moby/moby/client"
"strings" "strings"
"testing" "testing"
"time"
"github.com/moby/moby/client"
) )
func TestRegexp(t *testing.T) { func TestRegexp(t *testing.T) {
...@@ -86,3 +88,23 @@ func TestDocker(t *testing.T) { ...@@ -86,3 +88,23 @@ func TestDocker(t *testing.T) {
} }
} }
func TestGetProcessIdInDocker(t *testing.T) {
// now := time.Now()
// pids, err := ContainerInfo.GetProcessIdInDocker(true)
// d := time.Since(now)
// if err != nil {
// t.Error(err)
// }
// t.Logf("%v", d.Seconds())
// t.Logf("%+v", pids)
now := time.Now()
pids, err := ContainerInfo.GetProcessIdInDocker(false)
d := time.Since(now)
if err != nil {
t.Error(err)
}
t.Logf("%d", d.Nanoseconds())
t.Logf("%+v", pids)
}
...@@ -450,7 +450,7 @@ func parseRunningInfo(info string) (map[int]DCURunningInfo, error) { ...@@ -450,7 +450,7 @@ func parseRunningInfo(info string) (map[int]DCURunningInfo, error) {
} }
type DCUPidInfo struct { type DCUPidInfo struct {
Pid uint64 Pid int32
PASId uint64 PASId uint64
HCUNode []string HCUNode []string
HCUIndex []string HCUIndex []string
...@@ -527,7 +527,7 @@ func parseDCUPidInfo(s string) ([]DCUPidInfo, error) { ...@@ -527,7 +527,7 @@ func parseDCUPidInfo(s string) ([]DCUPidInfo, error) {
if innerErr != nil { if innerErr != nil {
return nil, innerErr return nil, innerErr
} }
i.Pid = pid i.Pid = int32(pid)
i.PASId, innerErr = strconv.ParseUint(info[PASIDHeader], 10, 64) i.PASId, innerErr = strconv.ParseUint(info[PASIDHeader], 10, 64)
if innerErr != nil { if innerErr != nil {
return nil, innerErr return nil, innerErr
......
================================= System Management Interface ==================================
================================================================================================
PIDs for KFD processes:
PID: 16407
PASID: 32768
HCU Node(Include CPU sort):
HCU Index:
GPUID:
PCI BUS:
VRAM USED(MiB): 0
VRAM USED(%): inf
SDMA USED: 0
PID: 17343
PASID: 32784
HCU Node(Include CPU sort): ['14']
HCU Index: ['6']
GPUID: ['11320']
PCI BUS: ['0000:25:00.0']
VRAM USED(MiB): 62524
VRAM USED(%): 95
SDMA USED: 0
PID: 17341
PASID: 32780
HCU Node(Include CPU sort): ['12']
HCU Index: ['4']
GPUID: ['7796']
PCI BUS: ['0000:1d:00.0']
VRAM USED(MiB): 62460
VRAM USED(%): 95
SDMA USED: 0
PID: 16579
PASID: 32769
HCU Node(Include CPU sort):
HCU Index:
GPUID:
PCI BUS:
VRAM USED(MiB): 0
VRAM USED(%): inf
SDMA USED: 0
PID: 17344
PASID: 32797
HCU Node(Include CPU sort): ['15']
HCU Index: ['7']
GPUID: ['50100']
PCI BUS: ['0000:2c:00.0']
VRAM USED(MiB): 62524
VRAM USED(%): 95
SDMA USED: 0
PID: 17099
PASID: 32778
HCU Node(Include CPU sort):
HCU Index:
GPUID:
PCI BUS:
VRAM USED(MiB): 0
VRAM USED(%): inf
SDMA USED: 0
PID: 17342
PASID: 32779
HCU Node(Include CPU sort): ['13']
HCU Index: ['5']
GPUID: ['13523']
PCI BUS: ['0000:20:00.0']
VRAM USED(MiB): 62524
VRAM USED(%): 95
SDMA USED: 0
================================================================================================
======================================== End of SMI Log ========================================
...@@ -36,6 +36,7 @@ func GetProcessInfo(pid int32) { ...@@ -36,6 +36,7 @@ func GetProcessInfo(pid int32) {
if err != nil { if err != nil {
return return
} }
p.Times()
cmdStr, err := p.Cmdline() cmdStr, err := p.Cmdline()
if err != nil { if err != nil {
return return
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/shirou/gopsutil/v4/cpu" "github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/process"
) )
func TestGetSysUsers(t *testing.T) { func TestGetSysUsers(t *testing.T) {
...@@ -36,3 +37,11 @@ func BenchmarkGetSysInfo(b *testing.B) { ...@@ -36,3 +37,11 @@ func BenchmarkGetSysInfo(b *testing.B) {
} }
b.Logf("%+v", result) b.Logf("%+v", result)
} }
func TestCPUTime(t *testing.T) {
p, _ := process.NewProcess(1)
tt, _ := p.Times()
t.Logf("%s", tt.String())
tt1 := time.Duration(int((tt.User + tt.System))) * time.Second
t.Logf("%s", tt1.String())
}
...@@ -63,7 +63,7 @@ type MemorySize struct { ...@@ -63,7 +63,7 @@ type MemorySize struct {
Unit StorageCapacityUnit Unit StorageCapacityUnit
} }
func (s MemorySize) HumanReadStr() string { func (s MemorySize) HumanReadStr(i int) string {
total := s.Num * uint64(s.Unit) total := s.Num * uint64(s.Unit)
units := []StorageCapacityUnit{Byte, KiB, MiB, GiB, TiB, PiB} units := []StorageCapacityUnit{Byte, KiB, MiB, GiB, TiB, PiB}
var target StorageCapacityUnit var target StorageCapacityUnit
...@@ -76,7 +76,19 @@ func (s MemorySize) HumanReadStr() string { ...@@ -76,7 +76,19 @@ func (s MemorySize) HumanReadStr() string {
} }
} }
num := float64(total) / float64(target) num := float64(total) / float64(target)
return fmt.Sprintf("%.3f %s", num, target) switch i {
case 0:
return fmt.Sprintf("%d %s", int(num), target)
case 1:
return fmt.Sprintf("%.1f %s", num, target)
case 2:
return fmt.Sprintf("%.2f %s", num, target)
case 3:
return fmt.Sprintf("%.3f %s", num, target)
default:
return fmt.Sprintf("%.3f %s", num, target)
}
} }
func ParseUnit(s string) (StorageCapacityUnit, error) { func ParseUnit(s string) (StorageCapacityUnit, error) {
......
package utils package utils
import ( import (
"strings"
"testing" "testing"
) )
...@@ -56,8 +57,17 @@ func TestParseMemorySize(t *testing.T) { ...@@ -56,8 +57,17 @@ func TestParseMemorySize(t *testing.T) {
func TestHumanReadStr(t *testing.T) { func TestHumanReadStr(t *testing.T) {
ms := MemorySize{Num: 1025, Unit: Byte} ms := MemorySize{Num: 1025, Unit: Byte}
t.Log(ms.HumanReadStr()) t.Log(ms.HumanReadStr(2))
ms.Num = 1025 ms.Num = 1025
ms.Unit = PiB ms.Unit = PiB
t.Log(ms.HumanReadStr()) t.Log(ms.HumanReadStr(1))
}
func TestFo(t *testing.T) {
sb := strings.Builder{}
sb.WriteString("hello world\n")
sb.WriteString("time is come\n")
t.Log(sb.String())
sb.WriteString("okoko")
t.Log(sb.String())
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment