mirror of
https://github.com/XuehaiPan/nvitop.git
synced 2026-05-15 14:15:55 -06:00
feat(tui/device): add extra information to bar charts
This commit is contained in:
parent
932257a5f9
commit
51ee688d2b
3 changed files with 153 additions and 103 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue