Commit 3e5adb86 authored by liming6's avatar liming6
Browse files

feature 添加进程选择功能

parent c915d1bd
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"get-container/utils" "get-container/utils"
"math" "math"
"os" "os"
"sort"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
...@@ -364,7 +365,8 @@ func (m *DCUInfoMap) GetDCUProcessInfo2() map[int][]DCUProcessInfo { ...@@ -364,7 +365,8 @@ func (m *DCUInfoMap) GetDCUProcessInfo2() map[int][]DCUProcessInfo {
pids = append(pids, int32(v.Pid)) pids = append(pids, int32(v.Pid))
} }
pinfo := getProcessInfo(pids) pinfo := getProcessInfo(pids)
for _, v := range info { for _, v := range info { // 按照进程遍历
// 获取进程使用的所有dcu的索引
index := make([]int, 0) index := make([]int, 0)
for _, i := range v.HCUIndex { for _, i := range v.HCUIndex {
ii, err := strconv.Atoi(i) ii, err := strconv.Atoi(i)
...@@ -384,9 +386,17 @@ func (m *DCUInfoMap) GetDCUProcessInfo2() map[int][]DCUProcessInfo { ...@@ -384,9 +386,17 @@ func (m *DCUInfoMap) GetDCUProcessInfo2() map[int][]DCUProcessInfo {
item.DCUMem = v.VRamUsed.HumanReadStr(1) item.DCUMem = v.VRamUsed.HumanReadStr(1)
item.SDMA = v.SDMAUsed item.SDMA = v.SDMAUsed
l = append(l, item) l = append(l, item)
result[i] = l result[i] = l
} }
} }
// 每个切片对pid排序
for k, v := range result {
sort.SliceStable(v, func(i, j int) bool {
return v[i].Info.Pid < v[j].Info.Pid
})
result[k] = v
}
return result return result
} }
......
...@@ -21,7 +21,7 @@ func main() { ...@@ -21,7 +21,7 @@ func main() {
log.Fatalf("error init data backend: %v", err) log.Fatalf("error init data backend: %v", err)
} }
model := tui.NewModelMain(w, h) model := tui.NewModelMain(w, h)
if _, err := tea.NewProgram(&model).Run(); err != nil { if _, err := tea.NewProgram(&model, tea.WithAltScreen()).Run(); err != nil {
log.Fatalf("error create program; %v", err) log.Fatalf("error create program; %v", err)
} }
backend.Shutdown() backend.Shutdown()
......
...@@ -10,14 +10,18 @@ import ( ...@@ -10,14 +10,18 @@ import (
"github.com/charmbracelet/bubbles/progress" "github.com/charmbracelet/bubbles/progress"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
"github.com/lucasb-eyer/go-colorful"
"github.com/muesli/gamut"
"github.com/muesli/termenv" "github.com/muesli/termenv"
) )
type ModelDCUInfo struct { type ModelDCUInfo struct {
pro progress.Model // 进度条 pro progress.Model // 进度条
proLowLeight progress.Model // 低亮度进度条
proWidth int // 进度条宽度 proWidth int // 进度条宽度
modMsg *ModelMsg modMsg *ModelMsg
width, height int width, height int
actionMsg *ActionMsg
} }
const ( const (
...@@ -46,7 +50,10 @@ func (m *ModelDCUInfo) Init() tea.Cmd { ...@@ -46,7 +50,10 @@ func (m *ModelDCUInfo) Init() tea.Cmd {
if m.width > StaticWidth+ProgressMinWidth+OtherWidth { if m.width > StaticWidth+ProgressMinWidth+OtherWidth {
m.proWidth = m.width - OtherWidth - StaticWidth m.proWidth = m.width - OtherWidth - StaticWidth
} }
m.pro = progress.New(progress.WithColorProfile(termenv.TrueColor), progress.WithGradient("#0000ffff", "#ff0000ff"), progress.WithWidth(m.proWidth)) m.pro = progress.New(progress.WithColorProfile(termenv.TrueColor), progress.WithGradient("#0000ffff", "#ff0000ff"), progress.WithWidth(m.proWidth-5), progress.WithoutPercentage())
c1, _ := colorful.MakeColor(gamut.Darker(lipgloss.Color("#0000ffff"), 0.8))
c2, _ := colorful.MakeColor(gamut.Darker(lipgloss.Color("#ff0000ff"), 0.8))
m.proLowLeight = progress.New(progress.WithColorProfile(termenv.TrueColor), progress.WithGradient(c1.Hex(), c2.Hex()), progress.WithWidth(m.proWidth-5), progress.WithoutPercentage())
return nil return nil
} }
...@@ -59,6 +66,9 @@ func (m *ModelDCUInfo) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) { ...@@ -59,6 +66,9 @@ func (m *ModelDCUInfo) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) {
m.height = msg.Height m.height = msg.Height
m.width = msg.Width m.width = msg.Width
return m, nil return m, nil
case *ActionMsg:
m.actionMsg = msg
return m, nil
} }
return m, nil return m, nil
} }
...@@ -72,77 +82,146 @@ func (m *ModelDCUInfo) View() string { ...@@ -72,77 +82,146 @@ func (m *ModelDCUInfo) View() string {
smap, slock := m.modMsg.DCUInfo.GetSlowInfo() smap, slock := m.modMsg.DCUInfo.GetSlowInfo()
defer slock.Unlock() defer slock.Unlock()
defer qlock.Unlock() defer qlock.Unlock()
conTime := 0
strBuilder := strings.Builder{} strBuilder := strings.Builder{}
strCache := strings.Builder{}
var targetDCU int = -1
if m.actionMsg != nil && m.actionMsg.TargetDCUIndex != nil {
targetDCU = *m.actionMsg.TargetDCUIndex
}
infos := make([]string, 0) infos := make([]string, 0)
for i := range 128 { for i := range 64 {
qinfo, haveq := qmap[i] qinfo, haveq := qmap[i]
sinfo, haves := smap[i] sinfo, haves := smap[i]
if !(haveq || haves) { if !(haveq || haves) {
conTime++
if conTime > 8 {
break
}
continue continue
} }
isLowStyle := (targetDCU != qinfo.Id && targetDCU != -1)
strBuilder.WriteString(myBorder.Left) strBuilder.WriteString(myBorder.Left)
strBuilder.WriteByte(' ')
strBuilder.WriteString(FormatStr(strconv.Itoa(qinfo.Id), 4, lipgloss.Left)) strCache.WriteByte(' ')
strBuilder.WriteByte(' ') strCache.WriteString(FormatStr(strconv.Itoa(qinfo.Id), 4, lipgloss.Left))
strBuilder.WriteString(FormatStr(ReDCUName.FindString(qinfo.Name), 8, lipgloss.Left)) strCache.WriteByte(' ')
strBuilder.WriteByte(' ') strCache.WriteString(FormatStr(ReDCUName.FindString(qinfo.Name), 8, lipgloss.Left))
strBuilder.WriteString(FormatStr(qinfo.PerformanceLevel, 15, lipgloss.Right)) strCache.WriteByte(' ')
strBuilder.WriteByte(' ') strCache.WriteString(FormatStr(qinfo.PerformanceLevel, 15, lipgloss.Right))
strBuilder.WriteString(myBorder.Left) strCache.WriteByte(' ')
strBuilder.WriteByte(' ')
strBuilder.WriteString(FormatStr(qinfo.BusId, 13, lipgloss.Left)) if isLowStyle {
strBuilder.WriteByte(' ') str := strCache.String()
strBuilder.WriteString(FormatStr("Off", 6, lipgloss.Right)) strBuilder.WriteString(LowLeightStyle.Render(str))
strBuilder.WriteByte(' ') } else {
strBuilder.WriteString(strCache.String())
}
strCache.Reset()
strBuilder.WriteString(myBorder.Left) strBuilder.WriteString(myBorder.Left)
strBuilder.WriteByte(' ')
if sinfo.Mig.Load() { strCache.WriteByte(' ')
strBuilder.WriteString(FormatStr("On", 16, lipgloss.Left)) strCache.WriteString(FormatStr(qinfo.BusId, 13, lipgloss.Left))
strCache.WriteByte(' ')
strCache.WriteString(FormatStr("Off", 6, lipgloss.Right))
strCache.WriteByte(' ')
if isLowStyle {
str := strCache.String()
strBuilder.WriteString(LowLeightStyle.Render(str))
} else { } else {
strBuilder.WriteString(FormatStr("Off", 16, lipgloss.Left)) strBuilder.WriteString(strCache.String())
} }
strBuilder.WriteByte(' ') strCache.Reset()
strCache.WriteByte(' ')
strCache.WriteString(FormatStr("Off", 16, lipgloss.Left))
strBuilder.WriteString(myBorder.Left)
strCache.WriteByte(' ')
if sinfo.Ecc.Load() { if sinfo.Ecc.Load() {
strBuilder.WriteString(FormatStr("On", 3, lipgloss.Right)) strCache.WriteString(FormatStr("On", 3, lipgloss.Right))
} else {
strCache.WriteString(FormatStr("Off", 3, lipgloss.Right))
}
strCache.WriteByte(' ')
if isLowStyle {
str := strCache.String()
strBuilder.WriteString(LowLeightStyle.Render(str))
} else { } else {
strBuilder.WriteString(FormatStr("Off", 3, lipgloss.Right)) strBuilder.WriteString(strCache.String())
} }
strBuilder.WriteByte(' ') strCache.Reset()
strBuilder.WriteString(myBorder.Left) strBuilder.WriteString(myBorder.Left)
strBuilder.WriteString(" DCU: ")
strBuilder.WriteString(m.pro.ViewAs(float64(qinfo.DCUUTil / 100))) if isLowStyle {
strBuilder.WriteByte(' ') strBuilder.WriteString(LowLeightStyle.Render(" DCU: "))
strBuilder.WriteString(m.proLowLeight.ViewAs(float64(qinfo.DCUUTil / 100)))
strBuilder.WriteString(LowLeightStyle.Render(fmt.Sprintf(" %3d%% ", int(qinfo.DCUUTil))))
} else {
strBuilder.WriteString(" DCU: ")
strBuilder.WriteString(m.pro.ViewAs(float64(qinfo.DCUUTil / 100)))
strBuilder.WriteString(fmt.Sprintf(" %3d%% ", int(qinfo.DCUUTil)))
}
strBuilder.WriteString(myBorder.Left) strBuilder.WriteString(myBorder.Left)
strBuilder.WriteByte('\n') strBuilder.WriteByte('\n')
strBuilder.WriteString(myBorder.Left) strBuilder.WriteString(myBorder.Left)
strBuilder.WriteByte(' ')
strBuilder.WriteString(FormatStr(qinfo.Fan, 4, lipgloss.Left)) strCache.WriteByte(' ')
strBuilder.WriteByte(' ') strCache.WriteString(FormatStr(qinfo.Fan, 4, lipgloss.Left))
strBuilder.WriteString(FormatStr(fmt.Sprintf("%.1fC", qinfo.Temp), 6, lipgloss.Left)) strCache.WriteByte(' ')
strBuilder.WriteByte(' ') strCache.WriteString(FormatStr(fmt.Sprintf("%.1fC", qinfo.Temp), 6, lipgloss.Left))
// 18 strCache.WriteByte(' ')
strBuilder.WriteString(FormatStr(fmt.Sprintf("%.1fW / %.1fW", qinfo.PwrAvg, qinfo.PwrCap), 17, lipgloss.Right)) strCache.WriteString(FormatStr(fmt.Sprintf("%.1fW / %.1fW", qinfo.PwrAvg, qinfo.PwrCap), 17, lipgloss.Right))
strBuilder.WriteByte(' ') strCache.WriteByte(' ')
if isLowStyle {
str := strCache.String()
strBuilder.WriteString(LowLeightStyle.Render(str))
} else {
strBuilder.WriteString(strCache.String())
}
strCache.Reset()
strBuilder.WriteString(myBorder.Left) strBuilder.WriteString(myBorder.Left)
strBuilder.WriteByte(' ')
// 20 if isLowStyle {
strBuilder.WriteString(FormatStr(fmt.Sprintf("%dMiB / %dMiB", qinfo.MemUsed/uint64(utils.MiB), qinfo.MemTotal/uint64(utils.MiB)), 20, lipgloss.Right)) strCache.WriteByte(' ')
strBuilder.WriteByte(' ') strCache.WriteString(FormatStr(fmt.Sprintf("%dMiB / %dMiB", qinfo.MemUsed/uint64(utils.MiB), qinfo.MemTotal/uint64(utils.MiB)), 20, lipgloss.Right))
strCache.WriteByte(' ')
strBuilder.WriteString(LowLeightStyle.Render(strCache.String()))
strCache.Reset()
} else {
strBuilder.WriteByte(' ')
strBuilder.WriteString(FormatStr(fmt.Sprintf("%dMiB / %dMiB", qinfo.MemUsed/uint64(utils.MiB), qinfo.MemTotal/uint64(utils.MiB)), 20, lipgloss.Right))
strBuilder.WriteByte(' ')
}
strBuilder.WriteString(myBorder.Left) strBuilder.WriteString(myBorder.Left)
strBuilder.WriteByte(' ')
strBuilder.WriteString(FormatStr(fmt.Sprintf("%.1f%%", qinfo.DCUUTil), 6, lipgloss.Left)) if isLowStyle {
strBuilder.WriteByte(' ') strCache.WriteByte(' ')
strBuilder.WriteString(FormatStr(sinfo.PwrMode.Load().(string), 13, lipgloss.Right)) strCache.WriteString(FormatStr(fmt.Sprintf("%.1f%%", qinfo.DCUUTil), 6, lipgloss.Left))
strBuilder.WriteByte(' ') strCache.WriteByte(' ')
strCache.WriteString(FormatStr(sinfo.PwrMode.Load().(string), 13, lipgloss.Right))
strCache.WriteByte(' ')
strBuilder.WriteString(LowLeightStyle.Render(strCache.String()))
strCache.Reset()
} else {
strBuilder.WriteByte(' ')
strBuilder.WriteString(FormatStr(fmt.Sprintf("%.1f%%", qinfo.DCUUTil), 6, lipgloss.Left))
strBuilder.WriteByte(' ')
strBuilder.WriteString(FormatStr(sinfo.PwrMode.Load().(string), 13, lipgloss.Right))
strBuilder.WriteByte(' ')
}
strBuilder.WriteString(myBorder.Left) strBuilder.WriteString(myBorder.Left)
strBuilder.WriteString(" Mem: ")
strBuilder.WriteString(m.pro.ViewAs(float64(qinfo.MemUsed) / float64(qinfo.MemTotal))) if isLowStyle {
strBuilder.WriteByte(' ') strCache.WriteString(" Mem: ")
strCache.WriteString(m.proLowLeight.ViewAs(float64(qinfo.MemUsed) / float64(qinfo.MemTotal)))
strCache.WriteString(LowLeightStyle.Render(fmt.Sprintf(" %3d%% ", int(100*float64(qinfo.MemUsed)/float64(qinfo.MemTotal)))))
strBuilder.WriteString(LowLeightStyle.Render(strCache.String()))
strCache.Reset()
} else {
strBuilder.WriteString(" Mem: ")
strBuilder.WriteString(m.pro.ViewAs(float64(qinfo.MemUsed) / float64(qinfo.MemTotal)))
strBuilder.WriteByte(' ')
strBuilder.WriteString(fmt.Sprintf("%3d%%", int(100*float64(qinfo.MemUsed)/float64(qinfo.MemTotal))))
strBuilder.WriteByte(' ')
}
strBuilder.WriteString(myBorder.Left) strBuilder.WriteString(myBorder.Left)
infos = append(infos, strBuilder.String()) infos = append(infos, strBuilder.String())
strBuilder.Reset() strBuilder.Reset()
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"get-container/cmd/hytop/backend" "get-container/cmd/hytop/backend"
"get-container/gpu" "get-container/gpu"
"get-container/utils" "get-container/utils"
"syscall"
"time" "time"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
...@@ -14,6 +15,15 @@ const ( ...@@ -14,6 +15,15 @@ const (
DCUTopVersion = "1.0.0" DCUTopVersion = "1.0.0"
) )
var (
HeightLightStyle = lipgloss.NewStyle().Background(lipgloss.Color("#00fffb7a")) // 高亮风格
SelectedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#ffb81fe3")) // 被选中的风格
HeightSelectedStyle = lipgloss.NewStyle().Background(lipgloss.Color("#ffb81fe3")) // 既被选中,又高亮的风格
LowLeightStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#442d2d"))
NormalStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#e6e6e6eb"))
)
// ModelMsg 模型信息,在父组件和各个子组件间共享信息 // ModelMsg 模型信息,在父组件和各个子组件间共享信息
type ModelMsg struct { type ModelMsg struct {
t time.Time // 当前时间 t time.Time // 当前时间
...@@ -26,6 +36,17 @@ type ModelMsg struct { ...@@ -26,6 +36,17 @@ type ModelMsg struct {
type TickMsg time.Time type TickMsg time.Time
// ActionMsg 动作消息
type ActionMsg struct {
SelectPids map[int32]bool // 选择的pid进程
Action *syscall.Signal // 对选择的pid的动作
PidView *int32 // 进程视图指标的pid号,为null表示没有进入进程指标视图
PointPid *int32 // 指针指向的pid,为null表示没有选择进程
PidEnvView *int32 // 进程环境变量视图的pid号,为null表示不进入进程环境变量视图
PidTreeView *int32 // 进入pstree视图的pid号,为null表示不进入pstree视图
TargetDCUIndex *int // PointPid使用的dcu index
}
// ModelMain tui主模型类 // ModelMain tui主模型类
type ModelMain struct { type ModelMain struct {
width, height int // 终端尺寸 width, height int // 终端尺寸
...@@ -34,6 +55,7 @@ type ModelMain struct { ...@@ -34,6 +55,7 @@ type ModelMain struct {
SysLoad *ModelSysLoad SysLoad *ModelSysLoad
ProcessInfo *ModelProcessInfo ProcessInfo *ModelProcessInfo
modelMsg *ModelMsg modelMsg *ModelMsg
actionMsg *ActionMsg
} }
func NewModelMain(width, height int) ModelMain { func NewModelMain(width, height int) ModelMain {
...@@ -44,6 +66,7 @@ func NewModelMain(width, height int) ModelMain { ...@@ -44,6 +66,7 @@ func NewModelMain(width, height int) ModelMain {
result.DCUInfo = NewModelDCUInfo(width, height) result.DCUInfo = NewModelDCUInfo(width, height)
result.SysLoad = NewModelSysLoad(width) result.SysLoad = NewModelSysLoad(width)
result.ProcessInfo = NewModelProcessInfo(width) result.ProcessInfo = NewModelProcessInfo(width)
result.actionMsg = &ActionMsg{}
return result return result
} }
...@@ -90,6 +113,24 @@ func (m *ModelMain) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) { ...@@ -90,6 +113,24 @@ func (m *ModelMain) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) {
switch msg.String() { switch msg.String() {
case "ctrl+c", "q": case "ctrl+c", "q":
return m, tea.Quit return m, tea.Quit
case "up":
cmd := m.handleKeyUp()
return m, cmd
case "down":
cmd := m.handleKeyDown()
return m, cmd
case "enter":
return m, tea.Quit
case "h":
return m, tea.Quit
case "k":
return m, tea.Quit
case "esc":
cmd := m.handleKeyEsc()
return m, cmd
case " ":
cmd := m.handleKeySpace()
return m, cmd
} }
case TickMsg: // 定时事件 case TickMsg: // 定时事件
updateModelInfo(m.modelMsg, time.Time(msg)) updateModelInfo(m.modelMsg, time.Time(msg))
...@@ -127,6 +168,28 @@ func (m *ModelMain) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) { ...@@ -127,6 +168,28 @@ func (m *ModelMain) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) {
return m, nil return m, nil
} }
func (m *ModelMain) handleKeyEsc() tea.Cmd {
return nil
}
func (m *ModelMain) handleKeySpace() tea.Cmd {
if m.actionMsg == nil || m.actionMsg.PointPid == nil {
return nil
}
if m.actionMsg.SelectPids == nil {
m.actionMsg.SelectPids = make(map[int32]bool)
}
_, have := m.actionMsg.SelectPids[*m.actionMsg.PointPid]
if have {
delete(m.actionMsg.SelectPids, *m.actionMsg.PointPid)
} else {
m.actionMsg.SelectPids[*m.actionMsg.PointPid] = true
}
m1, cmd1 := m.ProcessInfo.Update(m.actionMsg)
m.ProcessInfo = m1.(*ModelProcessInfo)
return cmd1
}
func (m *ModelMain) View() string { func (m *ModelMain) View() string {
return m.Header.View() + m.DCUInfo.View() + m.SysLoad.View() + m.ProcessInfo.View() + "\n" return m.Header.View() + m.DCUInfo.View() + m.SysLoad.View() + m.ProcessInfo.View() + "\n"
} }
...@@ -185,3 +248,100 @@ func updateModelInfo(modelMsg *ModelMsg, t time.Time) error { ...@@ -185,3 +248,100 @@ func updateModelInfo(modelMsg *ModelMsg, t time.Time) error {
} }
return nil return nil
} }
func (m *ModelMain) handleKeyUp() tea.Cmd {
if m.actionMsg == nil {
m.actionMsg = &ActionMsg{}
}
if m.modelMsg.DCUPidInfo == nil {
return nil
}
processes := make([]backend.DCUProcessInfo, 0)
for index := range 64 {
p, have := m.modelMsg.DCUPidInfo[index]
if have && len(p) > 0 {
processes = append(processes, p...)
}
}
processNum := len(processes)
if processNum == 0 {
return nil
}
index := 0
if m.actionMsg.PointPid == nil {
// 获取列表中的最后一个进程的pid
index = processNum - 1
} else {
var targetIndex = -1
for l := processNum - 1; l >= 0; l-- {
if processes[l].Info.Pid == *m.actionMsg.PointPid {
targetIndex = l - 1
break
}
}
if targetIndex == -1 {
index = processNum - 1
} else {
index = targetIndex
}
}
pid := processes[index].Info.Pid
m.actionMsg.PointPid = &pid
idx := processes[index].DCU
m.actionMsg.TargetDCUIndex = &idx
m1, cmd1 := m.ProcessInfo.Update(m.actionMsg)
m2, cmd2 := m.DCUInfo.Update(m.actionMsg)
m.ProcessInfo = m1.(*ModelProcessInfo)
m.DCUInfo = m2.(*ModelDCUInfo)
return tea.Batch(cmd1, cmd2)
}
func (m *ModelMain) handleKeyDown() tea.Cmd {
if m.actionMsg == nil {
m.actionMsg = &ActionMsg{}
}
if m.modelMsg.DCUPidInfo == nil {
return nil
}
processes := make([]backend.DCUProcessInfo, 0)
for index := range 64 {
p, have := m.modelMsg.DCUPidInfo[index]
if have && len(p) > 0 {
processes = append(processes, p...)
}
}
processNum := len(processes)
if processNum == 0 {
return nil
}
index := 0
if m.actionMsg.PointPid == nil {
index = 0
} else {
var targetIndex = -1
for l := 0; l < processNum-1; l++ {
if processes[l].Info.Pid == *m.actionMsg.PointPid {
targetIndex = l + 1
if targetIndex >= processNum {
targetIndex = 0
}
break
}
}
if targetIndex == -1 {
index = 0
} else {
index = targetIndex
}
}
pid := processes[index].Info.Pid
m.actionMsg.PointPid = &pid
idx := processes[index].DCU
m.actionMsg.TargetDCUIndex = &idx
m1, cmd1 := m.ProcessInfo.Update(m.actionMsg)
m2, cmd2 := m.DCUInfo.Update(m.actionMsg)
m.ProcessInfo = m1.(*ModelProcessInfo)
m.DCUInfo = m2.(*ModelDCUInfo)
return tea.Batch(cmd1, cmd2)
}
...@@ -20,6 +20,7 @@ type ModelProcessInfo struct { ...@@ -20,6 +20,7 @@ type ModelProcessInfo struct {
width int width int
style lipgloss.Style style lipgloss.Style
modMsg *ModelMsg modMsg *ModelMsg
actionMsg *ActionMsg
} }
const ( const (
...@@ -61,8 +62,13 @@ func (m *ModelProcessInfo) Init() tea.Cmd { ...@@ -61,8 +62,13 @@ func (m *ModelProcessInfo) Init() tea.Cmd {
func (m *ModelProcessInfo) View() string { func (m *ModelProcessInfo) View() string {
haveProcess := false haveProcess := false
var heightLightPid int32 = 0
if m.actionMsg != nil && m.actionMsg.PointPid != nil {
heightLightPid = *m.actionMsg.PointPid
}
lines := make([]string, 0) lines := make([]string, 0)
sb := strings.Builder{} sb := strings.Builder{}
sbInner := strings.Builder{}
for index := range 64 { for index := range 64 {
processes, have := m.Cache[index] processes, have := m.Cache[index]
if !have { if !have {
...@@ -71,38 +77,61 @@ func (m *ModelProcessInfo) View() string { ...@@ -71,38 +77,61 @@ func (m *ModelProcessInfo) View() string {
for _, process := range processes { for _, process := range processes {
haveProcess = true haveProcess = true
sb.WriteString(myBorder.Left) sb.WriteString(myBorder.Left)
sb.WriteString(FormatStr(fmt.Sprintf("%d", process.DCU), 4, lipgloss.Right))
sb.WriteByte(' ') sbInner.WriteString(FormatStr(fmt.Sprintf("%d", process.DCU), 4, lipgloss.Right))
sb.WriteString(FormatStr(fmt.Sprintf("%d", process.Info.Pid), 7, lipgloss.Right)) sbInner.WriteByte(' ')
sb.WriteByte(' ') sbInner.WriteString(FormatStr(fmt.Sprintf("%d", process.Info.Pid), 7, lipgloss.Right))
sb.WriteString(FormatStr(process.Info.User, 8, lipgloss.Right)) sbInner.WriteByte(' ')
sb.WriteByte(' ') sbInner.WriteString(FormatStr(process.Info.User, 8, lipgloss.Right))
sb.WriteString(FormatStr(process.DCUMem, 8, lipgloss.Right)) sbInner.WriteByte(' ')
sb.WriteByte(' ') sbInner.WriteString(FormatStr(process.DCUMem, 8, lipgloss.Right))
sb.WriteString(FormatStr(fmt.Sprintf("%d", process.SDMA), 4, lipgloss.Right)) sbInner.WriteByte(' ')
sb.WriteByte(' ') sbInner.WriteString(FormatStr(fmt.Sprintf("%d", process.SDMA), 4, lipgloss.Right))
sb.WriteString(FormatStr(fmt.Sprintf("%.1f", process.Info.CPU), 5, lipgloss.Right)) sbInner.WriteByte(' ')
sb.WriteByte(' ') sbInner.WriteString(FormatStr(fmt.Sprintf("%.1f", process.Info.CPU), 5, lipgloss.Right))
sb.WriteString(FormatStr(fmt.Sprintf("%.1f", process.Info.Mem), 5, lipgloss.Right)) sbInner.WriteByte(' ')
sb.WriteByte(' ') sbInner.WriteString(FormatStr(fmt.Sprintf("%.1f", process.Info.Mem), 5, lipgloss.Right))
sb.WriteString(FormatStr(process.Info.Time, 9, lipgloss.Right)) sbInner.WriteByte(' ')
sb.WriteByte(' ') sbInner.WriteString(FormatStr(process.Info.Time, 9, lipgloss.Right))
sbInner.WriteByte(' ')
if process.Info.ContInfo != nil { if process.Info.ContInfo != nil {
sb.WriteString(FormatStr(process.Info.ContInfo.Name, 20, lipgloss.Left)) sbInner.WriteString(FormatStr(process.Info.ContInfo.Name, 20, lipgloss.Left))
} else { } else {
sb.WriteString(FormatStr(" - ", 20, lipgloss.Right)) sbInner.WriteString(FormatStr(" - ", 20, lipgloss.Right))
} }
sb.WriteByte(' ') sbInner.WriteByte(' ')
w := m.width - lipgloss.Width(sb.String()) - 2 w := m.width - lipgloss.Width(sbInner.String()) - 3
tw := lipgloss.Width(process.Info.Cmd) tw := lipgloss.Width(process.Info.Cmd)
if w >= tw { if w >= tw {
sb.WriteString(process.Info.Cmd) sbInner.WriteString(process.Info.Cmd)
sb.WriteString(strings.Repeat(" ", w-tw)) sbInner.WriteString(strings.Repeat(" ", w-tw))
} else { } else {
sb.WriteString(FormatStr(process.Info.Cmd, w-2, lipgloss.Left)) sbInner.WriteString(FormatStr(process.Info.Cmd, w-1, lipgloss.Left))
sb.WriteString("..") sbInner.WriteString("..")
} }
sb.WriteByte(' ') sbInner.WriteByte(' ')
selected := false
if m.actionMsg != nil && m.actionMsg.SelectPids != nil {
b, have := m.actionMsg.SelectPids[process.Info.Pid]
if have && b {
selected = true
}
}
if heightLightPid == process.Info.Pid {
if selected {
sb.WriteString(HeightSelectedStyle.Render(sbInner.String()))
} else {
sb.WriteString(HeightLightStyle.Render(sbInner.String()))
}
} else {
if selected {
sb.WriteString(SelectedStyle.Render(sbInner.String()))
} else {
sb.WriteString(sbInner.String())
}
}
sbInner.Reset()
sb.WriteString(myBorder.Right) sb.WriteString(myBorder.Right)
sb.WriteByte('\n') sb.WriteByte('\n')
lines = append(lines, sb.String()) lines = append(lines, sb.String())
...@@ -131,6 +160,9 @@ func (m *ModelProcessInfo) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) { ...@@ -131,6 +160,9 @@ func (m *ModelProcessInfo) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) {
maps.Copy(m.Cache, msg.DCUPidInfo) maps.Copy(m.Cache, msg.DCUPidInfo)
m.modMsg = msg m.modMsg = msg
return m, nil return m, nil
case *ActionMsg:
m.actionMsg = msg
return m, nil
} }
return m, nil return m, nil
} }
...@@ -35,8 +35,10 @@ type ModelSysLoad struct { ...@@ -35,8 +35,10 @@ type ModelSysLoad struct {
topLine string topLine string
bottomLine string bottomLine string
style lipgloss.Style style lipgloss.Style
width int // 组件总宽度 width int // 组件总宽度
colors []color.Color colors []color.Color // 时序图的颜色表
actionMsg *ActionMsg // 动作消息
modelMsg *ModelMsg // 模型周期性消息
} }
type SysLoadInfo struct { type SysLoadInfo struct {
...@@ -145,7 +147,12 @@ func (m *ModelSysLoad) init() [6]time.Time { ...@@ -145,7 +147,12 @@ func (m *ModelSysLoad) init() [6]time.Time {
func (m *ModelSysLoad) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) { func (m *ModelSysLoad) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := inputMsg.(type) { switch msg := inputMsg.(type) {
case *ModelMsg: case *ModelMsg:
m.modelMsg = msg
m.updateInfo(msg) m.updateInfo(msg)
return m, nil
case *ActionMsg:
m.actionMsg = msg
return m, nil return m, nil
} }
return m, nil return m, nil
...@@ -196,8 +203,6 @@ func (m *ModelSysLoad) updateInfo(t *ModelMsg) { ...@@ -196,8 +203,6 @@ func (m *ModelSysLoad) updateInfo(t *ModelMsg) {
s.DCUMemUsageAvg, s.DCUUsageAvg = 0, 0 s.DCUMemUsageAvg, s.DCUUsageAvg = 0, 0
qinfo, lock := t.DCUInfo.GetQuitInfo() qinfo, lock := t.DCUInfo.GetQuitInfo()
defer lock.Unlock()
for k, v := range qinfo { for k, v := range qinfo {
s.DCUMemUsageAvg += v.MemUsedPerent s.DCUMemUsageAvg += v.MemUsedPerent
s.DCUMemUsage[k] = v.MemUsedPerent s.DCUMemUsage[k] = v.MemUsedPerent
...@@ -205,6 +210,7 @@ func (m *ModelSysLoad) updateInfo(t *ModelMsg) { ...@@ -205,6 +210,7 @@ func (m *ModelSysLoad) updateInfo(t *ModelMsg) {
s.DCUUsage[k] = v.DCUUTil s.DCUUsage[k] = v.DCUUTil
} }
l := len(qinfo) l := len(qinfo)
lock.Unlock()
s.DCUMemUsageAvg /= float32(l) s.DCUMemUsageAvg /= float32(l)
s.DCUUsageAvg /= float32(l) s.DCUUsageAvg /= float32(l)
m.current = &s m.current = &s
......
...@@ -192,6 +192,9 @@ func (m *MyTimeChart) View() string { ...@@ -192,6 +192,9 @@ func (m *MyTimeChart) View() string {
case utils.CharFull: case utils.CharFull:
runes[line][col] = utils.FullMW runes[line][col] = utils.FullMW
} }
if t, have := utils.MM[runes[line][col]]; have {
runes[line][col] = t
}
case utils.CharLeft: case utils.CharLeft:
switch utils.CharTypeOr(charStat, utils.CharLeft) { switch utils.CharTypeOr(charStat, utils.CharLeft) {
case utils.CharLeft: case utils.CharLeft:
...@@ -202,6 +205,9 @@ func (m *MyTimeChart) View() string { ...@@ -202,6 +205,9 @@ func (m *MyTimeChart) View() string {
runes[line][col] = utils.FullMW runes[line][col] = utils.FullMW
} }
charStat = utils.CharTypeOr(charStat, utils.CharLeft) charStat = utils.CharTypeOr(charStat, utils.CharLeft)
if t, have := utils.MM[runes[line][col]]; have {
runes[line][col] = t
}
case utils.CharRight: case utils.CharRight:
switch utils.CharTypeOr(charStat, utils.CharRight) { switch utils.CharTypeOr(charStat, utils.CharRight) {
case utils.CharLeft: case utils.CharLeft:
...@@ -212,8 +218,14 @@ func (m *MyTimeChart) View() string { ...@@ -212,8 +218,14 @@ func (m *MyTimeChart) View() string {
runes[line][col] = utils.FullMW runes[line][col] = utils.FullMW
} }
charStat = utils.CharTypeOr(charStat, utils.CharRight) charStat = utils.CharTypeOr(charStat, utils.CharRight)
if t, have := utils.MM[runes[line][col]]; have {
runes[line][col] = t
}
case utils.CharFull: case utils.CharFull:
charStat = utils.CharFull charStat = utils.CharFull
if t, have := utils.MM[runes[line][col]]; have {
runes[line][col] = t
}
} }
} }
......
...@@ -462,7 +462,6 @@ type DCUPidInfo struct { ...@@ -462,7 +462,6 @@ type DCUPidInfo struct {
} }
// GetDCUPidInfo 获取Pid相关信息 // GetDCUPidInfo 获取Pid相关信息
// 需要剔除PCIBus为空的项
func GetDCUPidInfo() ([]DCUPidInfo, error) { func GetDCUPidInfo() ([]DCUPidInfo, error) {
output, err := exec.Command(DCUBinaryFile, "--showpids").Output() output, err := exec.Command(DCUBinaryFile, "--showpids").Output()
if err != nil { if err != nil {
......
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