Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
liming6
dcu-process-montor
Commits
63d7bbfc
Commit
63d7bbfc
authored
Nov 14, 2025
by
liming6
Browse files
feature 添加展示进程信息功能
parent
9608d37d
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
491 additions
and
72 deletions
+491
-72
cmd/dcutop/backend/main.go
cmd/dcutop/backend/main.go
+135
-1
cmd/dcutop/tui/main.go
cmd/dcutop/tui/main.go
+21
-12
cmd/dcutop/tui/process.go
cmd/dcutop/tui/process.go
+129
-0
cmd/dcutop/tui/sysload.go
cmd/dcutop/tui/sysload.go
+1
-1
cmd/dcutop/tui/tui_test.go
cmd/dcutop/tui/tui_test.go
+7
-15
docker/find.go
docker/find.go
+60
-36
docker/find_test.go
docker/find_test.go
+23
-1
gpu/hy-smi.go
gpu/hy-smi.go
+2
-2
test-data/hy-smi-1.20.0-pids.log
test-data/hy-smi-1.20.0-pids.log
+77
-0
utils/pid.go
utils/pid.go
+1
-0
utils/system_test.go
utils/system_test.go
+9
-0
utils/unit.go
utils/unit.go
+14
-2
utils/utils_test.go
utils/utils_test.go
+12
-2
No files found.
cmd/dcutop/backend/main.go
View file @
63d7bbfc
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"
)
)
/*
/*
...
@@ -11,8 +19,29 @@ import (
...
@@ -11,8 +19,29 @@ 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
}
cmd/dcutop/tui/main.go
View file @
63d7bbfc
...
@@ -21,7 +21,7 @@ type ModelMsg struct {
...
@@ -21,7 +21,7 @@ type ModelMsg struct {
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.DCUPid
Info
// 使用dcu的进程信息
DCUPidInfo
map
[
int
][]
backend
.
DCUProcess
Info
// 使用dcu的进程信息
systemInfo
*
utils
.
SysInfo
// 系统信息
systemInfo
*
utils
.
SysInfo
// 系统信息
}
}
...
@@ -33,7 +33,7 @@ type ModelMain struct {
...
@@ -33,7 +33,7 @@ type ModelMain struct {
Header
*
ModelHeader
Header
*
ModelHeader
DCUInfo
*
ModelDCUInfo
DCUInfo
*
ModelDCUInfo
SysLoad
*
ModelSysLoad
SysLoad
*
ModelSysLoad
//
ProcessInfo *ModelProcess
ProcessInfo
*
ModelProcess
Info
index
uint64
// 记录update次数的值
index
uint64
// 记录update次数的值
modelMsg
*
ModelMsg
// 记录模型信息
modelMsg
*
ModelMsg
// 记录模型信息
}
}
...
@@ -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
()
}
}
cmd/dcutop/tui/process.go
0 → 100644
View file @
63d7bbfc
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
}
cmd/dcutop/tui/sysload.go
View file @
63d7bbfc
...
@@ -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
)
...
...
cmd/dcutop/tui/tui_test.go
View file @
63d7bbfc
...
@@ -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
.
Log
f
(
"
\n
%s"
,
m
.
View
())
}
}
docker/find.go
View file @
63d7bbfc
...
@@ -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
u
int
64
Pid
int
32
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
}
}
}
}
for
_
,
fields
:=
range
topResp
.
Processes
{
item
:=
ContainerPsInfo
{}
item
:=
ContainerPsInfo
{}
if
v
,
ok
:=
indexMap
[
"pid"
];
ok
{
if
v
,
ok
:=
indexMap
[
"pid"
];
ok
{
pid
,
err
:=
strconv
.
ParseUint
(
topResp
.
Processes
[
v
][
0
],
10
,
64
)
pid
,
err
:=
strconv
.
ParseUint
(
fields
[
v
],
10
,
64
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
item
.
Pid
=
pid
item
.
Pid
=
int32
(
pid
)
}
}
if
v
,
ok
:=
indexMap
[
"ppid"
];
ok
{
if
v
,
ok
:=
indexMap
[
"ppid"
];
ok
{
ppid
,
err
:=
strconv
.
ParseUint
(
topResp
.
Processes
[
v
][
0
],
10
,
64
)
ppid
,
err
:=
strconv
.
ParseUint
(
fields
[
v
],
10
,
64
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
item
.
Ppid
=
ppid
item
.
Ppid
=
ppid
}
}
if
v
,
ok
:=
indexMap
[
"uid"
];
ok
{
if
v
,
ok
:=
indexMap
[
"uid"
];
ok
{
item
.
Uid
=
topResp
.
Processe
s
[
v
]
[
0
]
item
.
Uid
=
field
s
[
v
]
}
}
if
v
,
ok
:=
indexMap
[
"cmd"
];
ok
{
if
v
,
ok
:=
indexMap
[
"cmd"
];
ok
{
item
.
Cmd
=
topResp
.
Processes
[
v
]
item
.
Cmd
=
fields
[
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
{
...
...
docker/find_test.go
View file @
63d7bbfc
...
@@ -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
)
}
gpu/hy-smi.go
View file @
63d7bbfc
...
@@ -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
u
int
64
Pid
int
32
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
...
...
test-data/hy-smi-1.20.0-pids.log
0 → 100644
View file @
63d7bbfc
================================= 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 ========================================
utils/pid.go
View file @
63d7bbfc
...
@@ -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
...
...
utils/system_test.go
View file @
63d7bbfc
...
@@ -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
())
}
utils/unit.go
View file @
63d7bbfc
...
@@ -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
)
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
)
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
)
{
...
...
utils/utils_test.go
View file @
63d7bbfc
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
())
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment