scope_profiler.region_profiler
Profile region classes implementing the strategy pattern for different profiling modes.
Classes
| Name | Description |
|---|---|
AggregateProfileRegion | Low-memory region that records aggregate timing statistics only. |
BaseProfileRegion | Base class providing shared profiling logic. |
CUDATimingNVTXProfileRegion | Region that records CPU/CUDA-event timing and emits an NVTX range. |
CUDATimingProfileRegion | Region that records CPU timing plus CUDA-event elapsed device time. |
DisabledProfileRegion | Profiling region that performs no measurements. |
FullProfileRegion | Region that records both timing and LIKWID metrics, and writes to HDF5. |
LineProfilerRegion | Region that records timing and line-by-line profiling via line_profiler. |
NVTXProfileRegion | Region that records CPU time and emits an NVTX range. |
PerfEventProfileRegion | Timing region which also sums Linux perf_event_open counters. |
ThreadedProfileRegion | Region that records which thread - and which task - each call ran on. |
TimeOnlyProfileRegion | Region that records timing, collected once at the end of the run. |
Functions
| Name | Description |
|---|---|
call_site_source | Source text of the with block starting at lineno in filename. |
function_source | Source file, starting line and text of a decorated function. |
AggregateProfileRegionclass#
class AggregateProfileRegion(region_name, config, tags=())Low-memory region that records aggregate timing statistics only.
configattributeinstance attribute#
config = configregion_nameattributeinstance attribute#
region_name = region_namesource_fileattributeinstance attribute#
source_file = Nonesource_linenoattributeinstance attribute#
source_lineno = Nonesource_textattributeinstance attribute#
source_text = Nonetagsattributeinstance attribute#
tags = tuple(tags)BaseProfileRegionclass#
class BaseProfileRegion(region_name: str, config: ProfilingConfig, tags=())Base class providing shared profiling logic.
Handles start/end time buffering and call counting. The buffers grow on
demand and are copied out once, at the end of the run, by
ProfileManager.finalize() - regions never touch HDF5 themselves.
buffer_limitattributeinstance attribute#
buffer_limit = config.buffer_limitcapacityattributeinstance attribute#
capacity = self.buffer_limitconfigattributeinstance attribute#
config = configend_timesattributeinstance attribute#
end_times = np.zeros(self.capacity, dtype=np.int64)ptrattributeinstance attribute#
ptr = 0region_nameattributeinstance attribute#
region_name = region_namesource_fileattributeinstance attribute#
source_file = Nonesource_linenoattributeinstance attribute#
source_lineno = Nonesource_textattributeinstance attribute#
source_text = Nonestart_timesattributeinstance attribute#
start_times = np.empty(self.capacity, dtype=np.int64)tagsattributeinstance attribute#
tags = tuple(tags)has_sourceproperty#
has_source: boolWhether this region’s call-site source was captured.
num_callsproperty#
num_calls: intTimes this region was entered, for the lifetime of the process.
Derived rather than counted: the slots in use (ptr) plus whatever
earlier finalize() calls already copied out. Keeping it out of
__enter__ removes an attribute write from every recorded call.
add_functionmethod#
def add_function(func) -> NoneRegister a function for profiling. No-op except in LineProfilerRegion.
appendmethod#
def append(start: float, end: float) -> NoneAppend a start/end time pair to the buffer, growing it if needed.
closed_slotsmethod#
def closed_slots() -> np.ndarray | NoneMask of buffered slots this finalize() should copy out.
A slot qualifies once its end time is written and it has not already gone out with an earlier finalize(). None - the usual case - means every slot qualifies and the caller can skip the mask entirely.
get_durations_numpymethod#
def get_durations_numpy() -> np.ndarrayReturn durations (end - start) for buffered entries as a NumPy array.
get_end_times_numpymethod#
def get_end_times_numpy() -> np.ndarrayReturn end times offset by the run’s start time.
get_start_times_numpymethod#
def get_start_times_numpy() -> np.ndarrayReturn start times offset by the run’s start time.
mark_writtenmethod#
def mark_written() -> NoneRecord that everything buffered so far has been handed to finalize().
Called by finalize() once the data has been copied out, so that a
second run in the same process reports only its own events instead of
re-reporting the first run’s. The timestamp buffer rewinds (the arrays
are reused; anything past ptr is unread scratch), while
num_calls keeps counting for the lifetime of the process — it is
the in-memory view of the region, which callers inspect after
finalize().
A call still running has a slot reserved that finalize() did not copy out, so it must survive the rewind. It is moved to the front of the buffer rather than pinning everything behind it: leaving the whole buffer in place would make the next finalize() re-report every completed call sitting below it, with a second set of call ids.
The one case that still cannot rewind is a call entered through the
decorator form, which keeps its slot index in the wrapper’s own frame
where nothing can remap it. Recognisable because such a slot is open
without appearing in _scope_ptr_stack. There the buffer stays put
and the slots already copied out are recorded instead, so the next
finalize() skips them rather than reporting those calls again.
open_slotsmethod#
def open_slots() -> np.ndarrayBuffer slots whose call is still running, in ascending order.
A slot is open until its end time is written, which is what distinguishes a call in flight from one that has returned. Both region forms are covered: the context manager writes its start on entry, the decorator writes nothing until the call returns.
set_sourcemethod#
def set_source(filename, lineno, text) -> NoneRecord where this region is defined, the first time it is called.
First writer wins: a region name reused at more than one call site keeps only the first location, matching how their timings are already pooled together under one name (see issue #161).
wrapmethod#
def wrap(func)Wrap a function for profiling.
Subclasses must override this method to implement the appropriate profiling behavior.
CUDATimingNVTXProfileRegionclass#
class CUDATimingNVTXProfileRegion(region_name: str, config: ProfilingConfig, tags=())Bases: CUDATimingProfileRegion
Region that records CPU/CUDA-event timing and emits an NVTX range.
wrapmethod#
def wrap(func)Wrap a function with CPU/CUDA timing and an NVTX range.
Inherited from scope_profiler.region_profiler.CUDATimingProfileRegion
get_gpu_durations_numpymethod#
def get_gpu_durations_numpy() -> np.ndarraySynchronize recorded CUDA events and return device durations in ns.
Inherited from scope_profiler.region_profiler.BaseProfileRegion
buffer_limitattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcebuffer_limit = config.buffer_limitcapacityattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcecapacity = self.buffer_limitconfigattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceconfig = configend_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceend_times = np.zeros(self.capacity, dtype=np.int64)ptrattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceptr = 0region_nameattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceregion_name = region_namesource_fileattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_file = Nonesource_linenoattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_lineno = Nonesource_textattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_text = Nonestart_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcestart_times = np.empty(self.capacity, dtype=np.int64)tagsattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcetags = tuple(tags)has_sourceproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcehas_source: boolWhether this region’s call-site source was captured.
num_callsproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcenum_calls: intTimes this region was entered, for the lifetime of the process.
Derived rather than counted: the slots in use (ptr) plus whatever
earlier finalize() calls already copied out. Keeping it out of
__enter__ removes an attribute write from every recorded call.
add_functionmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef add_function(func) -> NoneRegister a function for profiling. No-op except in LineProfilerRegion.
appendmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef append(start: float, end: float) -> NoneAppend a start/end time pair to the buffer, growing it if needed.
closed_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef closed_slots() -> np.ndarray | NoneMask of buffered slots this finalize() should copy out.
A slot qualifies once its end time is written and it has not already gone out with an earlier finalize(). None - the usual case - means every slot qualifies and the caller can skip the mask entirely.
get_durations_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_durations_numpy() -> np.ndarrayReturn durations (end - start) for buffered entries as a NumPy array.
get_end_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_end_times_numpy() -> np.ndarrayReturn end times offset by the run’s start time.
get_start_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_start_times_numpy() -> np.ndarrayReturn start times offset by the run’s start time.
mark_writtenmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef mark_written() -> NoneRecord that everything buffered so far has been handed to finalize().
Called by finalize() once the data has been copied out, so that a
second run in the same process reports only its own events instead of
re-reporting the first run’s. The timestamp buffer rewinds (the arrays
are reused; anything past ptr is unread scratch), while
num_calls keeps counting for the lifetime of the process — it is
the in-memory view of the region, which callers inspect after
finalize().
A call still running has a slot reserved that finalize() did not copy out, so it must survive the rewind. It is moved to the front of the buffer rather than pinning everything behind it: leaving the whole buffer in place would make the next finalize() re-report every completed call sitting below it, with a second set of call ids.
The one case that still cannot rewind is a call entered through the
decorator form, which keeps its slot index in the wrapper’s own frame
where nothing can remap it. Recognisable because such a slot is open
without appearing in _scope_ptr_stack. There the buffer stays put
and the slots already copied out are recorded instead, so the next
finalize() skips them rather than reporting those calls again.
open_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef open_slots() -> np.ndarrayBuffer slots whose call is still running, in ascending order.
A slot is open until its end time is written, which is what distinguishes a call in flight from one that has returned. Both region forms are covered: the context manager writes its start on entry, the decorator writes nothing until the call returns.
set_sourcemethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef set_source(filename, lineno, text) -> NoneRecord where this region is defined, the first time it is called.
First writer wins: a region name reused at more than one call site keeps only the first location, matching how their timings are already pooled together under one name (see issue #161).
CUDATimingProfileRegionclass#
class CUDATimingProfileRegion(region_name: str, config: ProfilingConfig, tags=())Bases: TimeOnlyProfileRegion
Region that records CPU timing plus CUDA-event elapsed device time.
get_gpu_durations_numpymethod#
def get_gpu_durations_numpy() -> np.ndarraySynchronize recorded CUDA events and return device durations in ns.
wrapmethod#
def wrap(func)Wrap a function to measure CPU enqueue time and device elapsed time.
Inherited from scope_profiler.region_profiler.BaseProfileRegion
buffer_limitattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcebuffer_limit = config.buffer_limitcapacityattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcecapacity = self.buffer_limitconfigattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceconfig = configend_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceend_times = np.zeros(self.capacity, dtype=np.int64)ptrattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceptr = 0region_nameattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceregion_name = region_namesource_fileattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_file = Nonesource_linenoattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_lineno = Nonesource_textattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_text = Nonestart_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcestart_times = np.empty(self.capacity, dtype=np.int64)tagsattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcetags = tuple(tags)has_sourceproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcehas_source: boolWhether this region’s call-site source was captured.
num_callsproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcenum_calls: intTimes this region was entered, for the lifetime of the process.
Derived rather than counted: the slots in use (ptr) plus whatever
earlier finalize() calls already copied out. Keeping it out of
__enter__ removes an attribute write from every recorded call.
add_functionmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef add_function(func) -> NoneRegister a function for profiling. No-op except in LineProfilerRegion.
appendmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef append(start: float, end: float) -> NoneAppend a start/end time pair to the buffer, growing it if needed.
closed_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef closed_slots() -> np.ndarray | NoneMask of buffered slots this finalize() should copy out.
A slot qualifies once its end time is written and it has not already gone out with an earlier finalize(). None - the usual case - means every slot qualifies and the caller can skip the mask entirely.
get_durations_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_durations_numpy() -> np.ndarrayReturn durations (end - start) for buffered entries as a NumPy array.
get_end_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_end_times_numpy() -> np.ndarrayReturn end times offset by the run’s start time.
get_start_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_start_times_numpy() -> np.ndarrayReturn start times offset by the run’s start time.
mark_writtenmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef mark_written() -> NoneRecord that everything buffered so far has been handed to finalize().
Called by finalize() once the data has been copied out, so that a
second run in the same process reports only its own events instead of
re-reporting the first run’s. The timestamp buffer rewinds (the arrays
are reused; anything past ptr is unread scratch), while
num_calls keeps counting for the lifetime of the process — it is
the in-memory view of the region, which callers inspect after
finalize().
A call still running has a slot reserved that finalize() did not copy out, so it must survive the rewind. It is moved to the front of the buffer rather than pinning everything behind it: leaving the whole buffer in place would make the next finalize() re-report every completed call sitting below it, with a second set of call ids.
The one case that still cannot rewind is a call entered through the
decorator form, which keeps its slot index in the wrapper’s own frame
where nothing can remap it. Recognisable because such a slot is open
without appearing in _scope_ptr_stack. There the buffer stays put
and the slots already copied out are recorded instead, so the next
finalize() skips them rather than reporting those calls again.
open_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef open_slots() -> np.ndarrayBuffer slots whose call is still running, in ascending order.
A slot is open until its end time is written, which is what distinguishes a call in flight from one that has returned. Both region forms are covered: the context manager writes its start on entry, the decorator writes nothing until the call returns.
set_sourcemethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef set_source(filename, lineno, text) -> NoneRecord where this region is defined, the first time it is called.
First writer wins: a region name reused at more than one call site keeps only the first location, matching how their timings are already pooled together under one name (see issue #161).
DisabledProfileRegionclass#
class DisabledProfileRegion(BaseProfileRegion)Bases: BaseProfileRegion
Profiling region that performs no measurements.
Used when profiling is disabled but code paths must remain valid.
appendmethod#
def append(start, end)Ignored: no data recorded.
get_durations_numpymethod#
def get_durations_numpy()Return an empty array since nothing is recorded.
wrapmethod#
def wrap(func)Return the original function unchanged — no wrapper, no overhead.
Inherited from scope_profiler.region_profiler.BaseProfileRegion
buffer_limitattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcebuffer_limit = config.buffer_limitcapacityattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcecapacity = self.buffer_limitconfigattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceconfig = configend_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceend_times = np.zeros(self.capacity, dtype=np.int64)ptrattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceptr = 0region_nameattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceregion_name = region_namesource_fileattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_file = Nonesource_linenoattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_lineno = Nonesource_textattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_text = Nonestart_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcestart_times = np.empty(self.capacity, dtype=np.int64)tagsattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcetags = tuple(tags)has_sourceproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcehas_source: boolWhether this region’s call-site source was captured.
num_callsproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcenum_calls: intTimes this region was entered, for the lifetime of the process.
Derived rather than counted: the slots in use (ptr) plus whatever
earlier finalize() calls already copied out. Keeping it out of
__enter__ removes an attribute write from every recorded call.
add_functionmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef add_function(func) -> NoneRegister a function for profiling. No-op except in LineProfilerRegion.
closed_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef closed_slots() -> np.ndarray | NoneMask of buffered slots this finalize() should copy out.
A slot qualifies once its end time is written and it has not already gone out with an earlier finalize(). None - the usual case - means every slot qualifies and the caller can skip the mask entirely.
get_end_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_end_times_numpy() -> np.ndarrayReturn end times offset by the run’s start time.
get_start_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_start_times_numpy() -> np.ndarrayReturn start times offset by the run’s start time.
mark_writtenmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef mark_written() -> NoneRecord that everything buffered so far has been handed to finalize().
Called by finalize() once the data has been copied out, so that a
second run in the same process reports only its own events instead of
re-reporting the first run’s. The timestamp buffer rewinds (the arrays
are reused; anything past ptr is unread scratch), while
num_calls keeps counting for the lifetime of the process — it is
the in-memory view of the region, which callers inspect after
finalize().
A call still running has a slot reserved that finalize() did not copy out, so it must survive the rewind. It is moved to the front of the buffer rather than pinning everything behind it: leaving the whole buffer in place would make the next finalize() re-report every completed call sitting below it, with a second set of call ids.
The one case that still cannot rewind is a call entered through the
decorator form, which keeps its slot index in the wrapper’s own frame
where nothing can remap it. Recognisable because such a slot is open
without appearing in _scope_ptr_stack. There the buffer stays put
and the slots already copied out are recorded instead, so the next
finalize() skips them rather than reporting those calls again.
open_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef open_slots() -> np.ndarrayBuffer slots whose call is still running, in ascending order.
A slot is open until its end time is written, which is what distinguishes a call in flight from one that has returned. Both region forms are covered: the context manager writes its start on entry, the decorator writes nothing until the call returns.
set_sourcemethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef set_source(filename, lineno, text) -> NoneRecord where this region is defined, the first time it is called.
First writer wins: a region name reused at more than one call site keeps only the first location, matching how their timings are already pooled together under one name (see issue #161).
FullProfileRegionclass#
class FullProfileRegion(region_name: str, config: ProfilingConfig, tags=())Bases: BaseProfileRegion
Region that records both timing and LIKWID metrics, and writes to HDF5.
This is the most complete profiling mode: users obtain LIKWID markers and nanosecond-resolution timing.
likwid_marker_startattributeinstance attribute#
likwid_marker_start = pylikwid.markerstartregionlikwid_marker_stopattributeinstance attribute#
likwid_marker_stop = pylikwid.markerstopregionwrapmethod#
def wrap(func)Wrap a function to measure time and collect LIKWID metrics.
Inherited from scope_profiler.region_profiler.BaseProfileRegion
buffer_limitattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcebuffer_limit = config.buffer_limitcapacityattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcecapacity = self.buffer_limitconfigattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceconfig = configend_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceend_times = np.zeros(self.capacity, dtype=np.int64)ptrattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceptr = 0region_nameattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceregion_name = region_namesource_fileattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_file = Nonesource_linenoattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_lineno = Nonesource_textattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_text = Nonestart_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcestart_times = np.empty(self.capacity, dtype=np.int64)tagsattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcetags = tuple(tags)has_sourceproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcehas_source: boolWhether this region’s call-site source was captured.
num_callsproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcenum_calls: intTimes this region was entered, for the lifetime of the process.
Derived rather than counted: the slots in use (ptr) plus whatever
earlier finalize() calls already copied out. Keeping it out of
__enter__ removes an attribute write from every recorded call.
add_functionmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef add_function(func) -> NoneRegister a function for profiling. No-op except in LineProfilerRegion.
appendmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef append(start: float, end: float) -> NoneAppend a start/end time pair to the buffer, growing it if needed.
closed_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef closed_slots() -> np.ndarray | NoneMask of buffered slots this finalize() should copy out.
A slot qualifies once its end time is written and it has not already gone out with an earlier finalize(). None - the usual case - means every slot qualifies and the caller can skip the mask entirely.
get_durations_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_durations_numpy() -> np.ndarrayReturn durations (end - start) for buffered entries as a NumPy array.
get_end_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_end_times_numpy() -> np.ndarrayReturn end times offset by the run’s start time.
get_start_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_start_times_numpy() -> np.ndarrayReturn start times offset by the run’s start time.
mark_writtenmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef mark_written() -> NoneRecord that everything buffered so far has been handed to finalize().
Called by finalize() once the data has been copied out, so that a
second run in the same process reports only its own events instead of
re-reporting the first run’s. The timestamp buffer rewinds (the arrays
are reused; anything past ptr is unread scratch), while
num_calls keeps counting for the lifetime of the process — it is
the in-memory view of the region, which callers inspect after
finalize().
A call still running has a slot reserved that finalize() did not copy out, so it must survive the rewind. It is moved to the front of the buffer rather than pinning everything behind it: leaving the whole buffer in place would make the next finalize() re-report every completed call sitting below it, with a second set of call ids.
The one case that still cannot rewind is a call entered through the
decorator form, which keeps its slot index in the wrapper’s own frame
where nothing can remap it. Recognisable because such a slot is open
without appearing in _scope_ptr_stack. There the buffer stays put
and the slots already copied out are recorded instead, so the next
finalize() skips them rather than reporting those calls again.
open_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef open_slots() -> np.ndarrayBuffer slots whose call is still running, in ascending order.
A slot is open until its end time is written, which is what distinguishes a call in flight from one that has returned. Both region forms are covered: the context manager writes its start on entry, the decorator writes nothing until the call returns.
set_sourcemethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef set_source(filename, lineno, text) -> NoneRecord where this region is defined, the first time it is called.
First writer wins: a region name reused at more than one call site keeps only the first location, matching how their timings are already pooled together under one name (see issue #161).
LineProfilerRegionclass#
class LineProfilerRegion(region_name: str, config: ProfilingConfig, tags=())Bases: BaseProfileRegion
Region that records timing and line-by-line profiling via line_profiler.
Uses line_profiler to collect per-line execution statistics for decorated functions. Also records nanosecond timestamps.
Line-by-line profiling is most useful with the decorator (wrap) path,
which automatically registers the function with the line profiler. When
used as a context manager, the profiler is enabled/disabled around the
block - any functions previously added via the decorator path will be
profiled while the context is active.
add_functionmethod#
def add_function(func) -> NoneRegister a function for line-by-line profiling.
enter_framemethod#
def enter_frame(frame)Enter this region while registering frame with line_profiler.
enter_timing_onlymethod#
def enter_timing_only()Enter this region without registering or enabling line_profiler.
get_statsmethod#
def get_stats()Return the line_profiler stats object.
manual_line_recordsmethod#
def manual_line_records(unit: float = 1e-09) -> listReturn manually traced line timings in the persisted record shape.
print_statsmethod#
def print_stats()Print line-by-line profiling statistics.
record_line_timingmethod#
def record_line_timing(frame, lineno: int, duration_ns: int) -> NoneRecord one line timing sample from recursive CLI tracing.
wrapmethod#
def wrap(func)Wrap a function to measure execution time and collect line-by-line stats.
Inherited from scope_profiler.region_profiler.BaseProfileRegion
buffer_limitattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcebuffer_limit = config.buffer_limitcapacityattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcecapacity = self.buffer_limitconfigattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceconfig = configend_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceend_times = np.zeros(self.capacity, dtype=np.int64)ptrattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceptr = 0region_nameattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceregion_name = region_namesource_fileattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_file = Nonesource_linenoattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_lineno = Nonesource_textattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_text = Nonestart_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcestart_times = np.empty(self.capacity, dtype=np.int64)tagsattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcetags = tuple(tags)has_sourceproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcehas_source: boolWhether this region’s call-site source was captured.
num_callsproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcenum_calls: intTimes this region was entered, for the lifetime of the process.
Derived rather than counted: the slots in use (ptr) plus whatever
earlier finalize() calls already copied out. Keeping it out of
__enter__ removes an attribute write from every recorded call.
appendmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef append(start: float, end: float) -> NoneAppend a start/end time pair to the buffer, growing it if needed.
closed_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef closed_slots() -> np.ndarray | NoneMask of buffered slots this finalize() should copy out.
A slot qualifies once its end time is written and it has not already gone out with an earlier finalize(). None - the usual case - means every slot qualifies and the caller can skip the mask entirely.
get_durations_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_durations_numpy() -> np.ndarrayReturn durations (end - start) for buffered entries as a NumPy array.
get_end_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_end_times_numpy() -> np.ndarrayReturn end times offset by the run’s start time.
get_start_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_start_times_numpy() -> np.ndarrayReturn start times offset by the run’s start time.
mark_writtenmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef mark_written() -> NoneRecord that everything buffered so far has been handed to finalize().
Called by finalize() once the data has been copied out, so that a
second run in the same process reports only its own events instead of
re-reporting the first run’s. The timestamp buffer rewinds (the arrays
are reused; anything past ptr is unread scratch), while
num_calls keeps counting for the lifetime of the process — it is
the in-memory view of the region, which callers inspect after
finalize().
A call still running has a slot reserved that finalize() did not copy out, so it must survive the rewind. It is moved to the front of the buffer rather than pinning everything behind it: leaving the whole buffer in place would make the next finalize() re-report every completed call sitting below it, with a second set of call ids.
The one case that still cannot rewind is a call entered through the
decorator form, which keeps its slot index in the wrapper’s own frame
where nothing can remap it. Recognisable because such a slot is open
without appearing in _scope_ptr_stack. There the buffer stays put
and the slots already copied out are recorded instead, so the next
finalize() skips them rather than reporting those calls again.
open_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef open_slots() -> np.ndarrayBuffer slots whose call is still running, in ascending order.
A slot is open until its end time is written, which is what distinguishes a call in flight from one that has returned. Both region forms are covered: the context manager writes its start on entry, the decorator writes nothing until the call returns.
set_sourcemethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef set_source(filename, lineno, text) -> NoneRecord where this region is defined, the first time it is called.
First writer wins: a region name reused at more than one call site keeps only the first location, matching how their timings are already pooled together under one name (see issue #161).
NVTXProfileRegionclass#
class NVTXProfileRegion(region_name: str, config: ProfilingConfig, tags=())Bases: TimeOnlyProfileRegion
Region that records CPU time and emits an NVTX range.
NVTX is an annotation API, not a GPU timing API. Nsight Systems and Nsight Compute consume the ranges and correlate them with GPU work. The normal CPU timestamps are retained in the scope-profiler result.
wrapmethod#
def wrap(func)Wrap a function with both CPU timing and an NVTX range.
Inherited from scope_profiler.region_profiler.BaseProfileRegion
buffer_limitattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcebuffer_limit = config.buffer_limitcapacityattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcecapacity = self.buffer_limitconfigattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceconfig = configend_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceend_times = np.zeros(self.capacity, dtype=np.int64)ptrattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceptr = 0region_nameattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceregion_name = region_namesource_fileattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_file = Nonesource_linenoattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_lineno = Nonesource_textattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_text = Nonestart_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcestart_times = np.empty(self.capacity, dtype=np.int64)tagsattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcetags = tuple(tags)has_sourceproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcehas_source: boolWhether this region’s call-site source was captured.
num_callsproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcenum_calls: intTimes this region was entered, for the lifetime of the process.
Derived rather than counted: the slots in use (ptr) plus whatever
earlier finalize() calls already copied out. Keeping it out of
__enter__ removes an attribute write from every recorded call.
add_functionmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef add_function(func) -> NoneRegister a function for profiling. No-op except in LineProfilerRegion.
appendmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef append(start: float, end: float) -> NoneAppend a start/end time pair to the buffer, growing it if needed.
closed_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef closed_slots() -> np.ndarray | NoneMask of buffered slots this finalize() should copy out.
A slot qualifies once its end time is written and it has not already gone out with an earlier finalize(). None - the usual case - means every slot qualifies and the caller can skip the mask entirely.
get_durations_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_durations_numpy() -> np.ndarrayReturn durations (end - start) for buffered entries as a NumPy array.
get_end_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_end_times_numpy() -> np.ndarrayReturn end times offset by the run’s start time.
get_start_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_start_times_numpy() -> np.ndarrayReturn start times offset by the run’s start time.
mark_writtenmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef mark_written() -> NoneRecord that everything buffered so far has been handed to finalize().
Called by finalize() once the data has been copied out, so that a
second run in the same process reports only its own events instead of
re-reporting the first run’s. The timestamp buffer rewinds (the arrays
are reused; anything past ptr is unread scratch), while
num_calls keeps counting for the lifetime of the process — it is
the in-memory view of the region, which callers inspect after
finalize().
A call still running has a slot reserved that finalize() did not copy out, so it must survive the rewind. It is moved to the front of the buffer rather than pinning everything behind it: leaving the whole buffer in place would make the next finalize() re-report every completed call sitting below it, with a second set of call ids.
The one case that still cannot rewind is a call entered through the
decorator form, which keeps its slot index in the wrapper’s own frame
where nothing can remap it. Recognisable because such a slot is open
without appearing in _scope_ptr_stack. There the buffer stays put
and the slots already copied out are recorded instead, so the next
finalize() skips them rather than reporting those calls again.
open_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef open_slots() -> np.ndarrayBuffer slots whose call is still running, in ascending order.
A slot is open until its end time is written, which is what distinguishes a call in flight from one that has returned. Both region forms are covered: the context manager writes its start on entry, the decorator writes nothing until the call returns.
set_sourcemethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef set_source(filename, lineno, text) -> NoneRecord where this region is defined, the first time it is called.
First writer wins: a region name reused at more than one call site keeps only the first location, matching how their timings are already pooled together under one name (see issue #161).
PerfEventProfileRegionclass#
class PerfEventProfileRegion(region_name: str, config: ProfilingConfig, tags=())Bases: TimeOnlyProfileRegion
Timing region which also sums Linux perf_event_open counters.
Counters are opened per active invocation. This makes nested and recursive regions correct without sharing a mutable counter state, at the intended cost of an extra kernel round trip per selected event.
perf_event_totalsmethod#
def perf_event_totals() -> PerfEventTotalsCounter totals accumulated by completed calls in this region.
wrapmethod#
def wrap(func)Inherited from scope_profiler.region_profiler.BaseProfileRegion
buffer_limitattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcebuffer_limit = config.buffer_limitcapacityattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcecapacity = self.buffer_limitconfigattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceconfig = configend_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceend_times = np.zeros(self.capacity, dtype=np.int64)ptrattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceptr = 0region_nameattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceregion_name = region_namesource_fileattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_file = Nonesource_linenoattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_lineno = Nonesource_textattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_text = Nonestart_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcestart_times = np.empty(self.capacity, dtype=np.int64)tagsattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcetags = tuple(tags)has_sourceproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcehas_source: boolWhether this region’s call-site source was captured.
num_callsproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcenum_calls: intTimes this region was entered, for the lifetime of the process.
Derived rather than counted: the slots in use (ptr) plus whatever
earlier finalize() calls already copied out. Keeping it out of
__enter__ removes an attribute write from every recorded call.
add_functionmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef add_function(func) -> NoneRegister a function for profiling. No-op except in LineProfilerRegion.
appendmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef append(start: float, end: float) -> NoneAppend a start/end time pair to the buffer, growing it if needed.
closed_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef closed_slots() -> np.ndarray | NoneMask of buffered slots this finalize() should copy out.
A slot qualifies once its end time is written and it has not already gone out with an earlier finalize(). None - the usual case - means every slot qualifies and the caller can skip the mask entirely.
get_durations_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_durations_numpy() -> np.ndarrayReturn durations (end - start) for buffered entries as a NumPy array.
get_end_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_end_times_numpy() -> np.ndarrayReturn end times offset by the run’s start time.
get_start_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_start_times_numpy() -> np.ndarrayReturn start times offset by the run’s start time.
mark_writtenmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef mark_written() -> NoneRecord that everything buffered so far has been handed to finalize().
Called by finalize() once the data has been copied out, so that a
second run in the same process reports only its own events instead of
re-reporting the first run’s. The timestamp buffer rewinds (the arrays
are reused; anything past ptr is unread scratch), while
num_calls keeps counting for the lifetime of the process — it is
the in-memory view of the region, which callers inspect after
finalize().
A call still running has a slot reserved that finalize() did not copy out, so it must survive the rewind. It is moved to the front of the buffer rather than pinning everything behind it: leaving the whole buffer in place would make the next finalize() re-report every completed call sitting below it, with a second set of call ids.
The one case that still cannot rewind is a call entered through the
decorator form, which keeps its slot index in the wrapper’s own frame
where nothing can remap it. Recognisable because such a slot is open
without appearing in _scope_ptr_stack. There the buffer stays put
and the slots already copied out are recorded instead, so the next
finalize() skips them rather than reporting those calls again.
open_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef open_slots() -> np.ndarrayBuffer slots whose call is still running, in ascending order.
A slot is open until its end time is written, which is what distinguishes a call in flight from one that has returned. Both region forms are covered: the context manager writes its start on entry, the decorator writes nothing until the call returns.
set_sourcemethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef set_source(filename, lineno, text) -> NoneRecord where this region is defined, the first time it is called.
First writer wins: a region name reused at more than one call site keeps only the first location, matching how their timings are already pooled together under one name (see issue #161).
ThreadedProfileRegionclass#
class ThreadedProfileRegion(region_name: str, config: ProfilingConfig, tags=())Bases: BaseProfileRegion
Region that records which thread - and which task - each call ran on.
Selected by track_threads=True. Two things change against
:class:TimeOnlyProfileRegion:
- every thread gets its own buffers and its own scope stack, so concurrent calls no longer overwrite each other’s reserved slots or close each other’s scopes;
- each recorded call carries the lane it ran on, so the nesting
reconstruction can group calls into stacks that really are stacks (see
:func:
~scope_profiler.concurrency.lane_ids).
With track_async=True a call additionally carries the id of the
asyncio task or greenlet it ran in, and the time that task spent suspended
inside the call - the await time of that one call, as opposed to the
task’s total.
The per-call cost over :class:TimeOnlyProfileRegion is one thread-local
lookup plus, in async mode, two integer reads off the current task record.
Nothing here allocates or locks per call.
num_callsproperty#
num_calls: intTimes this region was entered, over every thread, for the process.
threadsproperty#
threads: listThread records that have entered this region, in index order.
closed_slotsmethod#
def closed_slots()Not meaningful per lane; :meth:snapshot_arrays applies the mask.
None, as the base class means it: every slot qualifies, and there is no mask for a caller to apply. A threaded region keeps no buffers of its own, so there is nothing here to mask in the first place.
mark_writtenmethod#
def mark_written() -> NoneRewind every lane, keeping calls that are still running.
open_slotsmethod#
def open_slots() -> np.ndarraySlots still running, over every lane. For diagnostics only.
snapshot_arraysmethod#
def snapshot_arrays()This run’s completed calls, concatenated over every thread.
Returns
tuple or None
(start_times, end_times, None, None, None, thread_ids, task_ids, await_ns) in nanoseconds, laid out on the snapshot
tuple :meth:ProfileManager._snapshot_regions documents, or None
when this region recorded nothing since the last finalize().
task_ids and await_ns are None unless async tracking is on.
wrapmethod#
def wrap(func)Wrap a function so its calls are recorded on the caller’s thread.
Inherited from scope_profiler.region_profiler.BaseProfileRegion
buffer_limitattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcebuffer_limit = config.buffer_limitcapacityattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcecapacity = self.buffer_limitconfigattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceconfig = configend_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceend_times = np.zeros(self.capacity, dtype=np.int64)ptrattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceptr = 0region_nameattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceregion_name = region_namesource_fileattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_file = Nonesource_linenoattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_lineno = Nonesource_textattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_text = Nonestart_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcestart_times = np.empty(self.capacity, dtype=np.int64)tagsattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcetags = tuple(tags)has_sourceproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcehas_source: boolWhether this region’s call-site source was captured.
add_functionmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef add_function(func) -> NoneRegister a function for profiling. No-op except in LineProfilerRegion.
appendmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef append(start: float, end: float) -> NoneAppend a start/end time pair to the buffer, growing it if needed.
get_durations_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_durations_numpy() -> np.ndarrayReturn durations (end - start) for buffered entries as a NumPy array.
get_end_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_end_times_numpy() -> np.ndarrayReturn end times offset by the run’s start time.
get_start_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_start_times_numpy() -> np.ndarrayReturn start times offset by the run’s start time.
set_sourcemethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef set_source(filename, lineno, text) -> NoneRecord where this region is defined, the first time it is called.
First writer wins: a region name reused at more than one call site keeps only the first location, matching how their timings are already pooled together under one name (see issue #161).
TimeOnlyProfileRegionclass#
class TimeOnlyProfileRegion(BaseProfileRegion)Bases: BaseProfileRegion
Region that records timing, collected once at the end of the run.
wrapmethod#
def wrap(func)Wrap a function to measure its execution time.
Inherited from scope_profiler.region_profiler.BaseProfileRegion
buffer_limitattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcebuffer_limit = config.buffer_limitcapacityattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcecapacity = self.buffer_limitconfigattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceconfig = configend_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceend_times = np.zeros(self.capacity, dtype=np.int64)ptrattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceptr = 0region_nameattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourceregion_name = region_namesource_fileattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_file = Nonesource_linenoattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_lineno = Nonesource_textattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcesource_text = Nonestart_timesattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcestart_times = np.empty(self.capacity, dtype=np.int64)tagsattributeinstance attribute#
scope_profiler.region_profiler.BaseProfileRegionView sourcetags = tuple(tags)has_sourceproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcehas_source: boolWhether this region’s call-site source was captured.
num_callsproperty#
scope_profiler.region_profiler.BaseProfileRegionView sourcenum_calls: intTimes this region was entered, for the lifetime of the process.
Derived rather than counted: the slots in use (ptr) plus whatever
earlier finalize() calls already copied out. Keeping it out of
__enter__ removes an attribute write from every recorded call.
add_functionmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef add_function(func) -> NoneRegister a function for profiling. No-op except in LineProfilerRegion.
appendmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef append(start: float, end: float) -> NoneAppend a start/end time pair to the buffer, growing it if needed.
closed_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef closed_slots() -> np.ndarray | NoneMask of buffered slots this finalize() should copy out.
A slot qualifies once its end time is written and it has not already gone out with an earlier finalize(). None - the usual case - means every slot qualifies and the caller can skip the mask entirely.
get_durations_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_durations_numpy() -> np.ndarrayReturn durations (end - start) for buffered entries as a NumPy array.
get_end_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_end_times_numpy() -> np.ndarrayReturn end times offset by the run’s start time.
get_start_times_numpymethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef get_start_times_numpy() -> np.ndarrayReturn start times offset by the run’s start time.
mark_writtenmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef mark_written() -> NoneRecord that everything buffered so far has been handed to finalize().
Called by finalize() once the data has been copied out, so that a
second run in the same process reports only its own events instead of
re-reporting the first run’s. The timestamp buffer rewinds (the arrays
are reused; anything past ptr is unread scratch), while
num_calls keeps counting for the lifetime of the process — it is
the in-memory view of the region, which callers inspect after
finalize().
A call still running has a slot reserved that finalize() did not copy out, so it must survive the rewind. It is moved to the front of the buffer rather than pinning everything behind it: leaving the whole buffer in place would make the next finalize() re-report every completed call sitting below it, with a second set of call ids.
The one case that still cannot rewind is a call entered through the
decorator form, which keeps its slot index in the wrapper’s own frame
where nothing can remap it. Recognisable because such a slot is open
without appearing in _scope_ptr_stack. There the buffer stays put
and the slots already copied out are recorded instead, so the next
finalize() skips them rather than reporting those calls again.
open_slotsmethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef open_slots() -> np.ndarrayBuffer slots whose call is still running, in ascending order.
A slot is open until its end time is written, which is what distinguishes a call in flight from one that has returned. Both region forms are covered: the context manager writes its start on entry, the decorator writes nothing until the call returns.
set_sourcemethod#
scope_profiler.region_profiler.BaseProfileRegionView sourcedef set_source(filename, lineno, text) -> NoneRecord where this region is defined, the first time it is called.
First writer wins: a region name reused at more than one call site keeps only the first location, matching how their timings are already pooled together under one name (see issue #161).
call_site_sourcefunction#
def call_site_source(filename: str, lineno: int) -> str | NoneSource text of the with block starting at lineno in filename.
Falls back to just the call-site line when the enclosing with
statement cannot be located (e.g. the file cannot be parsed), so a region
still gets some location information rather than none.
function_sourcefunction#
def function_source(func) -> tuple[str, int, str] | NoneSource file, starting line and text of a decorated function.
Returns None when the source cannot be recovered (e.g. a function defined
interactively or via exec).