Skip to content

Commit

Permalink
cubestat: lint fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
okuvshynov committed Aug 2, 2024
1 parent 78e4e21 commit 5611fa0
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 36 deletions.
38 changes: 21 additions & 17 deletions cubestat/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,34 @@

from cubestat.common import DisplayMode


class ColorTheme(DisplayMode):
mono = 'mono'
inv = 'inv'
col = 'col'
inv = 'inv'
col = 'col'


colors_ansi256 = {
'green': [-1, 150, 107, 22],
'red' : [-1, 224, 181, 138],
'blue' : [-1, 189, 146, 103],
'pink' : [-1, 223, 180, 137],
'gray' : [-1, 7, 8, 0],
'white' : [-1, 8, 7, 15],
'red': [-1, 224, 181, 138],
'blue': [-1, 189, 146, 103],
'pink': [-1, 223, 180, 137],
'gray': [-1, 7, 8, 0],
'white': [-1, 8, 7, 15],
}

light_colormap = {
'cpu': 'green',
'ram': 'pink',
'gpu': 'red',
'ane': 'red',
'disk': 'blue',
'cpu': 'green',
'ram': 'pink',
'gpu': 'red',
'ane': 'red',
'disk': 'blue',
'network': 'blue',
'swap': 'pink',
'power': 'red',
'swap': 'pink',
'power': 'red',
}


def prepare_cells():
chrs = [' ', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█']
cells = {}
Expand All @@ -39,10 +42,11 @@ def prepare_cells():
colorpair += 1
return cells


def get_theme(metric, color_mode):
res = {
ColorTheme.mono : 'gray',
ColorTheme.inv : 'white',
ColorTheme.col : light_colormap.get(metric, 'green')
ColorTheme.mono: 'gray',
ColorTheme.inv: 'white',
ColorTheme.col: light_colormap.get(metric, 'green')
}
return res[color_mode]
30 changes: 26 additions & 4 deletions cubestat/common.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,45 @@
import math
from enum import Enum


class DisplayMode(Enum):
def __str__(self):
return self.value

def next(self):
values = list(self.__class__)
return values[(values.index(self) + 1) % len(values)]

def prev(self):
values = list(self.__class__)
return values[(values.index(self) + len(values) - 1) % len(values)]



class SimpleMode(DisplayMode):
show = 'show'
hide = 'hide'


# buckets is a list of factor/label, e.g. [(1024*1024, 'Mb'), (1024, 'Kb'), (1, 'b')]
def format_measurement(curr, mx, buckets):
for lim, unit in buckets[:-1]:
if mx > lim:
return f'{curr / lim :3.0f} {unit}'
return f'{curr :3.0f} {buckets[-1][1]}'


def label2(slice, buckets, idxs):
mx = max(slice)
mx = float(1 if mx == 0 else 2 ** (int((mx - 1)).bit_length()))
return mx, [format_measurement(slice[idx], mx, buckets) for idx in idxs]


def label10(slice, buckets, idxs):
mx = max(slice)
mx = float(1 if mx <= 0 else 10 ** math.ceil(math.log10(mx)))
return mx, [format_measurement(slice[idx], mx, buckets) for idx in idxs]


class RateReader:
def __init__(self, interval_ms):
self.interval_s = interval_ms / 1000.0
Expand All @@ -46,10 +52,26 @@ def next(self, key, value):
self.last[key] = value
return res


def label_bytes(values, idxs):
buckets = [(1024 ** 5, 'PB'), (1024 ** 4, 'TB'), (1024 ** 3, 'GB'), (1024 ** 2, 'MB'), (1024, 'KB'), (1, 'Bytes')]
buckets = [
(1024 ** 5, 'PB'),
(1024 ** 4, 'TB'),
(1024 ** 3, 'GB'),
(1024 ** 2, 'MB'),
(1024, 'KB'),
(1, 'Bytes')
]
return label2(values, buckets, idxs)


def label_bytes_per_sec(values, idxs):
buckets = [(1024 ** 5, 'PB/s'), (1024 ** 4, 'TB/s'), (1024 ** 3, 'GB/s'), (1024 ** 2, 'MB/s'), (1024, 'KB/s'), (1, 'Bytes/s')]
buckets = [
(1024 ** 5, 'PB/s'),
(1024 ** 4, 'TB/s'),
(1024 ** 3, 'GB/s'),
(1024 ** 2, 'MB/s'),
(1024, 'KB/s'),
(1, 'Bytes/s')
]
return label2(values, buckets, idxs)
20 changes: 12 additions & 8 deletions cubestat/cubestat.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@
from cubestat.metrics.registry import get_metrics, metrics_configure_argparse
from cubestat.metrics import cpu, gpu, memory, accel, swap, network, disk, power


class ViewMode(DisplayMode):
off = "off"
one = "one"
all = "all"


class Cubestat:
def __init__(self, stdscr, args):
self.screen = Screen(stdscr)
self.ruler_interval = 20 # chars
self.ruler_interval = 20 # chars

self.lock = Lock()

Expand All @@ -39,11 +41,11 @@ def __init__(self, stdscr, args):
self.theme = ColorTheme.col

self.refresh_ms = args.refresh_ms
self.step_s = args.refresh_ms / 1000.0
self.step_s = args.refresh_ms / 1000.0
self.metrics = get_metrics(args)

self.input_handler = InputHandler(self)
self.data_manager = DataManager(args.buffer_size)
self.data_manager = DataManager(args.buffer_size)

def do_read(self, context):
updates = []
Expand All @@ -66,7 +68,7 @@ def _ruler_values(self, metric, title, idxs, data):
if self.view == ViewMode.off:
return []
idxs = [idx for idx in idxs if idx < len(data)]
data_indices = [-idx - 1 for idx in idxs]
data_indices = [-idx - 1 for idx in idxs]
_, formatted_values = metric.format(title, data, data_indices)
if self.view == ViewMode.one and len(idxs) > 1:
idxs = idxs[:1]
Expand All @@ -79,7 +81,7 @@ def render(self):
exit(0)
if self.snapshots_observed == self.snapshots_rendered and not self.settings_changed:
return

self.screen.render_start()
cols = self.screen.cols
ruler_indices = list(range(0, cols, self.ruler_interval))
Expand All @@ -94,7 +96,7 @@ def render(self):

if not show:
continue

if skip > 0:
skip -= 1
continue
Expand All @@ -105,12 +107,12 @@ def render(self):
self.screen.render_ruler(indent, title, base_ruler, ruler_values, row)

max_value = self.max_val(metric, title, data_slice)
theme = get_theme(metric_name, self.theme)
theme = get_theme(metric_name, self.theme)
self.screen.render_chart(theme, max_value, data_slice, row)

row += 2
self.snapshots_rendered = self.snapshots_observed
self.settings_changed = False
self.settings_changed = False
if self.view != ViewMode.off:
ruler_times = [(i, f'-{(self.step_s * (i + self.h_shift)):.2f}s') for i in ruler_indices]
self.screen.render_time(base_ruler, ruler_times, row)
Expand All @@ -124,10 +126,12 @@ def loop(self, platform):
self.render()
self.input_handler.handle_input()


def start(stdscr, platform, args):
h = Cubestat(stdscr, args)
h.loop(platform)


def main():
logging.basicConfig(filename='/tmp/cubestat.log', level=logging.INFO)
parser = argparse.ArgumentParser("cubestat")
Expand Down
5 changes: 3 additions & 2 deletions cubestat/data.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import collections
import itertools


class DataManager:
def __init__(self, buffer_size):
init_series = lambda: collections.deque(maxlen=buffer_size)
init_group = lambda: collections.defaultdict(init_series)
self.data = collections.defaultdict(init_group)
init_group = lambda: collections.defaultdict(init_series)
self.data = collections.defaultdict(init_group)

def get_slice(self, series, indent, h_shift, cols, spacing):
data_length = len(series) - h_shift if h_shift > 0 else len(series)
Expand Down
1 change: 1 addition & 0 deletions cubestat/input.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import curses


class InputHandler:
def __init__(self, horizon):
self.horizon = horizon
Expand Down
9 changes: 5 additions & 4 deletions cubestat/metrics/accel.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from cubestat.metrics.base_metric import base_metric
from cubestat.metrics.registry import cubestat_metric


@cubestat_metric('darwin')
class ane_metric(base_metric):
def __init__(self) -> None:
Expand All @@ -10,7 +11,7 @@ def __init__(self) -> None:
def get_ane_scaler(self) -> float:
# This is pretty much a guess based on tests on a few models I had available.
# Need anything M3 + Ultra models to test.
# Based on TOPS numbers Apple published, all models seem to have same ANE
# Based on TOPS numbers Apple published, all models seem to have same ANE
# except Ultra having 2x.
ane_power_scalers = {
"M1": 13000.0,
Expand All @@ -19,7 +20,7 @@ def get_ane_scaler(self) -> float:
}
# identity the model to get ANE scaler
brand_str = subprocess.check_output(['sysctl', '-n', 'machdep.cpu.brand_string'], text=True)
ane_scaler = 15500 # default to M2
ane_scaler = 15500 # default to M2
for k, v in ane_power_scalers.items():
if k in brand_str:
ane_scaler = v
Expand All @@ -32,10 +33,10 @@ def read(self, context):
res = {}
res['ANE util %'] = 100.0 * context['processor']['ane_power'] / self.ane_scaler
return res

def pre(self, title):
return True, ''

def format(self, title, values, idxs):
return 100.0, [f'{values[i]:3.0f}%' for i in idxs]

Expand Down
4 changes: 3 additions & 1 deletion cubestat/metrics/cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
from cubestat.metrics.registry import cubestat_metric
from cubestat.common import DisplayMode


class CPUMode(DisplayMode):
all = 'all'
by_cluster = 'by_cluster'
by_core = 'by_core'

def auto_cpu_mode() -> CPUMode:
return CPUMode.all if os.cpu_count() < 20 else CPUMode.by_cluster
return CPUMode.all if os.cpu_count() < 20 else CPUMode.by_cluster


class cpu_metric(base_metric):
def pre(self, title):
Expand Down

0 comments on commit 5611fa0

Please sign in to comment.