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
You need to sign in or sign up before continuing.
Commit
63d7bbfc
authored
Nov 14, 2025
by
liming6
Browse files
feature 添加展示进程信息功能
parent
9608d37d
Changes
13
Hide 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
import
(
"get-container/docker"
"get-container/gpu"
"get-container/utils"
"maps"
"os"
"strconv"
"sync"
"time"
"github.com/shirou/gopsutil/v4/process"
)
/*
...
...
@@ -10,9 +18,30 @@ import (
*/
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
{
Id
int
Name
string
// full
...
...
@@ -167,3 +196,108 @@ func GetDCUInfo() map[int]DCUInfo {
})
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
...
...
@@ -16,13 +16,13 @@ const (
// ModelMsg 模型信息,在父组件和各个子组件间共享信息
type
ModelMsg
struct
{
t
time
.
Time
// 当前时间
index
uint64
// update次数
Version
*
gpu
.
HYVersionInfo
// gpu版本相关信息
MyVersion
string
DCUInfo
map
[
int
]
backend
.
DCUInfo
// DCU全量信息
//
DCUPidInfo
[]gpu.DCUPid
Info
// 使用dcu的进程信息
systemInfo
*
utils
.
SysInfo
// 系统信息
t
time
.
Time
// 当前时间
index
uint64
// update次数
Version
*
gpu
.
HYVersionInfo
// gpu版本相关信息
MyVersion
string
DCUInfo
map
[
int
]
backend
.
DCUInfo
// DCU全量信息
DCUPidInfo
map
[
int
][]
backend
.
DCUProcess
Info
// 使用dcu的进程信息
systemInfo
*
utils
.
SysInfo
// 系统信息
}
type
TickMsg
time
.
Time
...
...
@@ -33,9 +33,9 @@ type ModelMain struct {
Header
*
ModelHeader
DCUInfo
*
ModelDCUInfo
SysLoad
*
ModelSysLoad
//
ProcessInfo *ModelProcess
index
uint64
// 记录update次数的值
modelMsg
*
ModelMsg
// 记录模型信息
ProcessInfo
*
ModelProcess
Info
index
uint64
// 记录update次数的值
modelMsg
*
ModelMsg
// 记录模型信息
}
func
NewModelMain
(
width
,
height
int
)
ModelMain
{
...
...
@@ -45,6 +45,7 @@ func NewModelMain(width, height int) ModelMain {
result
.
Header
=
&
ModelHeader
{}
result
.
DCUInfo
=
&
ModelDCUInfo
{
width
:
width
,
height
:
height
,
info
:
make
(
map
[
int
]
backend
.
DCUInfo
)}
result
.
SysLoad
=
NewModelSysLoad
(
width
)
result
.
ProcessInfo
=
NewModelProcessInfo
(
width
)
return
result
}
...
...
@@ -78,7 +79,9 @@ func (m *ModelMain) Init() tea.Cmd {
if
c
:=
m
.
SysLoad
.
Init
();
c
!=
nil
{
cmds
=
append
(
cmds
,
c
)
}
if
c
:=
m
.
ProcessInfo
.
Init
();
c
!=
nil
{
cmds
=
append
(
cmds
,
c
)
}
m
.
modelMsg
=
&
modelMsg
// 将调用初始化方法
cmds
=
append
(
cmds
,
tickCmd
(),
sendMsgCmd
(
&
modelMsg
))
...
...
@@ -98,24 +101,28 @@ func (m *ModelMain) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) {
header
,
_
:=
m
.
Header
.
Update
(
m
.
modelMsg
)
dcuInfo
,
_
:=
m
.
DCUInfo
.
Update
(
m
.
modelMsg
)
sysLoad
,
_
:=
m
.
SysLoad
.
Update
(
m
.
modelMsg
)
pidinfo
,
_
:=
m
.
ProcessInfo
.
Update
(
m
.
modelMsg
)
m
.
Header
=
header
.
(
*
ModelHeader
)
m
.
DCUInfo
=
dcuInfo
.
(
*
ModelDCUInfo
)
m
.
SysLoad
=
sysLoad
.
(
*
ModelSysLoad
)
m
.
ProcessInfo
=
pidinfo
.
(
*
ModelProcessInfo
)
return
m
,
tickCmd
()
case
ModelMsg
:
// 初始化
header
,
_
:=
m
.
Header
.
Update
(
m
.
modelMsg
)
dcuInfo
,
_
:=
m
.
DCUInfo
.
Update
(
m
.
modelMsg
)
sysLoad
,
_
:=
m
.
SysLoad
.
Update
(
m
.
modelMsg
)
pidinfo
,
_
:=
m
.
ProcessInfo
.
Update
(
m
.
modelMsg
)
m
.
Header
=
header
.
(
*
ModelHeader
)
m
.
DCUInfo
=
dcuInfo
.
(
*
ModelDCUInfo
)
m
.
SysLoad
=
sysLoad
.
(
*
ModelSysLoad
)
m
.
ProcessInfo
=
pidinfo
.
(
*
ModelProcessInfo
)
return
m
,
nil
}
return
m
,
nil
}
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
{
...
...
@@ -150,6 +157,7 @@ func initModelInfo(model *ModelMsg) error {
}
model
.
DCUInfo
=
backend
.
GetDCUInfo
()
model
.
systemInfo
,
err
=
utils
.
GetSysInfo
()
model
.
DCUPidInfo
=
backend
.
GetDCUProcessInfo
()
return
err
}
...
...
@@ -164,4 +172,5 @@ func updateModelInfo(modelMsg *ModelMsg, index uint64, t time.Time) {
}
modelMsg
.
DCUInfo
=
backend
.
GetDCUInfo
()
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 {
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
)
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
)
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
import
(
"fmt"
"get-container/cmd/dcutop/tchart"
"strings"
"testing"
"time"
"github.com/charmbracelet/lipgloss"
"github.com/emirpasic/gods/v2/maps/linkedhashmap"
"github.com/emirpasic/gods/v2/trees/binaryheap"
)
...
...
@@ -97,19 +97,11 @@ func TestBinaryHeap(t *testing.T) {
}
}
func
TestLinkedHashMap
(
t
*
testing
.
T
)
{
m
:=
linkedhashmap
.
New
[
time
.
Time
,
int
]()
now
:=
time
.
Now
()
for
i
:=
range
5
{
m
.
Put
(
now
.
Add
(
time
.
Duration
(
i
)
*
time
.
Second
),
5
-
i
)
}
mi
:=
m
.
Iterator
()
for
{
if
mi
.
Next
()
{
t
.
Logf
(
"%v: %d"
,
mi
.
Key
(),
mi
.
Value
())
}
else
{
break
}
func
TestNewModelProcessInfo
(
t
*
testing
.
T
)
{
m
:=
NewModelProcessInfo
(
130
)
t
.
Logf
(
"
\n
%s"
,
m
.
Header
)
for
l
:=
range
strings
.
SplitSeq
(
m
.
Header
,
"
\n
"
)
{
t
.
Log
(
lipgloss
.
Width
(
l
))
}
t
.
Log
(
m
.
Size
())
t
.
Log
f
(
"
\n
%s"
,
m
.
View
())
}
docker/find.go
View file @
63d7bbfc
...
...
@@ -7,13 +7,14 @@ import (
"context"
"errors"
"fmt"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/client"
"os"
"regexp"
"strings"
"sync"
"time"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/client"
)
/**
...
...
@@ -45,66 +46,64 @@ type ContainersInfo struct {
}
type
ContainerPsInfo
struct
{
Pid
u
int
64
Pid
int
32
Ppid
uint64
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
{
return
nil
,
errors
.
New
(
"topInfo is nil"
)
}
result
:=
make
(
map
[
string
]
ContainerPsInfo
)
indexMap
,
t
:=
make
(
map
[
string
]
int
),
0
result
:=
make
(
map
[
string
][]
ContainerPsInfo
)
for
cid
,
topResp
:=
range
topInfo
{
indexMap
,
t
:=
make
(
map
[
string
]
int
),
0
result
[
cid
]
=
make
([]
ContainerPsInfo
,
0
)
for
index
,
key
:=
range
topResp
.
Titles
{
switch
strings
.
TrimSpace
(
strings
.
ToLower
(
key
))
{
case
"pid"
:
indexMap
[
key
]
=
index
indexMap
[
"pid"
]
=
index
t
++
break
case
"ppid"
:
indexMap
[
key
]
=
index
indexMap
[
"ppid"
]
=
index
t
++
break
case
"uid"
:
indexMap
[
key
]
=
index
indexMap
[
"uid"
]
=
index
t
++
break
case
"cmd"
:
indexMap
[
key
]
=
index
indexMap
[
"cmd"
]
=
index
t
++
break
default
:
break
}
if
t
>=
4
{
break
}
}
item
:=
ContainerPsInfo
{}
if
v
,
ok
:=
indexMap
[
"pid"
];
ok
{
pid
,
err
:=
strconv
.
ParseUint
(
topResp
.
Processes
[
v
][
0
],
10
,
64
)
if
err
!=
nil
{
return
nil
,
err
for
_
,
fields
:=
range
topResp
.
Processes
{
item
:=
ContainerPsInfo
{}
if
v
,
ok
:=
indexMap
[
"pid"
];
ok
{
pid
,
err
:=
strconv
.
ParseUint
(
fields
[
v
],
10
,
64
)
if
err
!=
nil
{
return
nil
,
err
}
item
.
Pid
=
int32
(
pid
)
}
i
tem
.
Pid
=
pid
}
if
v
,
ok
:=
indexMap
[
"ppid"
];
ok
{
ppid
,
err
:=
strconv
.
ParseUint
(
topResp
.
Processes
[
v
][
0
],
10
,
64
)
if
err
!=
nil
{
return
nil
,
err
i
f
v
,
ok
:=
indexMap
[
"ppid"
];
ok
{
ppid
,
err
:=
strconv
.
ParseUint
(
fields
[
v
],
10
,
64
)
if
err
!=
nil
{
return
nil
,
err
}
item
.
Ppid
=
ppid
}
i
tem
.
Ppid
=
ppid
}
if
v
,
ok
:=
indexMap
[
"uid"
];
ok
{
i
tem
.
Uid
=
topResp
.
Processes
[
v
][
0
]
}
if
v
,
ok
:=
indexMap
[
"cmd"
];
ok
{
item
.
Cmd
=
topResp
.
Processes
[
v
]
i
f
v
,
ok
:=
indexMap
[
"uid"
];
ok
{
item
.
Uid
=
fields
[
v
]
}
i
f
v
,
ok
:=
indexMap
[
"cmd"
];
ok
{
item
.
Cmd
=
fields
[
v
]
}
result
[
cid
]
=
append
(
result
[
cid
],
item
)
}
result
[
cid
]
=
item
}
return
result
,
nil
}
...
...
@@ -148,6 +147,31 @@ func initContainerInfo() error {
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
func
FindContainerIdByPid
(
pid
uint64
,
method
FindCIDMethod
)
(
*
string
,
error
)
{
switch
method
{
...
...
@@ -161,7 +185,7 @@ func FindContainerIdByPid(pid uint64, method FindCIDMethod) (*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
}
switch
method
{
...
...
docker/find_test.go
View file @
63d7bbfc
...
...
@@ -2,9 +2,11 @@ package docker
import
(
"context"
"github.com/moby/moby/client"
"strings"
"testing"
"time"
"github.com/moby/moby/client"
)
func
TestRegexp
(
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) {
}
type
DCUPidInfo
struct
{
Pid
u
int
64
Pid
int
32
PASId
uint64
HCUNode
[]
string
HCUIndex
[]
string
...
...
@@ -527,7 +527,7 @@ func parseDCUPidInfo(s string) ([]DCUPidInfo, error) {
if
innerErr
!=
nil
{
return
nil
,
innerErr
}
i
.
Pid
=
pid
i
.
Pid
=
int32
(
pid
)
i
.
PASId
,
innerErr
=
strconv
.
ParseUint
(
info
[
PASIDHeader
],
10
,
64
)
if
innerErr
!=
nil
{
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) {
if
err
!=
nil
{
return
}
p
.
Times
()
cmdStr
,
err
:=
p
.
Cmdline
()
if
err
!=
nil
{
return
...
...
utils/system_test.go
View file @
63d7bbfc
...
...
@@ -5,6 +5,7 @@ import (
"time"
"github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/process"
)
func
TestGetSysUsers
(
t
*
testing
.
T
)
{
...
...
@@ -36,3 +37,11 @@ func BenchmarkGetSysInfo(b *testing.B) {
}
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 {
Unit
StorageCapacityUnit
}
func
(
s
MemorySize
)
HumanReadStr
()
string
{
func
(
s
MemorySize
)
HumanReadStr
(
i
int
)
string
{
total
:=
s
.
Num
*
uint64
(
s
.
Unit
)
units
:=
[]
StorageCapacityUnit
{
Byte
,
KiB
,
MiB
,
GiB
,
TiB
,
PiB
}
var
target
StorageCapacityUnit
...
...
@@ -76,7 +76,19 @@ func (s MemorySize) HumanReadStr() string {
}
}
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
)
{
...
...
utils/utils_test.go
View file @
63d7bbfc
package
utils
import
(
"strings"
"testing"
)
...
...
@@ -56,8 +57,17 @@ func TestParseMemorySize(t *testing.T) {
func
TestHumanReadStr
(
t
*
testing
.
T
)
{
ms
:=
MemorySize
{
Num
:
1025
,
Unit
:
Byte
}
t
.
Log
(
ms
.
HumanReadStr
())
t
.
Log
(
ms
.
HumanReadStr
(
2
))
ms
.
Num
=
1025
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