|
STAR
Cal STAR — firmware, DAQ server, and engine design
|
Functions | |
| float | _time_us (object call, int n=ITERATIONS) |
| None | test_get_is_within_the_convenience_budget (str prop) |
| None | test_the_hot_path_meets_the_phase_budget (str prop) |
| None | test_accessor_is_faster_than_get (str prop) |
| None | test_tables_are_dramatically_faster_than_the_equation_of_state () |
| None | test_propssi_would_be_far_slower () |
| None | test_backends_are_confined_to_their_thread () |
| None | test_a_shared_tabulated_backend_is_also_thread_safe () |
| None | test_the_memo_returns_exactly_what_the_backend_would () |
| None | test_get_and_the_accessor_share_one_entry () |
| None | test_the_memo_is_bounded () |
Variables | |
| pytestmark | |
| float | HOT_PATH_BUDGET_US = 10.0 |
| float | CONVENIENCE_BUDGET_US = 15.0 |
| int | ITERATIONS = 20_000 |
| int | BATCHES = 5 |
| float | _STEP_K = 1.0e-6 |
Phase 01's speed gate, and the thread confinement that makes it safe. Speed is a correctness property here, not a nicety. A transient on a sixty-node network evaluates properties millions of times over Jacobian assembly; at CoolProp's convenience API (184 us/call) that solve does not finish, so the whole layer exists to make it 0.1 us. A regression would not break a test anywhere else -- it would just quietly make the simulator unusable, months later, with no obvious culprit. Thresholds are deliberately loose against the measured numbers so shared CI runners do not produce flakes. They are ceilings on the *design*, not benchmarks: the point is to catch someone accidentally routing the hot path through PropsSI or rebuilding a backend per call, which costs 10-1000x, not to notice a 20% drift.
|
protected |
Microseconds per call in the fastest of :data:`BATCHES` batches, after a warm-up that excludes table build. ``call`` takes the iteration index and is expected to use it to move the state point -- see :data:`_STEP_K`. The index runs on across batches, so no batch repeats another's state points.
Definition at line 98 of file test_props_performance.py.
Referenced by test_accessor_is_faster_than_get(), test_get_is_within_the_convenience_budget(), test_propssi_would_be_far_slower(), test_tables_are_dramatically_faster_than_the_equation_of_state(), and test_the_hot_path_meets_the_phase_budget().
| None test_props_performance.test_a_shared_tabulated_backend_is_also_thread_safe | ( | ) |
One measured table, many threads. Unlike the CoolProp backends, a tabulated one cannot be rebuilt per thread -- it is parameterised by its data, not by a species name -- so the single instance is shared and only its cursor is thread-local. This asserts that actually holds.
Definition at line 236 of file test_props_performance.py.
| None test_props_performance.test_accessor_is_faster_than_get | ( | str | prop | ) |
The bound accessor is the loop API, and must earn that claim. It hoists everything invariant -- state-pair resolution, which backends support the property, keyword unpacking -- out of the call. If it ever stopped being faster, the extra API would be complexity for nothing.
Definition at line 145 of file test_props_performance.py.
References _time_us(), and read().
| None test_props_performance.test_backends_are_confined_to_their_thread | ( | ) |
Threads must not share a backend cursor. Backends wrap a mutable cursor: ``update`` moves it, ``value`` reads it. Two threads sharing one would interleave -- each reading the other's state point -- and produce plausible wrong numbers with no exception anywhere. Each thread here queries a *different* state point in a tight loop and checks its own answer every time. Interleaving would show up as a wrong density, not as a crash, which is exactly why it needs asserting.
Definition at line 201 of file test_props_performance.py.
| None test_props_performance.test_get_and_the_accessor_share_one_entry | ( | ) |
Otherwise the accessor -- the API this module tells people to use in a loop -- would be the slower of the two for a repeated point, and its own advice would be wrong.
Definition at line 315 of file test_props_performance.py.
References read().
| None test_props_performance.test_get_is_within_the_convenience_budget | ( | str | prop | ) |
The ergonomic API stays close to a microsecond.
Definition at line 119 of file test_props_performance.py.
References _time_us().
| None test_props_performance.test_propssi_would_be_far_slower | ( | ) |
The measurement behind the ban in test_property_call_discipline. That test forbids ``PropsSI`` in library code on the strength of a number. This is the number, re-measured, so the rule keeps a live justification rather than a comment citing a benchmark nobody runs. Tests are exempt from the ban precisely so this comparison can exist.
Definition at line 177 of file test_props_performance.py.
References _time_us().
| None test_props_performance.test_tables_are_dramatically_faster_than_the_equation_of_state | ( | ) |
The reason the chain is ordered the way it is. A loose 3x floor against a measured 10-30x: enough to prove the tabulated path is actually being taken, without failing on a noisy runner.
Definition at line 162 of file test_props_performance.py.
References _time_us().
| None test_props_performance.test_the_hot_path_meets_the_phase_budget | ( | str | prop | ) |
The accessor -- what a solve loop uses -- stays fast. Phase 01's design target is under a microsecond, met at 0.63 us on the development host. What is asserted here is the looser ceiling above, so the test means the same thing on a loaded runner; run with FEEDTWIN_STRICT_PERF=1 to hold the real target. Z is included deliberately: it is the gas-side workhorse (COPV, ullage) and is derived from several reads rather than being one, so it is the property most likely to drift over.
Definition at line 127 of file test_props_performance.py.
References _time_us(), and read().
| None test_props_performance.test_the_memo_is_bounded | ( | ) |
It is cleared wholesale rather than evicted one at a time, so the only thing that must hold is that it cannot grow without limit.
Definition at line 335 of file test_props_performance.py.
| None test_props_performance.test_the_memo_returns_exactly_what_the_backend_would | ( | ) |
The property memo is an *exact* cache, and has to stay one. No rounding, no tolerance, no quantised state -- a hit returns the number the backend would have returned, and the only thing saved is asking again. That is what makes it safe to put in front of a solve: it cannot move an answer, only shorten the path to it. Checked against a fluid with no memo of its own, so the comparison is against the backend rather than against another cache.
Definition at line 276 of file test_props_performance.py.
|
protected |
Definition at line 95 of file test_props_performance.py.
| int test_props_performance.BATCHES = 5 |
Definition at line 79 of file test_props_performance.py.
| float test_props_performance.CONVENIENCE_BUDGET_US = 15.0 |
Definition at line 59 of file test_props_performance.py.
| float test_props_performance.HOT_PATH_BUDGET_US = 10.0 |
Definition at line 58 of file test_props_performance.py.
| int test_props_performance.ITERATIONS = 20_000 |
Definition at line 70 of file test_props_performance.py.
| test_props_performance.pytestmark |
Definition at line 29 of file test_props_performance.py.