From cc1485f969a7ef5efe5dca80c638245c783083b4 Mon Sep 17 00:00:00 2001
From: op06072
Date: Fri, 20 Jan 2023 01:25:16 +0900
Subject: [PATCH] FIx the leak and update readme
---
README.md | 105 ++--
.../xcdebugger/Breakpoints_v2.xcbkptlist | 522 +++++++++++-------
socpowerbuddy_swift/main.swift | 130 +++--
socpowerbuddy_swift/render.swift | 410 ++++++++------
socpowerbuddy_swift/sampler.swift | 368 +++++++-----
socpowerbuddy_swift/static.swift | 37 +-
6 files changed, 920 insertions(+), 652 deletions(-)
diff --git a/README.md b/README.md
index f61803a..2540490 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-neoasitop
+neoasitop
A sudoless performance monitoring CLI tool for Apple Silicon
@@ -10,32 +10,21 @@
+
+
+
![](image/neoasitop.png)
+# Introducing
## What is `neoasitop`
-A Swift-based `asitop`-inspired command line tool for Apple Silicon (aka M1) Macs.
-
-* Utilization info:
- * CPU (E-cluster and P-cluster), GPU
- * Frequency and utilization, temperature
- * ANE utilization (measured by power)
- * Fan speed (if fan exists)
- * SOC throttling
-* Memory info:
- * RAM and swap, size and usage
- * Memory bandwidth (CPU/GPU/total)
- * Media engine bandwidth usage
-* Power info:
- * System power, CPU power, GPU power, DRAM power
- * Chart for CPU/GPU power
- * Peak power, rolling average display
+A Swift-based `asitop`-inspired command line tool for Apple Silicon (aka M series) Macs.
`neoasitop` uses the custom [`socpowerbuddy`](https://github.com/BitesPotatoBacks/SocPowerBuddy)-inspired logic, which allows access to a variety of hardware performance counters without sudo permission. `neoasitop` is lightweight and has minimal performance impact.
-**`neoasitop` only tested on following Apple Silicon Macs!**
+**`neoasitop` officially tested on following Apple Silicon Macs!**
* Test list
* 2021 MacBook Pro[MacBookPro18,1] (M1 Pro, Ventura)
@@ -43,24 +32,9 @@ A Swift-based `asitop`-inspired command line tool for Apple Silicon (aka M1) Mac
* 2020 Mac mini[Macmini9,1] (M1, Monterey)
* 2020 MacBook Air[MacBookAir10,1] (M1, Monterey)
-## Installation and Usage
-
-1. Install the [Homebrew](https://brew.sh/index_ko)
-2. Run `brew tap op06072/neoasitop`
-3. Run `brew install neoasitop`
-4. Run `neoasitop`
+## Why
-```shell
-# advanced options
-neoasitop [--interval ] [--color ] [--avg ]
-
-OPTIONS:
- -i, --interval
- Display interval and sampling interval for info gathering (seconds) (default: 1)
- -c, --color Choose display color (0~8) (default: 2)
- --avg Interval for averaged values (seconds) (default: 30)
- -h, --help Show help information.
-```
+Because I didn't want to be the system admin just to see the status of the system. Why kill a fly with a spear? Admin privileges are too powerful to just monitor the system.
## How it works
@@ -86,26 +60,66 @@ OPTIONS:
* Fan existence
* memory and swap usage
-Some information is guesstimate and hardcoded as there doesn't seem to be a official source for it on the system:
+[`Hot`](https://github.com/macmade/Hot) is used to measure the following:
+
+* SOC Throttling
+
+Some information is guesstimated and hardcoded as there doesn't seem to be a official source for it on the system:
* CPU/GPU TDP
* CPU/GPU maximum memory bandwidth
* ANE max power
* Media engine max bandwidth
-[`Hot`](https://github.com/macmade/Hot)
+## Feature
-* SOC Throttling
+* Utilization info:
+ * CPU (E-cluster and P-cluster), GPU
+ * Frequency and utilization, temperature
+ * ANE utilization (measured by power)
+ * Fan speed (if fan exists)
+ * SOC throttling
+* Memory info:
+ * RAM and swap, size and usage
+ * Memory bandwidth (CPU/GPU/total)
+ * Media engine bandwidth usage
+* Power info:
+ * System power, CPU power, GPU power, DRAM power
+ * Chart for CPU/GPU power
+ * Peak power, rolling average display
-## Why
+# Installation, Usage, and Making
+**Note:** Tool usage is listed by `neoasitop --help`
+```shell
+# advanced options
+neoasitop [--interval ] [--color ] [--avg ]
-Because I didn't find something like this online. Also, just curious about stuff.
+OPTIONS:
+ -i, --interval
+ Display interval and sampling interval for info gathering (seconds) (default: 1)
+ -c, --color Choose display color (0~8) (default: 2)
+ --avg Interval for averaged values (seconds) (default: 30)
+ -h, --help Show help information.
+```
-## Disclaimers
+## Install using Homebrew
+1. If you dont have Hombrew, [install it](https://brew.sh/index_ko)!
+2. Add my tap using `brew tap op06072/neoasitop`
+3. Install the tool with `brew install neoasitop`
+4. Run `neoasitop`!
-I just get this from `asitop` don't blame me if it fried your new MacBook or something.
+## Install Manually
+1. Download the bin from [latest release](https://github.com/op06072/NeoAsitop/releases).
+2. Unzip the downloaded file into your desired dir (such as `/usr/bin`)
+4. Run `neoasitop`!
-## Credits
+### Building the project
+The source is bundled in a Xcode project. Simply build via Xcode on your mac!
+
+### Diagnosing missing entries for your system
+A diagnostic dumping tool is included within each release: `iorepdump`. It dumps all IOReport groups matching those used by NeoAsitop. It's helpful for discovering entries on new silicon.
+
+# Credits
Special thanks to:
@@ -113,4 +127,7 @@ Special thanks to:
- [BitesPotatoBacks](https://github.com/BitesPotatoBacks) for the project [SocPowerBuddy](https://github.com/BitesPotatoBacks/SocPowerBuddy) that gave me the way to replace powermetrics.
- [exelban](https://github.com/exelban) for the project [stats](https://github.com/exelban/stats) that gave me the way to get sensor value.
- [macmade](https://github.com/macmade) for the project [Hot](https://github.com/macmade/Hot) that gave me the way to get soc throttle status.
-- [rderik](https://github.com/rderik) for the project [clock](https://github.com/rderik/clock) that gave me the way to use ncurses in swift.
\ No newline at end of file
+- [rderik](https://github.com/rderik) for the project [clock](https://github.com/rderik/clock) that gave me the way to use ncurses in swift.
+
+## Dislaimers
+As I said, some information is just guesstimated. So don't blame me if it fried your new MacBook or something. ~~Well...I don't think that's going to happen.~~
\ No newline at end of file
diff --git a/socpowerbuddy_swift.xcodeproj/xcuserdata/eomsehwan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/socpowerbuddy_swift.xcodeproj/xcuserdata/eomsehwan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
index 9cd9e33..f5ff394 100644
--- a/socpowerbuddy_swift.xcodeproj/xcuserdata/eomsehwan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
+++ b/socpowerbuddy_swift.xcodeproj/xcuserdata/eomsehwan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
@@ -14,8 +14,8 @@
filePath = "socpowerbuddy_swift/sampler.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "299"
- endingLineNumber = "299"
+ startingLineNumber = "344"
+ endingLineNumber = "344"
landmarkName = "format(sd:vd:)"
landmarkType = "9">
@@ -1447,9 +1447,9 @@
filePath = "socpowerbuddy_swift/static.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "376"
- endingLineNumber = "376"
- landmarkName = "generateSocMax(sd:)"
+ startingLineNumber = "381"
+ endingLineNumber = "381"
+ landmarkName = "archError(sd:)"
landmarkType = "9">
@@ -1692,102 +1692,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1904,7 +1792,7 @@
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
-
-
-
-
-
-
-
-
-
-
-
-
@@ -2717,15 +2557,15 @@
@@ -2733,15 +2573,15 @@
@@ -2749,15 +2589,15 @@
@@ -2765,15 +2605,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2781,15 +2701,15 @@
@@ -2797,33 +2717,241 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/socpowerbuddy_swift/main.swift b/socpowerbuddy_swift/main.swift
index e74b16c..6ac26be 100644
--- a/socpowerbuddy_swift/main.swift
+++ b/socpowerbuddy_swift/main.swift
@@ -38,11 +38,11 @@ while cmd.interval/1000 >= options.interval {
cmd.interval /= 2
}
-var cpu_peak_pwr: Float = 0
-var gpu_peak_pwr: Float = 0
+var cpu_peak_pwr: Float = 0
+var gpu_peak_pwr: Float = 0
var system_peak_pwr: Float = 0
-var cpu_avg_pwr_list: [Float] = []
-var gpu_avg_pwr_list: [Float] = []
+var cpu_avg_pwr_list: [Float] = []
+var gpu_avg_pwr_list: [Float] = []
var system_avg_pwr_list: [Float] = []
let procInfo = ProcessInfo()
@@ -113,10 +113,10 @@ generateSocMax(sd: &sd)
sd.max_pwr.append(8)
sd.max_bw.append(7)
-iorep.cpusubchn = nil
-iorep.pwrsubchn = nil
+iorep.cpusubchn = nil
+iorep.pwrsubchn = nil
iorep.clpcsubchn = nil
-iorep.bwsubchn = nil
+iorep.bwsubchn = nil
iorep.cpuchn_cpu = IOReportCopyChannelsInGroup("CPU Stats", nil, 0, 0, 0)
iorep.cpuchn_gpu = IOReportCopyChannelsInGroup("GPU Stats", nil, 0, 0, 0)
iorep.pwrchn_eng = IOReportCopyChannelsInGroup("Energy Model", nil, 0, 0, 0)
@@ -152,6 +152,13 @@ iorep.bwsub = IOReportCreateSubscription(
&iorep.bwsubchn, 0, nil
)
+iorep.cpuchn_cpu = nil
+iorep.cpuchn_gpu = nil
+iorep.pwrchn_eng = nil
+iorep.pwrchn_pmp = nil
+iorep.clpcchn = nil
+iorep.bwchn = nil
+
print("\n [2/2] Gathering System Info\n")
var fan_set = sd.fan_exist
gen_screen()
@@ -161,86 +168,77 @@ var monInfo = dispInfo(sd: sd)
var cpu_pwr = monInfo.cpu_pwr.val
var gpu_pwr = monInfo.gpu_pwr.val
var xy: [Int32] = [0, 0]
-var scrin = display(monInfo, true, nil, xy, options.color) // 레이아웃 렌더링
+var scrin: refreshInfo? = display(monInfo, true, nil, xy, options.color) // 레이아웃 렌더링
//print("layout finish")
-var scr = scrin.tbx
-xy = scrin.xy
+var scr = scrin!.tbx
+var bottomPnt: OpaquePointer? = nil
+xy = scrin!.xy
while true {
autoreleasepool {
- var rd = render_data()
- var vd = vd_init(sd: sd)
+ var rd: render_data? = render_data()
+ var vd: variating_data? = vd_init(sd: sd)
if fan_set {
- getSensorVal(vd: &vd, set_mode: fan_set, sd: &sd) // 센서값
+ getSensorVal(vd: &vd!, set_mode: fan_set, sd: &sd) // 센서값
fan_set = false
} else {
- getSensorVal(vd: &vd, sd: &sd) // 센서값
+ getSensorVal(vd: &vd!, sd: &sd) // 센서값
}
- getMemUsage(vd: &vd)
- sd.ram_capacity = "\(Int(vd.mem_stat.total[0]))\(ByteUnit(vd.mem_stat.total[1]))"
+ getMemUsage(vd: &vd!)
+ sd.ram_capacity = "\(Int(vd!.mem_stat.total[0]))\(ByteUnit(vd!.mem_stat.total[1]))"
monInfo = dispInfo(sd: sd)
monInfo.cpu_pwr.val = cpu_pwr
monInfo.gpu_pwr.val = gpu_pwr
- sample(iorep: iorep, sd: sd, vd: &vd, cmd: cmd) // 데이터 샘플링 (애플 비공개 함수 이용)
+ sample(iorep: iorep, sd: sd, vd: &vd!, cmd: cmd) // 데이터 샘플링 (애플 비공개 함수 이용)
//print("sampling finish")
- format(sd: &sd, vd: &vd) // 포매팅
+ format(sd: &sd, vd: &vd!) // 포매팅
//print("formatting finish")
- summary(sd: sd, vd: vd, rd: &rd, rvd: &monInfo, opt: options.avg)
- cpu_pwr = monInfo.cpu_pwr.val
- gpu_pwr = monInfo.gpu_pwr.val
- //print("summarize finish")
-
- switch getch() {
- // Wait for user input
- // Exit on 'q'
- case Int32(UnicodeScalar("q").value):
- endwin()
- if scr.items.count != 0 {
- if scr.items[0].items.count != 0 {
- if sd.fan_exist {
- del_tbox(tbx: &scr.items[0].items[2].items[0])
- }
- for i in (0...2).reversed() {
- del_tbox(tbx: &scr.items[0].items[i])
- }
- }
- if scr.items[1].items.count != 0 {
- for i in (0...1).reversed() {
- del_tbox(tbx: &scr.items[1].items[i])
- }
+ summary(sd: sd, vd: vd!, rd: &rd!, rvd: &monInfo, opt: options.avg)
+ rd = nil
+ vd = nil
+ }
+
+ cpu_pwr = monInfo.cpu_pwr.val
+ gpu_pwr = monInfo.gpu_pwr.val
+ //print("summarize finish")
+
+ switch getch() {
+ // Wait for user input
+ // Exit on 'q'
+ case Int32(UnicodeScalar("q").value):
+ endwin()
+ if scr.items.count != 0 {
+ if scr.items[0].items.count != 0 {
+ if sd.fan_exist {
+ del_tbox(tbx: &scr.items[0].items[2].items[0])
}
- for i in 0...2 {
- del_tbox(tbx: &scr.items[i])
+ for i in (0...2).reversed() {
+ del_tbox(tbx: &scr.items[0].items[i])
}
}
- del_tbox(tbx: &scr)
- exit(EX_OK)
- default:
- scrin = display(monInfo, false, scr, xy, options.color) // 정보 출력
- scr = scrin.tbx
- xy = scrin.xy
- wclear(scr.t.win)
-
- //dfs_kill(tbx: &scr)
-
- var first_box = 1
- if fan_set {
- del_tbox(tbx: &scr.items[0].items[2].items[0])
- first_box = 2
- }
- for i in (0...first_box).reversed() {
- del_tbox(tbx: &scr.items[0].items[i])
- }
- for i in (0...1).reversed() {
- del_tbox(tbx: &scr.items[1].items[i])
+ if scr.items[1].items.count != 0 {
+ for i in (0...1).reversed() {
+ del_tbox(tbx: &scr.items[1].items[i])
+ }
}
for i in 0...2 {
del_tbox(tbx: &scr.items[i])
}
- del_tbox(tbx: &scr)
- //print("render finish")
}
- Thread.sleep(forTimeInterval: options.interval-(cmd.interval*1e-3))
+ del_tbox(tbx: &scr)
+ print("\nGood Bye")
+ exit(EX_OK)
+ default:
+ autoreleasepool {
+ scrin = display(monInfo, false, scr, xy, options.color, bottomPnt) // 정보 출력
+ scr = scrin!.tbx
+ xy = scrin!.xy
+ bottomPnt = scrin!.bottom
+ scrin = nil
+ }
+ wclear(scr.t.win)
+ //print("render finish")
}
+ Thread.sleep(forTimeInterval: options.interval-(cmd.interval*1e-3))
}
diff --git a/socpowerbuddy_swift/render.swift b/socpowerbuddy_swift/render.swift
index e97098b..906eb5c 100644
--- a/socpowerbuddy_swift/render.swift
+++ b/socpowerbuddy_swift/render.swift
@@ -48,6 +48,7 @@ struct chartInfo {
struct refreshInfo {
var tbx: tbox
+ var bottom: OpaquePointer?
var xy: [Int32]
}
@@ -184,12 +185,16 @@ func gen_screen() {
nodelay(stdscr, true)
}
-func screen_bottom() {
+func screen_bottom(_ bottm: OpaquePointer? = nil) -> OpaquePointer? {
autoreleasepool {
let size = get_size()
let lines = size[0]-1
let cols = size[1]
- let bottom = newwin(1, cols, lines, 0)!
+ var bottom = newwin(1, cols, lines, 0)!
+ if bottm != nil {
+ delwin(bottom)
+ bottom = bottm!
+ }
init_pair(3, Int16(blue), Int16(blue))
wattron(bottom, COLOR_PAIR(3))
box(bottom, 0, 0)
@@ -200,6 +205,8 @@ func screen_bottom() {
waddstr(bottom, quit_msg)
wattroff(bottom, COLOR_PAIR(2))
wrefresh(bottom)
+
+ return bottom
}
}
@@ -225,41 +232,41 @@ func screen_init() -> tbox {
}
func Stack(size: Int32, title: [String], border: Int, stack: split, tbx: inout tbox, offset: Int32? = nil, render: Bool) {
+ let hstack = 1-stack.mode
+ let vstack = stack.mode
+ let t = tbx.t
+ var line = t.h
+ var col = t.w
+ var left = t.x
+ var top = t.y
+ var tiles: [tbox]? = []
+ var colr = green
+
+ if t.c != black && t.c != red && t.title != "" {
+ line -= 2
+ col -= 2
+ left += 1
+ top += 1
+ } else if t.title != "" {
+ line -= 1
+ col -= 1
+ left += 1
+ top += 1
+ }
+
+ var hsize = col
+ var vsize = line
+ var hplus: Int32 = 0
+ var vplus: Int32 = 0
+ if hstack > 0 {
+ hsize /= size
+ hplus = hsize
+ } else if vstack > 0 {
+ vsize /= size
+ vplus = vsize
+ }
+
autoreleasepool {
- let hstack = 1-stack.mode
- let vstack = stack.mode
- let t = tbx.t
- var line = t.h
- var col = t.w
- var left = t.x
- var top = t.y
- var tiles: [tbox] = []
- var colr = green
-
- if t.c != black && t.c != red && t.title != "" {
- line -= 2
- col -= 2
- left += 1
- top += 1
- } else if t.title != "" {
- line -= 1
- col -= 1
- left += 1
- top += 1
- }
-
- var hsize = col
- var vsize = line
- var hplus: Int32 = 0
- var vplus: Int32 = 0
- if hstack > 0 {
- hsize /= size
- hplus = hsize
- } else if vstack > 0 {
- vsize /= size
- vplus = vsize
- }
-
for i in 0.. 0 {
- if border == 2 {
- init_pair(5, Int16(yellow), Int16(black))
- wattron(win, COLOR_PAIR(5))
- colr = yellow
- } else if border == 3 {
- init_pair(6, Int16(red), Int16(black))
- wattron(win, COLOR_PAIR(6))
- colr = red
+ autoreleasepool {
+ var win: OpaquePointer? = nil
+ if tbx.items.count > 0 {
+ win = tbx.items[Int(i)].t.win
+ wresize(win, vsize+spair, hsize)
+ mvwin(win, y, x)
+ } else {
+ win = newwin(vsize+spair, hsize, y, x)
}
- box(win, 0, 0)
- } else {
- colr = black
- }
- var titl = ""
- if title.count > i {
- titl = title[Int(i)]
- if titl != "" {
- var start = col/8
- if border == 1{
- start = col/10
+ wattron(win, COLOR_PAIR(1))
+ //werase(win)
+ if border > 0 {
+ if border == 2 {
+ init_pair(5, Int16(yellow), Int16(black))
+ wattron(win, COLOR_PAIR(5))
+ colr = yellow
+ } else if border == 3 {
+ init_pair(6, Int16(red), Int16(black))
+ wattron(win, COLOR_PAIR(6))
+ colr = red
}
- start -= Int32(titl.count/2)
- if start < 0 {
- start = 0
+ box(win, 0, 0)
+ } else {
+ colr = black
+ }
+ var titl = ""
+ if title.count > i {
+ titl = title[Int(i)]
+ if titl != "" {
+ var start = col/8
+ if border == 1{
+ start = col/10
+ }
+ start -= Int32(titl.count/2)
+ if start < 0 {
+ start = 0
+ }
+ wmove(win, 0, start)
+ wattron(win, COLOR_PAIR(1))
+ waddstr(win, " \(titl) ")
}
- wmove(win, 0, start)
- wattron(win, COLOR_PAIR(1))
- waddstr(win, " \(titl) ")
}
+
+ wattroff(win, COLOR_PAIR(1))
+ if tbx.items.count > 0 {
+ tiles!.append(tbox(
+ t: Tile(x: x, y: y, w: hsize, h: vsize, c: colr, win: win, title: titl),
+ items: tbx.items[Int(i)].items
+ ))
+ } else {
+ tiles!.append(tbox(
+ t: Tile(x: x, y: y, w: hsize, h: vsize, c: colr, win: win, title: titl),
+ items: []
+ ))
+ }
+ if render {
+ wrefresh(win)
+ }
+ win = nil
}
-
- wattroff(win, COLOR_PAIR(1))
- if render {
- wrefresh(win)
- }
- tiles.append(tbox(
- t: Tile(x: x, y: y, w: hsize, h: vsize, c: colr, win: win, title: titl),
- items: []
- ))
}
- tbx.items = tiles
+ tbx.items = tiles!
+ tiles = nil
}
}
@@ -371,7 +396,7 @@ func Gauge(value: Float? = nil, gauge: split, tbx: inout tbox, datapoint: [Float
}
for i in peak...line {
wmove(win, i, 1+(offset ?? 0))
- waddstr(win,bar)
+ waddstr(win, bar)
}
} else if vgauge != 0 {
if title != "" {
@@ -420,32 +445,49 @@ func Gauge(value: Float? = nil, gauge: split, tbx: inout tbox, datapoint: [Float
}
}
-func display(_ disp: dispInfo, _ gn: Bool = false, _ scrin: tbox? = nil, _ xy: [Int32], _ colr: UInt8 = 2) -> refreshInfo {
+func display(_ disp: dispInfo, _ gn: Bool = false, _ scrin: tbox? = nil, _ xy: [Int32], _ colr: UInt8 = 2, _ bottom: OpaquePointer? = nil) -> refreshInfo {
let size = get_size()
let lines = size[0]
let cols = size[1]
var scrn = scrin ?? screen_init()
+ var btm: OpaquePointer? = nil
- autoreleasepool {
-
- if lines < 34 || cols < 63 {
- endwin()
- print("Terminal size is too small!\nThis tool needs 63 cols and 34 lines at least!")
- exit(1)
- }
+ if lines < 34 || cols < 63 {
+ endwin()
+ print("Terminal size is too small!\nThis tool needs 63 cols and 34 lines at least!")
+ exit(1)
+ }
- if (cols != xy[0]) || (lines != xy[1]) {
- scrn = screen_init()
- }
-
- init_pair(1, Int16(colr), Int16(black))
-
- var first_stack: Int32 = 2
- if sd.fan_exist {
- first_stack = 3
+ if (cols != xy[0]) || (lines != xy[1]) {
+ if !gn {
+ var first_box = 1
+ if sd.fan_exist {
+ del_tbox(tbx: &scrn.items[0].items[2].items[0])
+ first_box = 2
+ }
+ for i in (0...first_box).reversed() {
+ del_tbox(tbx: &scrn.items[0].items[i])
+ }
+ for i in (0...1).reversed() {
+ del_tbox(tbx: &scrn.items[1].items[i])
+ }
+ for i in 0...2 {
+ del_tbox(tbx: &scrn.items[i])
+ }
+ del_tbox(tbx: &scrn)
}
-
- //print("rendering start")
+ scrn = screen_init()
+ }
+
+ init_pair(1, Int16(colr), Int16(black))
+
+ var first_stack: Int32 = 2
+ if sd.fan_exist {
+ first_stack = 3
+ }
+
+ //print("rendering start")
+ autoreleasepool {
Stack(
size: 3,
title: [disp.proc_grp, disp.mem_grp, disp.pwr_grp],
@@ -467,28 +509,31 @@ func display(_ disp: dispInfo, _ gn: Bool = false, _ scrin: tbox? = nil, _ xy: [
size: 2, title: [disp.cpu_pwr.title, disp.gpu_pwr.title],
border: 0, stack: .hsplit, tbx: &scrn.items[2], render: !gn
)
- //print("third box")
- var first_box = [[""]]
- if sd.fan_exist {
- first_box = [
- [disp.ecpu_usg.title, disp.pcpu_usg.title],
- [disp.gpu_usg.title, disp.ane_usg.title],
- [disp.fan_usg.title, ""]
- ]
- } else {
- first_box = [
- [disp.ecpu_usg.title, disp.pcpu_usg.title],
- [disp.gpu_usg.title, disp.ane_usg.title]
- ]
- }
-
- for (idx, titl) in first_box.enumerated() {
- Stack(
- size: 2, title: titl, border: 0, stack: .hsplit,
- tbx: &scrn.items[0].items[idx], render: !gn
- )
- }
- //print("fan gauge start")
+ }
+
+ //print("third box")
+ var first_box = [[""]]
+ if sd.fan_exist {
+ first_box = [
+ [disp.ecpu_usg.title, disp.pcpu_usg.title],
+ [disp.gpu_usg.title, disp.ane_usg.title],
+ [disp.fan_usg.title, ""]
+ ]
+ } else {
+ first_box = [
+ [disp.ecpu_usg.title, disp.pcpu_usg.title],
+ [disp.gpu_usg.title, disp.ane_usg.title]
+ ]
+ }
+
+ for (idx, titl) in first_box.enumerated() {
+ Stack(
+ size: 2, title: titl, border: 0, stack: .hsplit,
+ tbx: &scrn.items[0].items[idx], render: !gn
+ )
+ }
+ //print("fan gauge start")
+ autoreleasepool {
if sd.fan_mode > 0 {
Stack(
size: Int32(sd.fan_mode), title: ["", ""], border: 0,
@@ -505,47 +550,49 @@ func display(_ disp: dispInfo, _ gn: Bool = false, _ scrin: tbox? = nil, _ xy: [
) // FAN Speed
}
}
- //print("fan gauge finish")
-
- let proc_gauge_info = [
- [disp.ecpu_usg.val, disp.pcpu_usg.val],
- [disp.gpu_usg.val, disp.ane_usg.val]
- ]
- for i in 0...1 {
- for j in 0...1 {
- //print("processor gauge start")
- Gauge(
- value: proc_gauge_info[i][j],
- gauge: .hgauge,
- tbx: &scrn.items[0].items[i].items[j],
- render: !gn
- )
- }
- } //processor utilization group
- //print("processor gauge finish")
-
- if sd.fan_exist {
- let fan_label = scrn.items[0].items[2].items[1].t
- var mid = Int32((fan_label.h-1)/2)
- wattron(fan_label.win, COLOR_PAIR(1))
- for i in disp.airflow_info {
- wmove(fan_label.win, mid, 0)
- waddstr(fan_label.win, i)
- mid += 1
- }
- wattroff(fan_label.win, COLOR_PAIR(1))
- if !gn {
- wrefresh(fan_label.win)
- }
+ }
+ //print("fan gauge finish")
+
+ let proc_gauge_info = [
+ [disp.ecpu_usg.val, disp.pcpu_usg.val],
+ [disp.gpu_usg.val, disp.ane_usg.val]
+ ]
+ for i in 0...1 {
+ for j in 0...1 {
+ //print("processor gauge start")
+ Gauge(
+ value: proc_gauge_info[i][j],
+ gauge: .hgauge,
+ tbx: &scrn.items[0].items[i].items[j],
+ render: !gn
+ )
}
-
- Gauge(
- value: disp.ram_usg.val,
- gauge: .hgauge,
- tbx: &scrn.items[1].items[0],
- render: !gn
- ) // RAM Usage
- //print("ram gauge finish")
+ } //processor utilization group
+ //print("processor gauge finish")
+
+ if sd.fan_exist {
+ let fan_label = scrn.items[0].items[2].items[1].t
+ var mid = Int32((fan_label.h-1)/2)
+ wattron(fan_label.win, COLOR_PAIR(1))
+ for i in disp.airflow_info {
+ wmove(fan_label.win, mid, 0)
+ waddstr(fan_label.win, i)
+ mid += 1
+ }
+ wattroff(fan_label.win, COLOR_PAIR(1))
+ if !gn {
+ wrefresh(fan_label.win)
+ }
+ }
+
+ Gauge(
+ value: disp.ram_usg.val,
+ gauge: .hgauge,
+ tbx: &scrn.items[1].items[0],
+ render: !gn
+ ) // RAM Usage
+ //print("ram gauge finish")
+ autoreleasepool {
Stack(
size: 4,
title: [
@@ -555,31 +602,32 @@ func display(_ disp: dispInfo, _ gn: Bool = false, _ scrin: tbox? = nil, _ xy: [
border: 0, stack: .hsplit,
tbx: &scrn.items[1].items[1], render: !gn
)
- let bw_grp = [
- disp.ecpu_bw.val, disp.pcpu_bw.val,
- disp.gpu_bw.val, disp.media_bw.val
- ]
- for i in 0...3 {
- Gauge(
- value: bw_grp[i], gauge: .hgauge,
- tbx: &scrn.items[1].items[1].items[i],
- render: !gn
- )
- } // Bandwidth Group
- //print("bw gauge finish")
- Gauge(
- gauge: .vgauge, tbx: &scrn.items[2].items[0],
- datapoint: disp.cpu_pwr.val,
- render: !gn
- )
- //print("cpu_pwr gauge finish")
+ }
+
+ let bw_grp = [
+ disp.ecpu_bw.val, disp.pcpu_bw.val,
+ disp.gpu_bw.val, disp.media_bw.val
+ ]
+ for i in 0...3 {
Gauge(
- gauge: .vgauge, tbx: &scrn.items[2].items[1],
- datapoint: disp.gpu_pwr.val,
+ value: bw_grp[i], gauge: .hgauge,
+ tbx: &scrn.items[1].items[1].items[i],
render: !gn
)
- //print("gpu_pwr gauge finish")
- screen_bottom()
- }
- return refreshInfo(tbx: scrn, xy: [cols, lines])
+ } // Bandwidth Group
+ //print("bw gauge finish")
+ Gauge(
+ gauge: .vgauge, tbx: &scrn.items[2].items[0],
+ datapoint: disp.cpu_pwr.val,
+ render: !gn
+ )
+ //print("cpu_pwr gauge finish")
+ Gauge(
+ gauge: .vgauge, tbx: &scrn.items[2].items[1],
+ datapoint: disp.gpu_pwr.val,
+ render: !gn
+ )
+ //print("gpu_pwr gauge finish")
+ btm = screen_bottom(bottom)
+ return refreshInfo(tbx: scrn, bottom: btm, xy: [cols, lines])
}
diff --git a/socpowerbuddy_swift/sampler.swift b/socpowerbuddy_swift/sampler.swift
index 6c6898f..dc552c0 100644
--- a/socpowerbuddy_swift/sampler.swift
+++ b/socpowerbuddy_swift/sampler.swift
@@ -12,168 +12,211 @@ func sample(iorep: iorep_data,
sd: static_data,
vd: inout variating_data,
cmd: cmd_data) {
- autoreleasepool {
- let ptype_state = "P"
- let vtype_state = "V"
- let idletype_state = "IDLE"
- let offtype_state = "OFF"
-
- // It's awful and horrible memory leaking time!
- // I have no idea how can I fix this.
- var tmp_samp = IOReportCreateSamples(
- iorep.cpusub, iorep.cpusubchn?.takeUnretainedValue(), nil
- ).takeRetainedValue()
-
- let cpusamp_a = tmp_samp
- tmp_samp = IOReportCreateSamples(
- iorep.pwrsub, iorep.pwrsubchn?.takeUnretainedValue(), nil
- ).takeRetainedValue()
- let pwrsamp_a = tmp_samp
- tmp_samp = IOReportCreateSamples(
- iorep.clpcsub, iorep.clpcsubchn?.takeUnretainedValue(), nil
- ).takeRetainedValue()
- let clpcsamp_a = tmp_samp
- tmp_samp = IOReportCreateSamples(
- iorep.bwsub, iorep.bwsubchn?.takeUnretainedValue(), nil
- ).takeRetainedValue()
- let bwsamp_a = tmp_samp
-
- if cmd.interval > 0 {
- Thread.sleep(forTimeInterval: cmd.interval*1e-3)
- }
-
- tmp_samp = IOReportCreateSamples(
- iorep.cpusub, iorep.cpusubchn?.takeUnretainedValue(), nil
- ).takeRetainedValue()
- let cpusamp_b = tmp_samp
- tmp_samp = IOReportCreateSamples(
- iorep.pwrsub, iorep.pwrsubchn?.takeUnretainedValue(), nil
- ).takeRetainedValue()
- let pwrsamp_b = tmp_samp
- tmp_samp = IOReportCreateSamples(
- iorep.bwsub, iorep.bwsubchn?.takeUnretainedValue(), nil
- ).takeRetainedValue()
- let clpcsamp_b = tmp_samp
- tmp_samp = IOReportCreateSamples(
- iorep.bwsub, iorep.bwsubchn?.takeUnretainedValue(), nil
- ).takeRetainedValue()
- let bwsamp_b = tmp_samp
-
- var ttmp = IOReportCreateSamplesDelta(cpusamp_a, cpusamp_b, nil)?.takeRetainedValue()
-
- let cpu_delta = Array((ttmp as! Dictionary).values)[0] as? Array
- ttmp = IOReportCreateSamplesDelta(pwrsamp_a, pwrsamp_b, nil)?.takeRetainedValue()
- let pwr_delta = Array((ttmp as! Dictionary).values)[0] as? Array
- ttmp = IOReportCreateSamplesDelta(clpcsamp_a, clpcsamp_b, nil)?.takeRetainedValue()
- let clpc_delta = Array((ttmp as! Dictionary).values)[0] as? Array
- ttmp = IOReportCreateSamplesDelta(bwsamp_a, bwsamp_b, nil)?.takeRetainedValue()
- let bw_delta = Array((ttmp as! Dictionary).values)[0] as? Array
- // Fortunately, You just passed the memory leak part "this time".
-
- for sample in cpu_delta! {
- for i in stride(from: 0, to: IOReportStateGetCount(sample), by: 1) {
- let subgroup = IOReportChannelGetSubGroup(sample)
- let idx_name = IOReportStateGetNameForIndex(sample, i)
- let chann_name = IOReportChannelGetChannelName(sample)
- let residency = IOReportStateGetResidency(sample, i)
-
- for ii in 0.. 0 {
+ Thread.sleep(forTimeInterval: cmd.interval*1e-3)
+ }
+
+ let cpusamp_b = IOReportCreateSamples(iorep.cpusub, iorep.cpusubchn?.takeUnretainedValue(), nil)
+ let pwrsamp_b = IOReportCreateSamples(iorep.pwrsub, iorep.pwrsubchn?.takeUnretainedValue(), nil)
+ let clpcsamp_b = IOReportCreateSamples(iorep.clpcsub, iorep.clpcsubchn?.takeUnretainedValue(), nil)
+ let bwsamp_b = IOReportCreateSamples(iorep.bwsub, iorep.bwsubchn?.takeUnretainedValue(), nil)
+
+ let cpu_delta = IOReportCreateSamplesDelta(cpusamp_a?.takeUnretainedValue(), cpusamp_b?.takeUnretainedValue(), nil)
+ let pwr_delta = IOReportCreateSamplesDelta(pwrsamp_a?.takeUnretainedValue(), pwrsamp_b?.takeUnretainedValue(), nil)
+ let clpc_delta = IOReportCreateSamplesDelta(clpcsamp_a?.takeUnretainedValue(), clpcsamp_b?.takeUnretainedValue(), nil)
+ let bw_delta = IOReportCreateSamplesDelta(bwsamp_a?.takeUnretainedValue(), bwsamp_b?.takeUnretainedValue(), nil)
+
+ cpusamp_a?.release()
+ cpusamp_b?.release()
+ pwrsamp_a?.release()
+ pwrsamp_b?.release()
+ clpcsamp_a?.release()
+ clpcsamp_b?.release()
+ bwsamp_a?.release()
+ bwsamp_b?.release()
+
+ var tmp_vd: variating_data? = vd
+
+ IOReportIterate(cpu_delta?.takeUnretainedValue(), { sample in
+ for i in stride(from: 0, to: IOReportStateGetCount(sample), by: 1) {
+ var subgroup = IOReportChannelGetSubGroup(sample)
+ var idx_name = IOReportStateGetNameForIndex(sample, i)
+ var chann_name = IOReportChannelGetChannelName(sample)
+ let residency = IOReportStateGetResidency(sample, i)
+
+ for ii in 0..? = chann_name!.split(separator: " ")
+ var tmp_name: String? = last_tmp![0..? = [raw!]
- if chann_name == last_name+" wr" {
- vd.bandwidth_cnt[last_name]!.append(raw/Double(cmd.interval/1e+3)/1e9)
- } else if chann_name.contains(" rd") {
- let last_tmp = chann_name.split(separator: " ")
- last_name = last_tmp[0.. Dictionary? {
@@ -190,9 +233,9 @@ func appleSiliconSensors(page: Int32, usage: Int32, typ: Int32) -> Dictionary Dictionary