OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
openswmm::perf Namespace Reference

Classes

class  CounterBatch
 Private counters for one worker in a worksharing phase. Nested batches merge into the enclosing worker's batch. The outer batch merges under one lock after the loop; hydraulic arithmetic is unaffected. When profiling is disabled, no counters are initialized or merged. More...
 
struct  GatedTimer
 
struct  ProcessPhaseName
 
class  ProcessTimer
 
struct  ScopedTimer
 
struct  SigmaEvaluations
 

Typedefs

using FvCounts = std::array<long, n_fv_counter_count>
 
using AllocationSnapshot = void (*)(std::uint64_t*, std::uint64_t*)
 

Enumerations

enum  FvCounter : std::size_t {
  n_fv_substep ,
  n_fv_census ,
  n_fv_census_face ,
  n_fv_invert ,
  n_fv_savestate ,
  n_fv_restore ,
  n_fv_structref ,
  n_fv_alg_visit ,
  n_fv_alg_passthru ,
  n_fv_alg_solve ,
  n_fv_alg_resid ,
  n_fv_alg_flux ,
  n_fv_geom_area ,
  n_fv_geom_width ,
  n_fv_geom_i1 ,
  n_fv_geom_hydrad ,
  n_fv_macro_cycles ,
  n_fv_macro_rejected ,
  n_fv_counter_count
}
 
enum class  ProcessPhase : std::size_t {
  surface_faces ,
  surface_cells ,
  surface_rebuild ,
  surface_boundary ,
  surface_exchange ,
  surface_publish ,
  surface_species ,
  surface_species_cells ,
  surface_reactions ,
  gw_faces ,
  gw_cells ,
  gw_node_exchange ,
  gw_dt ,
  gw_infiltration ,
  gw_species ,
  gw_reactions ,
  gw_sigma_map ,
  heat_columns ,
  surface_quality ,
  runoff ,
  groundwater ,
  lid ,
  lid_nodes ,
  richards ,
  mesh_snow ,
  subcatch_snow ,
  common_source ,
  source_trial ,
  outfall ,
  source_results ,
  engine_source_results ,
  count
}
 
enum class  ProcessCounter : std::size_t {
  sigma_evaluations ,
  sigma_firings ,
  sigma_le_1 ,
  sigma_le_8 ,
  sigma_le_32 ,
  sigma_le_64 ,
  sigma_gt_64 ,
  sigma_map_refreshes ,
  water_trial_copies ,
  source_stage_copies ,
  rk2_snapshots ,
  mesh_snow_copies ,
  count
}
 

Functions

long value (FvCounter counter) noexcept
 Read one process-global completed FV counter total.
 
void reset_fv () noexcept
 Zero FV phase timers and completed counter totals.
 
void dump_fv () noexcept
 One machine-scrapeable line for the FV phase split.
 
std::chrono::steady_clock::time_point now () noexcept
 Sample the steady monotonic clock regardless of profiling enablement.
 
double since (std::chrono::steady_clock::time_point t0) noexcept
 Measure elapsed wall time from a steady-clock sample.
 
bool enabled () noexcept
 Read the process-cached profiling environment gate.
 
void reset_load () noexcept
 Zero load/open/initialize/start phase accumulators.
 
void dump_load () noexcept
 One machine-scrapeable line per phase on stderr.
 
void count (FvCounter counter, long n=1) noexcept
 Accumulate a batch of events into worker-private or serial global counters.
 
AllocationSnapshot allocation_snapshot () noexcept
 
void count (ProcessCounter counter, unsigned long long n=1) noexcept
 
unsigned long long value (ProcessCounter counter) noexcept
 
void clear_process_totals () noexcept
 
void reset_process () noexcept
 
void begin_process_model (const void *model) noexcept
 
void dump_process () noexcept
 
void end_process_model (const void *model, bool report=true) noexcept
 

Variables

double sec_2d_window = 0.0
 
double sec_2d_advance = 0.0
 
double sec_1d_step = 0.0
 
double sec_open_prescan2d = 0.0
 
double sec_open_read = 0.0
 
double sec_read_dispatch = 0.0
 
double sec_open_resolve = 0.0
 
double sec_open_validate = 0.0
 
double sec_res_extfiles = 0.0
 
double sec_res_tables = 0.0
 
double sec_res_transects = 0.0
 
double sec_res_xsect = 0.0
 
double sec_res_shrink = 0.0
 
double sec_init_state = 0.0
 
double sec_init_hydraulics = 0.0
 
double sec_init_hydrology = 0.0
 
double sec_init_quality = 0.0
 
double sec_init_geometry = 0.0
 
double sec_start_iface = 0.0
 
double sec_start_plugins = 0.0
 
double sec_fv_census = 0.0
 
double sec_fv_flux = 0.0
 
double sec_fv_nodesolve = 0.0
 
double sec_fv_positivity = 0.0
 
double sec_fv_cellupdate = 0.0
 
double sec_fv_nodeupdate = 0.0
 
double sec_fv_refreshdep = 0.0
 
double sec_fv_savestate = 0.0
 
double sec_fv_restore = 0.0
 
double sec_fv_structref = 0.0
 
double sec_fv_bndcallback = 0.0
 
double sec_fv_rebuild = 0.0
 
double sec_fv_reconstruct = 0.0
 
double sec_fv_ltsfire = 0.0
 
double sec_fv_settle = 0.0
 
double sec_fv_tier = 0.0
 
FvCounts fv_counts {}
 
thread_local FvCounts * local_fv_counts = nullptr
 
std::mutex fv_counts_mutex
 
thread_local double nested_wall = 0.0
 ScopedTimer that reads the clock only when OPENSWMM_PERF is set.
 
constexpr std::array< ProcessPhaseName, std::size_t(ProcessPhase::count)> process_names
 
std::array< std::atomic< double >, std::size_t(ProcessPhase::count)> process_seconds {}
 
std::array< std::atomic< unsigned long long >, std::size_t(ProcessPhase::count)> process_calls {}
 
std::array< std::atomic< unsigned long long >, std::size_t(ProcessPhase::count)> process_allocations {}
 
std::array< std::atomic< unsigned long long >, std::size_t(ProcessPhase::count)> process_allocated_bytes {}
 
std::atomic< bool > process_attribution_valid {true}
 
std::mutex process_models_mutex
 
std::unordered_set< const void * > process_models
 
bool process_tracking_failed = false
 
constexpr std::array< const char *, std::size_t(ProcessCounter::count)> process_counter_names
 
std::array< std::atomic< unsigned long long >, std::size_t(ProcessCounter::count)> process_counts {}
 

Typedef Documentation

◆ AllocationSnapshot

using openswmm::perf::AllocationSnapshot = void (*)(std::uint64_t*, std::uint64_t*)

◆ FvCounts

using openswmm::perf::FvCounts = std::array<long, n_fv_counter_count>

Enumeration Type Documentation

◆ FvCounter

enum openswmm::perf::FvCounter : std::size_t
Enumerator
n_fv_substep 
n_fv_census 
n_fv_census_face 
n_fv_invert 
n_fv_savestate 
n_fv_restore 
n_fv_structref 
n_fv_alg_visit 
n_fv_alg_passthru 
n_fv_alg_solve 
n_fv_alg_resid 
n_fv_alg_flux 
n_fv_geom_area 
n_fv_geom_width 
n_fv_geom_i1 
n_fv_geom_hydrad 
n_fv_macro_cycles 
n_fv_macro_rejected 
n_fv_counter_count 

◆ ProcessCounter

enum class openswmm::perf::ProcessCounter : std::size_t
strong
Enumerator
sigma_evaluations 
sigma_firings 
sigma_le_1 
sigma_le_8 
sigma_le_32 
sigma_le_64 
sigma_gt_64 
sigma_map_refreshes 
water_trial_copies 
source_stage_copies 
rk2_snapshots 
mesh_snow_copies 
count 

◆ ProcessPhase

enum class openswmm::perf::ProcessPhase : std::size_t
strong
Enumerator
surface_faces 
surface_cells 
surface_rebuild 
surface_boundary 
surface_exchange 
surface_publish 
surface_species 
surface_species_cells 
surface_reactions 
gw_faces 
gw_cells 
gw_node_exchange 
gw_dt 
gw_infiltration 
gw_species 
gw_reactions 
gw_sigma_map 
heat_columns 
surface_quality 
runoff 
groundwater 
lid 
lid_nodes 
richards 
mesh_snow 
subcatch_snow 
common_source 
source_trial 
outfall 
source_results 
engine_source_results 
count 

Function Documentation

◆ allocation_snapshot()

AllocationSnapshot openswmm::perf::allocation_snapshot ( )
inlinenoexcept
Here is the caller graph for this function:

◆ begin_process_model()

void openswmm::perf::begin_process_model ( const void * model)
inlinenoexcept
Here is the call graph for this function:

◆ clear_process_totals()

void openswmm::perf::clear_process_totals ( )
inlinenoexcept
Here is the call graph for this function:
Here is the caller graph for this function:

◆ count() [1/2]

void openswmm::perf::count ( FvCounter counter,
long n = 1 )
inlinenoexcept

Accumulate a batch of events into worker-private or serial global counters.

No-op when profiling is disabled. Parallel callers must install a CounterBatch; without one updates global fv_counts without a lock.

Parameters
[in]counterValid FvCounter below n_fv_counter_count; no bounds check.
[in]nIncrement, default one; may be zero/negative. Caller prevents signed-long overflow.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ count() [2/2]

void openswmm::perf::count ( ProcessCounter counter,
unsigned long long n = 1 )
inlinenoexcept
Here is the call graph for this function:

◆ dump_fv()

void openswmm::perf::dump_fv ( )
inlinenoexcept

One machine-scrapeable line for the FV phase split.

Same [PERF-FV] key=value contract as dump_load(); emitted from close() when OPENSWMM_PERF is set and the FV solver actually ran. Each phase is SELF time: a phase that calls another timed phase is charged only for its own work (see nested_wall), so the phases partition the time rather than overlapping it. total is their sum, NOT the router step — the difference between the two is unattributed time and is itself the useful signal when a phase is missing. It cannot be negative; if it ever is, a timer is nested inside a scope that does not go through GatedTimer.

Note
Emits to stderr whenever called; the caller checks enabled() and serializes access to totals. Printing failures are not returned.
Here is the call graph for this function:

◆ dump_load()

void openswmm::perf::dump_load ( )
inlinenoexcept

One machine-scrapeable line per phase on stderr.

Emitted from close() so all three benchmark cuts (open only, open+initialize, full) report. Format is [PERF-LOAD] key=value pairs in seconds; tests/benchmarks/scripts/ parses it.

Note
Emits to stderr whenever called; the caller checks enabled() and serializes access to totals. Printing failures are not returned.

◆ dump_process()

void openswmm::perf::dump_process ( )
inlinenoexcept
Here is the call graph for this function:
Here is the caller graph for this function:

◆ enabled()

bool openswmm::perf::enabled ( )
inlinenoexcept

Read the process-cached profiling environment gate.

Subsequent environment changes are ignored. C++ function-local static initialization is thread-safe.

Returns
True if OPENSWMM_PERF existed on the first call, including an empty or zero string.
Here is the caller graph for this function:

◆ end_process_model()

void openswmm::perf::end_process_model ( const void * model,
bool report = true )
inlinenoexcept
Here is the call graph for this function:

◆ now()

std::chrono::steady_clock::time_point openswmm::perf::now ( )
inlinenoexcept

Sample the steady monotonic clock regardless of profiling enablement.

Returns
Current steady_clock time point for use with since().
Here is the caller graph for this function:

◆ reset_fv()

void openswmm::perf::reset_fv ( )
inlinenoexcept

Zero FV phase timers and completed counter totals.

Does not reset sec_1d_step or active thread-local batches. Caller invokes only between worksharing regions with no concurrent counter/timer use.

◆ reset_load()

void openswmm::perf::reset_load ( )
inlinenoexcept

Zero load/open/initialize/start phase accumulators.

Does not reset runtime FV/1D/2D totals or environment gate; caller serializes reset with timer updates.

◆ reset_process()

void openswmm::perf::reset_process ( )
inlinenoexcept
Here is the call graph for this function:

◆ since()

double openswmm::perf::since ( std::chrono::steady_clock::time_point t0)
inlinenoexcept

Measure elapsed wall time from a steady-clock sample.

Parameters
[in]t0Earlier steady-clock time point; a future value yields a negative duration.
Returns
now()-t0 in fractional seconds, regardless of profiling enablement.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ value() [1/2]

long openswmm::perf::value ( FvCounter counter)
inlinenoexcept

Read one process-global completed FV counter total.

Read only between worksharing regions or under external synchronization.

Parameters
[in]counterValid FvCounter below n_fv_counter_count; no bounds check.
Returns
Stored count, with no locking or merge of currently active thread-local batches.
Here is the caller graph for this function:

◆ value() [2/2]

unsigned long long openswmm::perf::value ( ProcessCounter counter)
inlinenoexcept

Variable Documentation

◆ fv_counts

FvCounts openswmm::perf::fv_counts {}
inline

◆ fv_counts_mutex

std::mutex openswmm::perf::fv_counts_mutex
inline

◆ local_fv_counts

thread_local FvCounts* openswmm::perf::local_fv_counts = nullptr
inline

◆ nested_wall

thread_local double openswmm::perf::nested_wall = 0.0
inline

ScopedTimer that reads the clock only when OPENSWMM_PERF is set.

ScopedTimer is used at per-routing-step and per-load-phase call sites, where two unconditional clock reads are free. The FV phase timers are not in that regime: a 30 h / 5 s run is ~21,600 routing steps, each of which can carry hundreds of substeps, each carrying a dozen phases. At ~20 ns a read that is seconds of pure instrument on a run that has nothing to do with profiling. enabled() is a cached static bool, so the gated form costs a predicted branch instead. Wall time booked by GatedTimers that opened and closed inside the one currently running on this thread. Read and reset by each timer so that what lands in the accumulator is SELF time.

Without this the phase split double-counts wherever one timed phase calls another, which it does in three places today: restoreState and settleAccumulators both call refreshDepths, and runMacroCycle's boundary callback sits inside the settle window. The visible symptom was total exceeding the routing step it is a breakdown of — the LTS rows of the phase table reported between -7.9 % and -18.1 % "unattributed" time, which is not a quantity that can be negative. A breakdown whose parts can exceed the whole cannot rank optimization targets, which is the only reason these timers exist.

Thread-local because the accumulators are serial-path today but the flux sweep is slated to go parallel; a shared counter would then attribute one thread's children to another thread's parent. Nothing here is atomic and nothing needs to be: a timer only ever touches its own thread's tally.

◆ process_allocated_bytes

std::array<std::atomic<unsigned long long>, std::size_t(ProcessPhase::count)> openswmm::perf::process_allocated_bytes {}
inline

◆ process_allocations

std::array<std::atomic<unsigned long long>, std::size_t(ProcessPhase::count)> openswmm::perf::process_allocations {}
inline

◆ process_attribution_valid

std::atomic<bool> openswmm::perf::process_attribution_valid {true}
inline

◆ process_calls

std::array<std::atomic<unsigned long long>, std::size_t(ProcessPhase::count)> openswmm::perf::process_calls {}
inline

◆ process_counter_names

std::array<const char*, std::size_t(ProcessCounter::count)> openswmm::perf::process_counter_names
inlineconstexpr
Initial value:
{{
"sigma.evaluate", "sigma.firings", "sigma.hist.le1", "sigma.hist.2_8",
"sigma.hist.9_32", "sigma.hist.33_64", "sigma.hist.gt64", "sigma_map.refresh",
"copy.water_trial", "copy.source_stage", "copy.rk2_snapshot", "copy.mesh_snow"
}}

◆ process_counts

std::array<std::atomic<unsigned long long>, std::size_t(ProcessCounter::count)> openswmm::perf::process_counts {}
inline

◆ process_models

std::unordered_set<const void*> openswmm::perf::process_models
inline

◆ process_models_mutex

std::mutex openswmm::perf::process_models_mutex
inline

◆ process_names

std::array<ProcessPhaseName, std::size_t(ProcessPhase::count)> openswmm::perf::process_names
inlineconstexpr
Initial value:
{{
{"2D", "faces"}, {"2D", "cells"}, {"2D", "rebuild"}, {"2D", "boundary"},
{"2D", "exchange"}, {"2D", "publish"}, {"2D", "species_faces"},
{"2D", "species_cells"}, {"2D", "reactions"},
{"GW2D", "faces"}, {"GW2D", "cells"}, {"GW2D", "node_exchange"},
{"GW2D", "refresh_dt"}, {"GW2D", "infiltration"}, {"GW2D", "species"},
{"GW2D", "reactions"}, {"GW2D", "sigma_map"}, {"GW2D", "heat_columns"},
{"2D", "quality"}, {"HYD", "runoff"}, {"HYD", "groundwater"}, {"HYD", "lid"},
{"HYD", "lid_nodes"}, {"HYD", "richards"}, {"HYD", "mesh_snow"},
{"HYD", "subcatch_snow"}, {"HYD", "common_source"}, {"HYD", "source_trial"},
{"HYD", "outfall"}, {"HYD", "source_results"}, {"HYD", "engine_source_results"}
}}

◆ process_seconds

std::array<std::atomic<double>, std::size_t(ProcessPhase::count)> openswmm::perf::process_seconds {}
inline

◆ process_tracking_failed

bool openswmm::perf::process_tracking_failed = false
inline

◆ sec_1d_step

double openswmm::perf::sec_1d_step = 0.0
inline

◆ sec_2d_advance

double openswmm::perf::sec_2d_advance = 0.0
inline

◆ sec_2d_window

double openswmm::perf::sec_2d_window = 0.0
inline

◆ sec_fv_bndcallback

double openswmm::perf::sec_fv_bndcallback = 0.0
inline

◆ sec_fv_cellupdate

double openswmm::perf::sec_fv_cellupdate = 0.0
inline

◆ sec_fv_census

double openswmm::perf::sec_fv_census = 0.0
inline

◆ sec_fv_flux

double openswmm::perf::sec_fv_flux = 0.0
inline

◆ sec_fv_ltsfire

double openswmm::perf::sec_fv_ltsfire = 0.0
inline

◆ sec_fv_nodesolve

double openswmm::perf::sec_fv_nodesolve = 0.0
inline

◆ sec_fv_nodeupdate

double openswmm::perf::sec_fv_nodeupdate = 0.0
inline

◆ sec_fv_positivity

double openswmm::perf::sec_fv_positivity = 0.0
inline

◆ sec_fv_rebuild

double openswmm::perf::sec_fv_rebuild = 0.0
inline

◆ sec_fv_reconstruct

double openswmm::perf::sec_fv_reconstruct = 0.0
inline

◆ sec_fv_refreshdep

double openswmm::perf::sec_fv_refreshdep = 0.0
inline

◆ sec_fv_restore

double openswmm::perf::sec_fv_restore = 0.0
inline

◆ sec_fv_savestate

double openswmm::perf::sec_fv_savestate = 0.0
inline

◆ sec_fv_settle

double openswmm::perf::sec_fv_settle = 0.0
inline

◆ sec_fv_structref

double openswmm::perf::sec_fv_structref = 0.0
inline

◆ sec_fv_tier

double openswmm::perf::sec_fv_tier = 0.0
inline

◆ sec_init_geometry

double openswmm::perf::sec_init_geometry = 0.0
inline

◆ sec_init_hydraulics

double openswmm::perf::sec_init_hydraulics = 0.0
inline

◆ sec_init_hydrology

double openswmm::perf::sec_init_hydrology = 0.0
inline

◆ sec_init_quality

double openswmm::perf::sec_init_quality = 0.0
inline

◆ sec_init_state

double openswmm::perf::sec_init_state = 0.0
inline

◆ sec_open_prescan2d

double openswmm::perf::sec_open_prescan2d = 0.0
inline

◆ sec_open_read

double openswmm::perf::sec_open_read = 0.0
inline

◆ sec_open_resolve

double openswmm::perf::sec_open_resolve = 0.0
inline

◆ sec_open_validate

double openswmm::perf::sec_open_validate = 0.0
inline

◆ sec_read_dispatch

double openswmm::perf::sec_read_dispatch = 0.0
inline

◆ sec_res_extfiles

double openswmm::perf::sec_res_extfiles = 0.0
inline

◆ sec_res_shrink

double openswmm::perf::sec_res_shrink = 0.0
inline

◆ sec_res_tables

double openswmm::perf::sec_res_tables = 0.0
inline

◆ sec_res_transects

double openswmm::perf::sec_res_transects = 0.0
inline

◆ sec_res_xsect

double openswmm::perf::sec_res_xsect = 0.0
inline

◆ sec_start_iface

double openswmm::perf::sec_start_iface = 0.0
inline

◆ sec_start_plugins

double openswmm::perf::sec_start_plugins = 0.0
inline