Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ Collects system performance metrics using Linux sysstat utilities (mpstat, sar,
- `--subtools <list>` — Comma-separated subtools to run (default: `mpstat,sar,iostat,pidstat`)
- `--interval <seconds>` — Collection interval (default: `3`)

## mpstat CPU breakout dimensions
Beyond `num` (CPU number), mpstat metrics carry these CDM breakout dimensions, all derived from sysfs CPU topology data collected by `sysstat-start` and resolved via toolbox's `system_cpu_topology.build_cpu_topology()`/`get_cpu_topology()`/`get_cpu_node()`/`get_cpu_cache_domains()`:
- `cpu` — string alias for `num`, matching the naming already used by `tool-procstat`/`tool-kernel`
- `node` — NUMA node, when determinable. Collected into a `cpu-numa-nodes.txt` manifest by `sysstat-start` rather than copied directly from sysfs: a CPU's `nodeN` entry is a symlink, and sysfs symlinks report a zero apparent size, which breaks `cpio`'s `readlink()` call
- `shared-lN-domain` (e.g. `shared-l1-domain`, `shared-l3-domain`) — one per cache level present on the host, valued as the formatted CPU range sharing that cache instance (e.g. `"0-15"`). Dynamic per-platform on the collection side; registered in CDM's schema as explicit `shared-l1-domain` through `shared-l4-domain` fields rather than a wildcard match

## Conventions
- Primary branch is `master`
- Runs as a profiler tool on master/worker/profiler roles, blocked on client/server
Expand Down
19 changes: 17 additions & 2 deletions sysstat-post-process.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@

from toolbox.cdm_metrics import CDMMetrics
from toolbox.fileio import open_read_text_file
from toolbox.system_cpu_topology import build_cpu_topology, get_cpu_topology
from toolbox.system_cpu_topology import (
build_cpu_topology,
get_cpu_topology,
get_cpu_node,
get_cpu_cache_domains,
)


def build_netdev_types():
Expand Down Expand Up @@ -364,10 +369,20 @@ def process_mpstat(fork_idx, num_forks, log_file, cpu_topo):
if cpu_num % num_forks != fork_idx:
continue
package, die, core, thread = get_cpu_topology(cpu_num, cpu_topo)
node = get_cpu_node(cpu_num, cpu_topo)
cache_domains = get_cpu_cache_domains(cpu_num, cpu_topo)
for cpu_type in cpu_entry:
if cpu_type == "cpu":
continue
names = {"package": package, "die": die, "core": core, "thread": thread, "num": cpu_num, "type": cpu_type}
# "cpu" is a string alias for "num" (kept for backwards
# compatibility) -- stored as a string to match the
# "keyword" mapping type already used by every other tool
# that reports a "cpu" breakout (procstat, kernel).
names = {"package": package, "die": die, "core": core, "thread": thread, "num": cpu_num, "cpu": str(cpu_num), "type": cpu_type}
if node is not None:
names["node"] = str(node)
for level, domain in cache_domains.items():
names[f"shared-l{level}-domain"] = domain
if cpu_type in ("idle", "iowait", "steal"):
desc["type"] = "NonBusy-CPU"
else:
Expand Down
16 changes: 15 additions & 1 deletion sysstat-start
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,21 @@ done

# To be used by mpstat for post-processing
if [ -e /sys/devices/system/cpu/ ]; then
find /sys/devices/system/cpu/ | grep topology | cpio -pdumv --quiet . 2>/dev/null
find /sys/devices/system/cpu/ | grep -E 'topology|cache/index[0-9]+/(level|shared_cpu_list)$' | cpio -pdumv --quiet . 2>/dev/null

# NUMA node per CPU: sysfs exposes this as a nodeN symlink directly
# under each cpuN directory. That symlink reports a zero apparent
# size, which breaks cpio's readlink() call ("Cannot readlink:
# Invalid argument"), so resolve it ourselves into a manifest file
# instead -- same approach as netdev-types.txt below.
for cpu_dir in /sys/devices/system/cpu/cpu[0-9]*; do
for node_path in ${cpu_dir}/node[0-9]*; do
if [ -e "${node_path}" ]; then
echo "$(basename ${cpu_dir}) $(basename ${node_path})" >>cpu-numa-nodes.txt
break
fi
done
done
else
echo "WARNING: could not find /sys/devices/system/cpu/"
fi
Expand Down
Loading