feat(tui/device): add extra information to bar charts

This commit is contained in:
Xuehai Pan 2025-11-10 17:31:45 +08:00
parent 932257a5f9
commit 51ee688d2b
3 changed files with 153 additions and 103 deletions

View file

@ -98,7 +98,14 @@ def cut_string(
# pylint: disable=disallowed-name # pylint: disable=disallowed-name
def make_bar(prefix: str, percent: float | str, width: int, *, extra_text: str = '') -> str: def make_bar(
prefix: str,
percent: float | str,
width: int,
*,
extra_text: str = '',
swap_text: bool = False,
) -> str:
bar = f'{prefix}: ' bar = f'{prefix}: '
if percent != NA and not (isinstance(percent, float) and not math.isfinite(percent)): if percent != NA and not (isinstance(percent, float) and not math.isfinite(percent)):
if isinstance(percent, str) and percent.endswith('%'): if isinstance(percent, str) and percent.endswith('%'):
@ -116,6 +123,11 @@ def make_bar(prefix: str, percent: float | str, width: int, *, extra_text: str =
else: else:
bar += '' * (width - len(bar) - 4) bar += '' * (width - len(bar) - 4)
text = 'N/A' text = 'N/A'
if extra_text and len(f'{bar} {text} {extra_text}') <= width: if extra_text:
return f'{bar} {text}'.ljust(width - len(extra_text) - 1) + f' {extra_text}' if len(f'{bar} {text} {extra_text}') <= width:
if swap_text:
text, extra_text = extra_text, text
return f'{bar} {text}'.ljust(width - len(extra_text) - 3) + f' {extra_text}'
if len(f'{bar} {extra_text}') <= width and swap_text:
return f'{bar} {extra_text}'.ljust(width)
return f'{bar} {text}'.ljust(width) return f'{bar} {text}'.ljust(width)

View file

@ -189,7 +189,7 @@ class MainScreen(BaseSelectableScreen): # pylint: disable=too-many-instance-att
def print(self) -> None: def print(self) -> None:
if self.device_count > 0: if self.device_count > 0:
print_width = min(panel.print_width() for panel in self.container) print_width = min(panel.print_width() for panel in self.container)
self.width = max(print_width, min(self.width, 128)) self.width = max(print_width, min(self.width, 140))
else: else:
self.width = 79 self.width = 79
for panel in self.container: for panel in self.container:

View file

@ -353,39 +353,43 @@ class DevicePanel(BasePanel): # pylint: disable=too-many-instance-attributes
if draw_bars: if draw_bars:
left_width = (remaining_width - 6 + 1) // 2 - 1 left_width = (remaining_width - 6 + 1) // 2 - 1
right_width = (remaining_width - 6) // 2 + 1 right_width = (remaining_width - 6) // 2 + 1
matrix: list[tuple[int, int, int, str, float, str]] = [] matrix: list[list[tuple[int, int, str, float, str, str]]] = []
if device.is_mig_device: if device.is_mig_device:
matrix = [ matrix = [
( [
self.x + 80, (
y_start, self.x + 80,
remaining_width - 3, remaining_width - 3,
'MEM', 'MEM',
device.memory_percent, device.memory_percent,
device.memory_display_color, device.memory_display_color,
), device.memory_used_human,
),
],
] ]
if remaining_width >= 44 and len(prev_device_index) == 1: if remaining_width >= 44 and len(prev_device_index) == 1:
self.addstr(y_start - 1, self.x + 80 + left_width + 1, '') self.addstr(y_start - 1, self.x + 80 + left_width + 1, '')
elif self.compact: elif self.compact:
if remaining_width >= 44: if remaining_width >= 44:
matrix = [ matrix = [
( [
self.x + 80, (
y_start, self.x + 80,
left_width, left_width,
'MEM', 'MEM',
device.memory_percent, device.memory_percent,
device.memory_display_color, device.memory_display_color,
), device.memory_used_human,
( ),
self.x + 80 + left_width + 3, (
y_start, self.x + 80 + left_width + 3,
right_width, right_width,
'UTL', 'UTL',
device.gpu_utilization, device.gpu_utilization,
device.gpu_display_color, device.gpu_display_color,
), f'@ {device.clock_infos.sm}MHz',
),
],
] ]
separator = '' if index > 0 else '' separator = '' if index > 0 else ''
if len(prev_device_index) == 2: if len(prev_device_index) == 2:
@ -395,50 +399,56 @@ class DevicePanel(BasePanel): # pylint: disable=too-many-instance-attributes
self.addstr(y_start + 1, self.x + 80 + left_width + 1, '') self.addstr(y_start + 1, self.x + 80 + left_width + 1, '')
else: else:
matrix = [ matrix = [
( [
self.x + 80, (
y_start, self.x + 80,
remaining_width - 3, remaining_width - 3,
'MEM', 'MEM',
device.memory_percent, device.memory_percent,
device.memory_display_color, device.memory_display_color,
), device.memory_used_human,
),
],
] ]
else: else:
if remaining_width >= 44: if remaining_width >= 44:
matrix = [ matrix = [
( [
self.x + 80, (
y_start, self.x + 80,
left_width, left_width,
'MEM', 'MEM',
device.memory_percent, device.memory_percent,
device.memory_display_color, device.memory_display_color,
), device.memory_used_human,
( ),
self.x + 80, (
y_start + 1, self.x + 80 + left_width + 3,
left_width, right_width,
'UTL', 'MBW',
device.gpu_utilization, device.memory_utilization,
device.gpu_display_color, device.bandwidth_display_color,
), f'@ {device.clock_infos.memory}MHz',
( ),
self.x + 80 + left_width + 3, ],
y_start, [
right_width, (
'MBW', self.x + 80,
device.memory_utilization, left_width,
device.bandwidth_display_color, 'UTL',
), device.gpu_utilization,
( device.gpu_display_color,
self.x + 80 + left_width + 3, f'@ {device.clock_infos.sm}MHz',
y_start + 1, ),
right_width, (
'PWR', self.x + 80 + left_width + 3,
device.power_utilization, right_width,
device.power_display_color, 'PWR',
), device.power_utilization,
device.power_display_color,
f'{device.power_status.partition(" / ")[0]}',
),
],
] ]
separator = '' if index > 0 else '' separator = '' if index > 0 else ''
if len(prev_device_index) == 2: if len(prev_device_index) == 2:
@ -448,40 +458,59 @@ class DevicePanel(BasePanel): # pylint: disable=too-many-instance-attributes
self.addstr(y_start + 2, self.x + 80 + left_width + 1, '') self.addstr(y_start + 2, self.x + 80 + left_width + 1, '')
else: else:
matrix = [ matrix = [
( [
self.x + 80, (
y_start, self.x + 80,
remaining_width - 3, remaining_width - 3,
'MEM', 'MEM',
device.memory_percent, device.memory_percent,
device.memory_display_color, device.memory_display_color,
), device.memory_used_human,
( ),
self.x + 80, ],
y_start + 1, [
remaining_width - 3, (
'UTL', self.x + 80,
device.gpu_utilization, remaining_width - 3,
device.gpu_display_color, 'UTL',
), device.gpu_utilization,
device.gpu_display_color,
f'@ {device.clock_infos.sm}MHz',
),
],
] ]
for x_offset, y, width, prefix, utilization, color in matrix: for y, row in enumerate(matrix, start=y_start):
# pylint: disable-next=disallowed-name for x_offset, width, prefix, utilization, color, extra_text in row:
bar = make_bar(prefix, utilization, width=width) # pylint: disable-next=disallowed-name
self.addstr(y, x_offset - 2, f'{bar}') bar = make_bar(
if self.TERM_256COLOR: prefix,
parts = bar.rstrip().split(' ') utilization,
prefix_len = len(parts[0]) width=width,
bar_len = len(parts[1]) extra_text=extra_text,
full_bar_len = width - prefix_len - 5 swap_text=not extra_text.endswith('MHz'),
self.color_at(y, x_offset, width=width, fg=float(bar_len / full_bar_len)) )
for i, x in enumerate( self.addstr(y, x_offset, f'{bar}')
range(x_offset + prefix_len + 1, x_offset + prefix_len + 1 + bar_len), if self.TERM_256COLOR:
): parts = bar.rstrip().split(' ')
self.color_at(y, x, width=1, fg=float(i / full_bar_len)) prefix_len = len(parts[0])
else: bar_len = len(parts[1])
self.color_at(y, x_offset, width=width, fg=color, attr=attr) full_bar_len = width - prefix_len - 5
self.color_at(
y,
x_offset,
width=width,
fg=float(bar_len / full_bar_len),
)
for i, x in enumerate(
range(
x_offset + prefix_len + 1,
x_offset + prefix_len + 1 + bar_len,
),
):
self.color_at(y, x, width=1, fg=float(i / full_bar_len))
else:
self.color_at(y, x_offset, width=width, fg=color, attr=attr)
y_start += len(fmts) y_start += len(fmts)
prev_device_index = device.tuple_index prev_device_index = device.tuple_index
@ -546,7 +575,7 @@ class DevicePanel(BasePanel): # pylint: disable=too-many-instance-attributes
left_width = (remaining_width - 6 + 1) // 2 - 1 left_width = (remaining_width - 6 + 1) // 2 - 1
right_width = (remaining_width - 6) // 2 + 1 right_width = (remaining_width - 6) // 2 + 1
matrix: list[list[tuple[str, float, str, int]]] = [] matrix: list[list[tuple[str, float, str, int, str]]] = []
if device.is_mig_device: if device.is_mig_device:
matrix = [ matrix = [
[ [
@ -555,6 +584,7 @@ class DevicePanel(BasePanel): # pylint: disable=too-many-instance-attributes
device.memory_percent, device.memory_percent,
device.memory_display_color, device.memory_display_color,
remaining_width - 3, remaining_width - 3,
device.memory_used_human,
), ),
], ],
] ]
@ -573,12 +603,14 @@ class DevicePanel(BasePanel): # pylint: disable=too-many-instance-attributes
device.memory_percent, device.memory_percent,
device.memory_display_color, device.memory_display_color,
left_width, left_width,
device.memory_used_human,
), ),
( (
'MBW', 'MBW',
device.memory_utilization, device.memory_utilization,
device.bandwidth_display_color, device.bandwidth_display_color,
right_width, right_width,
f'@ {device.clock_infos.memory}MHz',
), ),
], ],
[ [
@ -587,12 +619,14 @@ class DevicePanel(BasePanel): # pylint: disable=too-many-instance-attributes
device.gpu_utilization, device.gpu_utilization,
device.gpu_display_color, device.gpu_display_color,
left_width, left_width,
f'@ {device.clock_infos.sm}MHz',
), ),
( (
'PWR', 'PWR',
device.power_utilization, device.power_utilization,
device.power_display_color, device.power_display_color,
right_width, right_width,
f'{device.power_status.partition(" / ")[0]}',
), ),
], ],
] ]
@ -612,6 +646,7 @@ class DevicePanel(BasePanel): # pylint: disable=too-many-instance-attributes
device.memory_percent, device.memory_percent,
device.memory_display_color, device.memory_display_color,
remaining_width - 3, remaining_width - 3,
device.memory_used_human,
), ),
], ],
[ [
@ -620,15 +655,18 @@ class DevicePanel(BasePanel): # pylint: disable=too-many-instance-attributes
device.gpu_utilization, device.gpu_utilization,
device.gpu_display_color, device.gpu_display_color,
remaining_width - 3, remaining_width - 3,
f'@ {device.clock_infos.sm}MHz',
), ),
], ],
] ]
for y, row in enumerate(matrix, start=y_start): for y, row in enumerate(matrix, start=y_start):
for prefix, utilization, color, width in row: for prefix, utilization, color, width, extra_text in row:
bar = make_bar( # pylint: disable=disallowed-name bar = make_bar( # pylint: disable=disallowed-name
prefix, prefix,
utilization, utilization,
width=width, width=width,
extra_text=extra_text,
swap_text=not extra_text.endswith('MHz'),
) )
lines[y] += f' {colored(bar, color)}' # type: ignore[arg-type] lines[y] += f' {colored(bar, color)}' # type: ignore[arg-type]