Commit 10bfd381 authored by liming6's avatar liming6
Browse files

fix 添加空值判断,提高稳定性

parent 51496f87
...@@ -3,6 +3,8 @@ package backend ...@@ -3,6 +3,8 @@ package backend
import ( import (
"testing" "testing"
"time" "time"
"github.com/samber/mo"
) )
func TestDcoker(t *testing.T) { func TestDcoker(t *testing.T) {
...@@ -90,3 +92,9 @@ func BenchmarkUpdateSlowInfo(b *testing.B) { ...@@ -90,3 +92,9 @@ func BenchmarkUpdateSlowInfo(b *testing.B) {
} }
} }
} }
func TestOpt(t *testing.T) {
o := mo.Option[int]{}
t.Log(o.IsNone())
}
\ No newline at end of file
...@@ -15,6 +15,7 @@ import ( ...@@ -15,6 +15,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/samber/mo"
"github.com/shirou/gopsutil/v3/process" "github.com/shirou/gopsutil/v3/process"
) )
...@@ -85,17 +86,17 @@ func Shutdown() { ...@@ -85,17 +86,17 @@ func Shutdown() {
type DCUQuickInfo struct { type DCUQuickInfo struct {
lock sync.RWMutex lock sync.RWMutex
Id int // Id int //
Name string // Name mo.Option[string] //
PerformanceLevel string // PerformanceLevel mo.Option[string] //
Fan string // Fan mo.Option[string] //
Temp float32 // Temp mo.Option[float32] //
PwrAvg float32 // PwrAvg mo.Option[float32] //
PwrCap float32 // PwrCap mo.Option[float32] //
BusId string // BusId mo.Option[string] //
MemTotal uint64 // MemTotal mo.Option[uint64] //
MemUsed uint64 // MemUsed mo.Option[uint64] //
MemUsedPerent float32 // MemUsedPerent mo.Option[float32] //
DCUUTil float32 // DCUUTil mo.Option[float32] //
} }
type DCUSlowInfo struct { type DCUSlowInfo struct {
...@@ -122,46 +123,16 @@ func (m *DCUInfoMap) UpdateQuickInfo() error { ...@@ -122,46 +123,16 @@ func (m *DCUInfoMap) UpdateQuickInfo() error {
if err != nil { if err != nil {
return err return err
} }
names, err := Rocmlib.GetDevName() names, _ := Rocmlib.GetDevName()
if err != nil { plevel, _ := Rocmlib.GetPerfLevel()
return err fan, _ := Rocmlib.GetFanSpeed()
} temp, _ := Rocmlib.GetTemp()
plevel, err := Rocmlib.GetPerfLevel() pwrAvg, _ := Rocmlib.GetPowerAvg()
if err != nil { pwrCap, _ := Rocmlib.GetPowerCap()
return err busid, _ := Rocmlib.GetPCIBusId()
} memTotal, _ := Rocmlib.GetMemTotal()
fan, err := Rocmlib.GetFanSpeed() memUsed, _ := Rocmlib.GetMemUsed()
if err != nil { dcu, _ := Rocmlib.GetBusyPercent()
return err
}
temp, err := Rocmlib.GetTemp()
if err != nil {
return err
}
pwrAvg, err := Rocmlib.GetPowerAvg()
if err != nil {
return err
}
pwrCap, err := Rocmlib.GetPowerCap()
if err != nil {
return err
}
busid, err := Rocmlib.GetPCIBusId()
if err != nil {
return err
}
memTotal, err := Rocmlib.GetMemTotal()
if err != nil {
return err
}
memUsed, err := Rocmlib.GetMemUsed()
if err != nil {
return err
}
dcu, err := Rocmlib.GetBusyPercent()
if err != nil {
return err
}
set := make(map[int]bool) set := make(map[int]bool)
...@@ -176,25 +147,51 @@ func (m *DCUInfoMap) UpdateQuickInfo() error { ...@@ -176,25 +147,51 @@ func (m *DCUInfoMap) UpdateQuickInfo() error {
} }
qinfo.lock.Lock() qinfo.lock.Lock()
qinfo.Id = i qinfo.Id = i
qinfo.Name = names[i] if names != nil {
qinfo.PerformanceLevel = plevel[i] qinfo.Name = mo.Some(names[i])
}
if plevel != nil {
qinfo.PerformanceLevel = mo.Some(plevel[i])
}
if fan != nil {
if rpm, have := fan[i]; !have || rpm == 0 { if rpm, have := fan[i]; !have || rpm == 0 {
qinfo.Fan = "N/A" qinfo.Fan = mo.Some("N/A")
} else { } else {
qinfo.Fan = strconv.Itoa(int(rpm)) qinfo.Fan = mo.Some(strconv.Itoa(int(rpm)))
} }
qinfo.Temp = float32(temp[i]) / 1000 }
qinfo.PwrAvg = float32(pwrAvg[i]) / 1000000 if temp != nil {
qinfo.PwrCap = float32(pwrCap[i]) / 1000000 qinfo.Temp = mo.Some(float32(temp[i]) / 1000)
qinfo.BusId = busid[i] }
qinfo.MemTotal = memTotal[i] if pwrAvg != nil {
qinfo.MemUsed = memUsed[i] qinfo.PwrAvg = mo.Some(float32(pwrAvg[i]) / 1000000)
if qinfo.MemTotal == 0 { }
qinfo.MemUsedPerent = 0 if pwrCap != nil {
qinfo.PwrCap = mo.Some(float32(pwrCap[i]) / 1000000)
}
if busid != nil {
qinfo.BusId = mo.Some(busid[i])
}
if memTotal != nil {
qinfo.MemTotal = mo.Some(memTotal[i])
}
if memUsed != nil {
qinfo.MemUsed = mo.Some(memUsed[i])
}
if qinfo.MemTotal.IsSome() {
if qinfo.MemTotal.MustGet() == 0 {
qinfo.MemUsedPerent = mo.Some(float32(0.0))
} else { } else {
qinfo.MemUsedPerent = float32(qinfo.MemUsed) / float32(qinfo.MemTotal) * 100 if qinfo.MemUsed.IsSome() {
qinfo.MemUsedPerent = mo.Some(float32(qinfo.MemUsed.MustGet()) / float32(qinfo.MemTotal.MustGet()) * 100)
}
} }
qinfo.DCUUTil = float32(dcu[i]) }
if dcu != nil {
qinfo.DCUUTil = mo.Some(float32(dcu[i]))
}
qinfo.lock.Unlock() qinfo.lock.Unlock()
set[i] = true set[i] = true
} }
...@@ -215,7 +212,12 @@ func (m *DCUInfoMap) UpdateSlowInfo() error { ...@@ -215,7 +212,12 @@ func (m *DCUInfoMap) UpdateSlowInfo() error {
} }
ecc, err := gpu.GetEccInfo() ecc, err := gpu.GetEccInfo()
if err != nil { if err != nil {
return err ecc = make(map[int]bool)
for i := range num {
ecc[i] = false
}
err = nil
// return err
} }
rinfo, err := gpu.GetRunningInfo() rinfo, err := gpu.GetRunningInfo()
if err != nil { if err != nil {
......
package main package main
import ( import (
"fmt"
"get-container/cmd/hytop/backend" "get-container/cmd/hytop/backend"
"get-container/cmd/hytop/tui" "get-container/cmd/hytop/tui"
"log" "log"
...@@ -8,9 +9,29 @@ import ( ...@@ -8,9 +9,29 @@ import (
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/x/term" "github.com/charmbracelet/x/term"
"github.com/spf13/pflag"
)
var (
flagHelp = pflag.BoolP("help", "h", false, "show help info of hytop")
flagVersion = pflag.BoolP("version", "v", false, "show version info of hytop")
) )
func main() { func main() {
pflag.Parse()
if *flagVersion {
fmt.Printf("hytop version: %s\n", tui.DCUTopVersion)
os.Exit(0)
}
if *flagHelp {
fmt.Println("hytop: a tool that allows viewing the operation status of DCU from the command line")
fmt.Println("Usage of hytop:")
fmt.Println(" hytop [option]")
fmt.Println("options: ")
pflag.PrintDefaults()
os.Exit(0)
}
w, h, err := term.GetSize(os.Stdout.Fd()) w, h, err := term.GetSize(os.Stdout.Fd())
if err != nil { if err != nil {
log.Fatalf("error get terminal size: %v", err) log.Fatalf("error get terminal size: %v", err)
......
...@@ -2,14 +2,20 @@ package tui ...@@ -2,14 +2,20 @@ package tui
const ( const (
HelpStr = ` HelpStr = `
hytop 1.0.0 - (C) Ming Li, 2025-2025. hytop 1.0.1 - (C) Ming Li, 2025-2026.
Released under the GNU GPLv3 License. Released under the GNU GPLv3 License.
hytop is a tool for monitoring DCUs from the command line. hytop is a tool for monitoring DCUs from the command line.
Button function introduction: Button function introduction:
h: show help info h : show help info
q : exit
Esc : go back or cancel all selected processes
Enter: enter the process view of the process where the cursor is located, or indicate confirmation
Space: select or unselect a process
up / down / left / right: move the cursor
(Press Esc to go back)
` `
) )
...@@ -113,9 +113,9 @@ func (m *ModelDCUInfo) View() string { ...@@ -113,9 +113,9 @@ func (m *ModelDCUInfo) View() string {
strCache.WriteByte(' ') strCache.WriteByte(' ')
strCache.WriteString(FormatStr(strconv.Itoa(qinfo.Id), 4, lipgloss.Left)) strCache.WriteString(FormatStr(strconv.Itoa(qinfo.Id), 4, lipgloss.Left))
strCache.WriteByte(' ') strCache.WriteByte(' ')
strCache.WriteString(FormatStr(ReDCUName.FindString(qinfo.Name), 8, lipgloss.Left)) strCache.WriteString(FormatStr(ReDCUName.FindString(qinfo.Name.OrElse("Unknow")), 8, lipgloss.Left))
strCache.WriteByte(' ') strCache.WriteByte(' ')
strCache.WriteString(FormatStr(qinfo.PerformanceLevel, 15, lipgloss.Right)) strCache.WriteString(FormatStr(qinfo.PerformanceLevel.OrElse("Unknow"), 15, lipgloss.Right))
strCache.WriteByte(' ') strCache.WriteByte(' ')
if isLowStyle { if isLowStyle {
...@@ -128,7 +128,7 @@ func (m *ModelDCUInfo) View() string { ...@@ -128,7 +128,7 @@ func (m *ModelDCUInfo) View() string {
strBuilder.WriteString(borderStr) strBuilder.WriteString(borderStr)
strCache.WriteByte(' ') strCache.WriteByte(' ')
strCache.WriteString(FormatStr(qinfo.BusId, 13, lipgloss.Left)) strCache.WriteString(FormatStr(qinfo.BusId.OrElse("Unknow"), 13, lipgloss.Left))
strCache.WriteByte(' ') strCache.WriteByte(' ')
strCache.WriteString(FormatStr("Off", 6, lipgloss.Right)) strCache.WriteString(FormatStr("Off", 6, lipgloss.Right))
strCache.WriteByte(' ') strCache.WriteByte(' ')
...@@ -161,23 +161,32 @@ func (m *ModelDCUInfo) View() string { ...@@ -161,23 +161,32 @@ func (m *ModelDCUInfo) View() string {
if isLowStyle { if isLowStyle {
strBuilder.WriteString(LowLeightStyle.Render(" DCU: ")) strBuilder.WriteString(LowLeightStyle.Render(" DCU: "))
strBuilder.WriteString(m.proLowLeight.ViewAs(float64(qinfo.DCUUTil / 100))) strBuilder.WriteString(m.proLowLeight.ViewAs(float64(qinfo.DCUUTil.OrElse(0.0) / 100)))
strBuilder.WriteString(LowLeightStyle.Render(fmt.Sprintf(" %3d%% ", int(qinfo.DCUUTil)))) strBuilder.WriteString(LowLeightStyle.Render(fmt.Sprintf(" %3d%% ", int(qinfo.DCUUTil.OrElse(0.0)))))
} else { } else {
strBuilder.WriteString(" DCU: ") strBuilder.WriteString(" DCU: ")
strBuilder.WriteString(m.pro.ViewAs(float64(qinfo.DCUUTil / 100))) strBuilder.WriteString(m.pro.ViewAs(float64(qinfo.DCUUTil.OrElse(0.0) / 100)))
strBuilder.WriteString(fmt.Sprintf(" %3d%% ", int(qinfo.DCUUTil))) strBuilder.WriteString(fmt.Sprintf(" %3d%% ", int(qinfo.DCUUTil.OrElse(0.0))))
} }
strBuilder.WriteString(borderStr) strBuilder.WriteString(borderStr)
strBuilder.WriteByte('\n') strBuilder.WriteByte('\n')
strBuilder.WriteString(borderStr) strBuilder.WriteString(borderStr)
strCache.WriteByte(' ') strCache.WriteByte(' ')
strCache.WriteString(FormatStr(qinfo.Fan, 4, lipgloss.Left)) strCache.WriteString(FormatStr(qinfo.Fan.OrElse("N/A"), 4, lipgloss.Left))
strCache.WriteByte(' ') strCache.WriteByte(' ')
strCache.WriteString(FormatStr(fmt.Sprintf("%.1fC", qinfo.Temp), 6, lipgloss.Left)) if qinfo.Temp.IsSome() {
temp := qinfo.Temp.MustGet()
if temp == 0 {
strCache.WriteString(FormatStr("N/A", 6, lipgloss.Left))
} else {
strCache.WriteString(FormatStr(fmt.Sprintf("%.1f°C", temp), 6, lipgloss.Left))
}
} else {
strCache.WriteString(FormatStr("N/A", 6, lipgloss.Left))
}
strCache.WriteByte(' ') strCache.WriteByte(' ')
strCache.WriteString(FormatStr(fmt.Sprintf("%.1fW / %.1fW", qinfo.PwrAvg, qinfo.PwrCap), 17, lipgloss.Right)) strCache.WriteString(FormatStr(fmt.Sprintf("%.1fW / %.1fW", qinfo.PwrAvg.OrElse(0.0), qinfo.PwrCap.OrElse(0.0)), 17, lipgloss.Right))
strCache.WriteByte(' ') strCache.WriteByte(' ')
if isLowStyle { if isLowStyle {
...@@ -191,13 +200,13 @@ func (m *ModelDCUInfo) View() string { ...@@ -191,13 +200,13 @@ func (m *ModelDCUInfo) View() string {
if isLowStyle { if isLowStyle {
strCache.WriteByte(' ') strCache.WriteByte(' ')
strCache.WriteString(FormatStr(fmt.Sprintf("%dMiB / %dMiB", qinfo.MemUsed/uint64(utils.MiB), qinfo.MemTotal/uint64(utils.MiB)), 20, lipgloss.Right)) strCache.WriteString(FormatStr(fmt.Sprintf("%dMiB / %dMiB", qinfo.MemUsed.OrElse(0)/uint64(utils.MiB), qinfo.MemTotal.OrElse(0)/uint64(utils.MiB)), 20, lipgloss.Right))
strCache.WriteByte(' ') strCache.WriteByte(' ')
strBuilder.WriteString(LowLeightStyle.Render(strCache.String())) strBuilder.WriteString(LowLeightStyle.Render(strCache.String()))
strCache.Reset() strCache.Reset()
} else { } else {
strBuilder.WriteByte(' ') strBuilder.WriteByte(' ')
strBuilder.WriteString(FormatStr(fmt.Sprintf("%dMiB / %dMiB", qinfo.MemUsed/uint64(utils.MiB), qinfo.MemTotal/uint64(utils.MiB)), 20, lipgloss.Right)) strBuilder.WriteString(FormatStr(fmt.Sprintf("%dMiB / %dMiB", qinfo.MemUsed.OrElse(0)/uint64(utils.MiB), qinfo.MemTotal.OrElse(0)/uint64(utils.MiB)), 20, lipgloss.Right))
strBuilder.WriteByte(' ') strBuilder.WriteByte(' ')
} }
...@@ -205,7 +214,7 @@ func (m *ModelDCUInfo) View() string { ...@@ -205,7 +214,7 @@ func (m *ModelDCUInfo) View() string {
if isLowStyle { if isLowStyle {
strCache.WriteByte(' ') strCache.WriteByte(' ')
strCache.WriteString(FormatStr(fmt.Sprintf("%.1f%%", qinfo.DCUUTil), 6, lipgloss.Left)) strCache.WriteString(FormatStr(fmt.Sprintf("%.1f%%", qinfo.DCUUTil.OrElse(0)), 6, lipgloss.Left))
strCache.WriteByte(' ') strCache.WriteByte(' ')
strCache.WriteString(FormatStr(sinfo.PwrMode.Load().(string), 13, lipgloss.Right)) strCache.WriteString(FormatStr(sinfo.PwrMode.Load().(string), 13, lipgloss.Right))
strCache.WriteByte(' ') strCache.WriteByte(' ')
...@@ -213,7 +222,7 @@ func (m *ModelDCUInfo) View() string { ...@@ -213,7 +222,7 @@ func (m *ModelDCUInfo) View() string {
strCache.Reset() strCache.Reset()
} else { } else {
strBuilder.WriteByte(' ') strBuilder.WriteByte(' ')
strBuilder.WriteString(FormatStr(fmt.Sprintf("%.1f%%", qinfo.DCUUTil), 6, lipgloss.Left)) strBuilder.WriteString(FormatStr(fmt.Sprintf("%.1f%%", qinfo.DCUUTil.OrElse(0)), 6, lipgloss.Left))
strBuilder.WriteByte(' ') strBuilder.WriteByte(' ')
strBuilder.WriteString(FormatStr(sinfo.PwrMode.Load().(string), 13, lipgloss.Right)) strBuilder.WriteString(FormatStr(sinfo.PwrMode.Load().(string), 13, lipgloss.Right))
strBuilder.WriteByte(' ') strBuilder.WriteByte(' ')
...@@ -223,15 +232,15 @@ func (m *ModelDCUInfo) View() string { ...@@ -223,15 +232,15 @@ func (m *ModelDCUInfo) View() string {
if isLowStyle { if isLowStyle {
strCache.WriteString(" Mem: ") strCache.WriteString(" Mem: ")
strCache.WriteString(m.proLowLeight.ViewAs(float64(qinfo.MemUsed) / float64(qinfo.MemTotal))) strCache.WriteString(m.proLowLeight.ViewAs(float64(qinfo.MemUsed.OrElse(0)) / float64(qinfo.MemTotal.OrElse(1))))
strCache.WriteString(LowLeightStyle.Render(fmt.Sprintf(" %3d%% ", int(100*float64(qinfo.MemUsed)/float64(qinfo.MemTotal))))) strCache.WriteString(LowLeightStyle.Render(fmt.Sprintf(" %3d%% ", int(100*float64(qinfo.MemUsed.OrElse(0))/float64(qinfo.MemTotal.OrElse(1))))))
strBuilder.WriteString(LowLeightStyle.Render(strCache.String())) strBuilder.WriteString(LowLeightStyle.Render(strCache.String()))
strCache.Reset() strCache.Reset()
} else { } else {
strBuilder.WriteString(" Mem: ") strBuilder.WriteString(" Mem: ")
strBuilder.WriteString(m.pro.ViewAs(float64(qinfo.MemUsed) / float64(qinfo.MemTotal))) strBuilder.WriteString(m.pro.ViewAs(float64(qinfo.MemUsed.OrElse(0)) / float64(qinfo.MemTotal.OrElse(1))))
strBuilder.WriteByte(' ') strBuilder.WriteByte(' ')
strBuilder.WriteString(fmt.Sprintf("%3d%%", int(100*float64(qinfo.MemUsed)/float64(qinfo.MemTotal)))) strBuilder.WriteString(fmt.Sprintf("%3d%%", int(100*float64(qinfo.MemUsed.OrElse(0))/float64(qinfo.MemTotal.OrElse(1)))))
strBuilder.WriteByte(' ') strBuilder.WriteByte(' ')
} }
strBuilder.WriteString(borderStr) strBuilder.WriteString(borderStr)
......
...@@ -13,7 +13,7 @@ import ( ...@@ -13,7 +13,7 @@ import (
) )
const ( const (
DCUTopVersion = "1.0.0" DCUTopVersion = "1.0.1"
) )
var ( var (
...@@ -65,7 +65,6 @@ const ( ...@@ -65,7 +65,6 @@ const (
VMTree ViewMode = 1 // 进程树视图 VMTree ViewMode = 1 // 进程树视图
VMOneProcess ViewMode = 2 // 进程详情视图 VMOneProcess ViewMode = 2 // 进程详情视图
VMProcessEnv ViewMode = 3 // 进程环境变量视图 VMProcessEnv ViewMode = 3 // 进程环境变量视图
VMHelp ViewMode = 4 // 帮助视图
) )
func (pa ProcessAction) String() string { func (pa ProcessAction) String() string {
...@@ -105,6 +104,7 @@ type ActionMsg struct { ...@@ -105,6 +104,7 @@ type ActionMsg struct {
PidEnvView *int32 // 进程环境变量视图的pid号,为null表示不进入进程环境变量视图 PidEnvView *int32 // 进程环境变量视图的pid号,为null表示不进入进程环境变量视图
PidTreePids []int32 // pid tree视图下,进程id的顺序列表 PidTreePids []int32 // pid tree视图下,进程id的顺序列表
TargetDCUIndex int // PointPid使用的dcu index,为-1表示没有选择任何dcu TargetDCUIndex int // PointPid使用的dcu index,为-1表示没有选择任何dcu
HelpView bool // 是否进入帮助界面
} }
// ModelMain tui主模型类 // ModelMain tui主模型类
...@@ -202,7 +202,8 @@ func (m *ModelMain) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) { ...@@ -202,7 +202,8 @@ func (m *ModelMain) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) {
cmd := m.handleKeyEnter() cmd := m.handleKeyEnter()
return m, cmd return m, cmd
case "h": case "h":
return m, tea.Quit m.actionMsg.HelpView = true
return m, nil
case "left", "right": case "left", "right":
cmd := m.handleKeyLR(msg.String()) cmd := m.handleKeyLR(msg.String())
return m, cmd return m, cmd
...@@ -462,6 +463,10 @@ func (m *ModelMain) handleKeyK() tea.Cmd { ...@@ -462,6 +463,10 @@ func (m *ModelMain) handleKeyK() tea.Cmd {
// VMMain视图下,取消所有选择的进程、退出单个进程模式或对话框返回 // VMMain视图下,取消所有选择的进程、退出单个进程模式或对话框返回
// VMTree视图下,取消所有选择的进程、退出单个进程模式或对话框返回,返回到VMMain视图 // VMTree视图下,取消所有选择的进程、退出单个进程模式或对话框返回,返回到VMMain视图
func (m *ModelMain) handleKeyEsc() tea.Cmd { func (m *ModelMain) handleKeyEsc() tea.Cmd {
if m.actionMsg.HelpView {
m.actionMsg.HelpView = false
return nil
}
switch m.actionMsg.VM { switch m.actionMsg.VM {
case VMMain: case VMMain:
if m.actionMsg.Action != nil { if m.actionMsg.Action != nil {
...@@ -542,6 +547,9 @@ func (m *ModelMain) handleKeySpace() tea.Cmd { ...@@ -542,6 +547,9 @@ func (m *ModelMain) handleKeySpace() tea.Cmd {
} }
func (m *ModelMain) View() string { func (m *ModelMain) View() string {
if m.actionMsg != nil && m.actionMsg.HelpView {
return HelpStr
}
switch m.actionMsg.VM { switch m.actionMsg.VM {
case VMMain: case VMMain:
if m.actionMsg.Action != nil { if m.actionMsg.Action != nil {
......
...@@ -166,13 +166,13 @@ func (m *ModelProcessDetail) handleModelMsg(msg *ModelMsg) { ...@@ -166,13 +166,13 @@ func (m *ModelProcessDetail) handleModelMsg(msg *ModelMsg) {
m.DCUPercent = 0 m.DCUPercent = 0
m.DCUMemPercent = 0 m.DCUMemPercent = 0
} else { } else {
dcumem = float64(dcuInfo.MemUsedPerent) dcumem = float64(dcuInfo.MemUsedPerent.OrElse(0))
dcu = float64(dcuInfo.DCUUTil) dcu = float64(dcuInfo.DCUUTil.OrElse(0))
m.DCUPercent = dcu m.DCUPercent = dcu
m.DCUMemPercent = dcumem m.DCUMemPercent = dcumem
} }
m.DCUMemTotal = utils.MemorySize{Unit: utils.Byte, Num: dcuInfo.MemTotal} m.DCUMemTotal = utils.MemorySize{Unit: utils.Byte, Num: dcuInfo.MemTotal.OrElse(0)}
m.DCUMemUsed = utils.MemorySize{Unit: utils.Byte, Num: dcuInfo.MemUsed} m.DCUMemUsed = utils.MemorySize{Unit: utils.Byte, Num: dcuInfo.MemUsed.OrElse(0)}
lock.Unlock() lock.Unlock()
m.MemTotal = utils.MemorySize{Unit: utils.Byte, Num: msg.systemInfo.MemTotal} m.MemTotal = utils.MemorySize{Unit: utils.Byte, Num: msg.systemInfo.MemTotal}
......
...@@ -284,24 +284,24 @@ func (m *ModelSysLoad) updateInfo(t *ModelMsg) { ...@@ -284,24 +284,24 @@ func (m *ModelSysLoad) updateInfo(t *ModelMsg) {
qinfo, lock := t.DCUInfo.GetQuitInfo() qinfo, lock := t.DCUInfo.GetQuitInfo()
m.dataMaplock.Lock() m.dataMaplock.Lock()
for k, v := range qinfo { for k, v := range qinfo {
s.DCUMemUsageAvg += v.MemUsedPerent s.DCUMemUsageAvg += v.MemUsedPerent.OrElse(0.0)
s.DCUMemUsage[k] = v.MemUsedPerent s.DCUMemUsage[k] = v.MemUsedPerent.OrElse(0.0)
s.DCUUsageAvg += v.DCUUTil s.DCUUsageAvg += v.DCUUTil.OrElse(0.0)
s.DCUUsage[k] = v.DCUUTil s.DCUUsage[k] = v.DCUUTil.OrElse(0.0)
l1, have := m.dcuMemData[k] l1, have := m.dcuMemData[k]
if !have { if !have {
l1 = linkedlist.New[tchart.TimePoint]() l1 = linkedlist.New[tchart.TimePoint]()
m.dcuMemData[k] = l1 m.dcuMemData[k] = l1
} }
l1.Add(tchart.TimePoint{Time: t.t, Value: float64(v.MemUsedPerent)}) l1.Add(tchart.TimePoint{Time: t.t, Value: float64(v.MemUsedPerent.OrElse(0.0))})
l2, have := m.dcuUsgData[k] l2, have := m.dcuUsgData[k]
if !have { if !have {
l2 = linkedlist.New[tchart.TimePoint]() l2 = linkedlist.New[tchart.TimePoint]()
m.dcuUsgData[k] = l2 m.dcuUsgData[k] = l2
} }
l2.Add(tchart.TimePoint{Time: t.t, Value: float64(v.DCUUTil)}) l2.Add(tchart.TimePoint{Time: t.t, Value: float64(v.DCUUTil.OrElse(0.0))})
} }
l := len(qinfo) l := len(qinfo)
lock.Unlock() lock.Unlock()
......
...@@ -52,6 +52,7 @@ require ( ...@@ -52,6 +52,7 @@ require (
github.com/quic-go/qpack v0.5.1 // indirect github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.54.0 // indirect github.com/quic-go/quic-go v0.54.0 // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/samber/mo v1.16.0 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
github.com/spf13/afero v1.15.0 // indirect github.com/spf13/afero v1.15.0 // indirect
......
...@@ -375,11 +375,11 @@ func parseSMIAllOutput(id int, str string) (*SMIAllOutput, error) { ...@@ -375,11 +375,11 @@ func parseSMIAllOutput(id int, str string) (*SMIAllOutput, error) {
// DCURunningInfo DCU运行状态信息 // DCURunningInfo DCU运行状态信息
type DCURunningInfo struct { type DCURunningInfo struct {
Id int Id int
Temp float32 Temp float32 // 为负数表示无法获取
AvgPower float32 AvgPower float32 // 为负数表示无法获取
PerformanceLevel string PerformanceLevel string
MemPerc float32 MemPerc float32 // 为负数表示无法获取
HCUPerc float32 HCUPerc float32 // 为负数表示无法获取
Mode string // Normal / Low Power Mode string // Normal / Low Power
} }
...@@ -423,24 +423,32 @@ func parseRunningInfo(info string) (map[int]DCURunningInfo, error) { ...@@ -423,24 +423,32 @@ func parseRunningInfo(info string) (map[int]DCURunningInfo, error) {
item.Id = id item.Id = id
temp, err := strconv.ParseFloat(strings.TrimSuffix(strings.ToLower(fields[fieldMap[HeaderMap["Temp"]]]), "c"), 32) temp, err := strconv.ParseFloat(strings.TrimSuffix(strings.ToLower(fields[fieldMap[HeaderMap["Temp"]]]), "c"), 32)
if err != nil { if err != nil {
return nil, err temp = -1.0
err = nil
// return nil, err
} }
item.Temp = float32(temp) item.Temp = float32(temp)
avgPwr, err := strconv.ParseFloat(strings.TrimSuffix(strings.ToLower(fields[fieldMap[HeaderMap["AvgPower"]]]), "w"), 32) avgPwr, err := strconv.ParseFloat(strings.TrimSuffix(strings.ToLower(fields[fieldMap[HeaderMap["AvgPower"]]]), "w"), 32)
if err != nil { if err != nil {
return nil, err avgPwr = -1.0
err = nil
// return nil, err
} }
item.AvgPower = float32(avgPwr) item.AvgPower = float32(avgPwr)
item.PerformanceLevel = fields[3] item.PerformanceLevel = fields[3]
vram, err := strconv.ParseFloat(strings.TrimSuffix(fields[fieldMap[HeaderMap["MemPerc"]]], "%"), 32) vram, err := strconv.ParseFloat(strings.TrimSuffix(fields[fieldMap[HeaderMap["MemPerc"]]], "%"), 32)
if err != nil { if err != nil {
return nil, err vram = -1.0
err = nil
// return nil, err
} }
item.MemPerc = float32(vram) item.MemPerc = float32(vram)
utl, err := strconv.ParseFloat(strings.TrimSuffix(fields[fieldMap[HeaderMap["HCUPerc"]]], "%"), 32) utl, err := strconv.ParseFloat(strings.TrimSuffix(fields[fieldMap[HeaderMap["HCUPerc"]]], "%"), 32)
if err != nil { if err != nil {
return nil, err utl = -1.0
err = nil
// return nil, err
} }
item.HCUPerc = float32(utl) item.HCUPerc = float32(utl)
item.Mode = fields[fieldMap[HeaderMap["Mode"]]] item.Mode = fields[fieldMap[HeaderMap["Mode"]]]
......
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