k4bench.analysis.component_detail¶
k4bench.analysis.component_detail ¶
One component of a k4run job, everything the run recorded of it: the numbers a component's detail view shows, gathered from the files the other views read, each computed once here.
The timed run (_components.json, :class:~k4bench.analysis.components.ComponentTiming)
gives its own (self) time in each phase and in each event it ran in, the
thread counters of those calls and what they asked of the allocator; the
memory pass (_heap.json, :class:~k4bench.analysis.heap.ComponentHeap)
gives the heap it held. The two are separate runs of the job, so they are set
side by side only as summaries: an event of one is not an event of the other.
:func:component_summary gives every component's event-loop and lifecycle
numbers at once, :func:component_detail one component's, with its calls
event by event, and :func:component_history one component's across the
runs of a trend window, a run it is missing from left without values, never
zero.
What the numbers do not say:
- when a call started or ended: the auditor records each component's costs per event and per phase, not a timeline of its calls;
- why a counter moved: instructions, cycles, faults and context switches describe the calls, they do not by themselves name a cause;
- whether memory leaked: net allocation is what a call allocated and did not
free, which an ownership transfer (the reader's event data, freed by the
writer) does too. Only the memory pass's growth kept after finalize
(:meth:
~k4bench.analysis.heap.ComponentHeap.summary) is evidence of that.
ComponentDetail
dataclass
¶
ComponentDetail(name: str, identity: Series | None, summary: Series | None, lifecycle: DataFrame, events: DataFrame, heap: Series | None, hardware_counters_error: str | None = None, threads: int = 1)
What one configuration's run recorded of component :attr:name
(:func:component_detail).
component_summary ¶
component_summary(timing: ComponentTiming, *, warm_up: int | None = WARM_UP_EVENT) -> DataFrame
Every component of timing's job, indexed by name in the auditor's order, the warm_up event left out of every number over events.
Columns:
- the :data:
~k4bench.analysis.components.EVENT_LOOP_TIME_COLUMNSof its own wall time (:func:~k4bench.analysis.components.event_loop_time), andp50_sandp95_sof it over the events it ran in; - for each of :data:
SUMMED_METRICS, its sum over the events it ran in (named as the metric),{metric}_events, how many of those events have a value, and{metric}_per_event, the sum over those. A metric the job did not record isNaNwith no events; ipc: instructions over cycles, each summed over the events both were counted in (a ratio of sums, never a mean of ratios), andipc_events, how many;allocations_per_s: its allocations per second of its own time over the events they were counted in;- for each of :data:
~k4bench.analysis.components.INCLUSIVE_METRICS,{metric}_maxand{metric}_medianover the events it ran in, and{metric}_events. They include the nested calls, so they do not add up across components; {phase}_sand{phase}_cpu_sfor each of :data:LIFECYCLE_PHASES: its own wall and CPU time there,NaNwhen it was not called in that phase or the job did not record it.
A component that ran in no event has no time (NaN), never zero, and
the counts of a component that ran stay as recorded, zero included.
Source code in k4bench/analysis/component_detail.py
component_choices ¶
component_choices(timing: ComponentTiming) -> DataFrame
The components of timing's job that can be inspected, indexed by
name in the auditor's order: its algorithms and services
(:data:INSPECTED_CATEGORIES), whether or not they ran, with columns
category and impl. The memory pass and the data flow name the
same components, by the same names.
Source code in k4bench/analysis/component_detail.py
component_detail ¶
component_detail(name: str, timing: ComponentTiming | None, *, summary: DataFrame | None = None, heap_summary: DataFrame | None = None, heap_holders: Iterable[str] | None = None, warm_up: int | None = WARM_UP_EVENT) -> ComponentDetail
What the run recorded of component name in one configuration: from
the timed run's timing (whose :func:component_summary may be passed
as summary, computed once for every component) and from the memory
pass's heap_summary
(:meth:~k4bench.analysis.heap.ComponentHeap.summary), of which only
heap_holders (:meth:~k4bench.analysis.heap.ComponentHeap.holders)
count, when given. Either may be None: the detail then lacks that
run's part.
Source code in k4bench/analysis/component_detail.py
component_history ¶
component_history(summary_trend: DataFrame | None, heap_trend: DataFrame | None, label: str, name: str, runs: DataFrame | None = None) -> DataFrame
Component name of configuration label in each run of the window: one row per run either trend holds (any configuration's), or runs (the window's results, say) holds, in the order measured.
summary_trend is :func:~k4bench.analysis.trend.build_component_summary_trend's,
heap_trend :func:~k4bench.analysis.trend.build_heap_trend's; either
may be None. A run only runs holds, which left no component costs
that could be read, is :data:NOT_TIMED. Columns: the runs' run_id, run_date,
k4h_release_date, k4h_release and x_date; label, name,
as the trend views name a series; status (:data:TIMED,
:data:ABSENT or :data:NOT_TIMED) and heap_status (:data:HELD,
:data:HELD_NONE or :data:NO_MEMORY_PASS); the
:data:TIMED_HISTORY_COLUMNS and :data:HEAP_HISTORY_COLUMNS. A run the
component has no row in leaves them NaN, a gap in a line rather than
a zero.