Skip to content

Common - Improve performance of zero-delay PerFrameHandlers - #1852

Open
LinkIsGrim wants to merge 2 commits into
CBATeam:masterfrom
LinkIsGrim:perf-pfh-zero-delay
Open

Common - Improve performance of zero-delay PerFrameHandlers#1852
LinkIsGrim wants to merge 2 commits into
CBATeam:masterfrom
LinkIsGrim:perf-pfh-zero-delay

Conversation

@LinkIsGrim

@LinkIsGrim LinkIsGrim commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

When merged this pull request will:

  • Give zero delay per frame handlers their own array, which runs unconditionally instead of checking an ETA that is always in the past. Delay modification and removal stay as-is.
  • Reject negative handles in remove, get and set instead of indexing from the end of the array.

Handles' indexes can now be negative. handle index >= 0 -> tracked in perFrameHandlerArray. handleIndex <= -1 -> eachFrameHandlerArray. Macros PFH_EACHFRAME_(ENCODE|DECODE) and PFH_IS_EACHFRAME for handling this, though they're just wrappers around negative conversion/ x < 0 check.

Zero-delay PFHs avoid params and just _x select whatever they need.

Delayed PFHs keep same behavior otherwise.

Note: CBA_fnc_addPerFrameHandler will still never return negative values. Negatives are internal.

Benchmark

Note this is synthetic: the loop bodies are the real ones, including the call and the ETA write, but the handler payload is empty and the hit/miss mix is fixed, so the differences are loop overhead only.

diag_codePerformance, 40 handlers per array, 10000 cycles, empty payload so the call cost is present in every variant. "hit" is a handler that fires this frame.

loop body all hit 1 of 11 hits half hit none hit
before #1835 (params, then check) 0.0728 0.0473 0.0582 0.0447
master today (check, then params) 0.0746 0.0266 0.0493 0.0225
this PR, zero delay array (select, no check) 0.0281 - - -
same but with params 0.0414 - - -

So a zero delay handler costs about 62% less overhead than it does today. For reference, the cost #1835 added on the hit path turns out to be about 2.5% once the call and the ETA write are in the measurement, and it remains a large win on the miss path, so this is not a regression fix - it is a straight speedup for handlers that run every frame.

Execution order

Behavior change here. Zero-delay PFHs will get executed after all delayed PFHs instead of in registration order among them. We don't document any ordering guarantees and I don't think it'll cause an issue, but bad code (PFHs mutating each other) may behave differently in terms of execution order. Also, giving a PFH a delay after registration moves it to the end of perFrameHandlerArray. Changing the delay of an already-delayed PFH still leaves it in place.

Comment thread addons/common/init_perFrameHandler.sqf Outdated
@PabstMirror PabstMirror changed the title Events - Improve performance of zero-delay PerFrameHandlers Common - Improve performance of zero-delay PerFrameHandlers Aug 23, 2026
// Execute per frame handlers
{
if (diag_tickTime > (_x select 2)) then {
_x params ["_function", "_delay", "_delta", "", "_args", "_handle"];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they shouldn't be
but I would hate if some func is expecting _args or _handle to exist

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wiki examples are explicit: https://github.com/CBATeam/CBA_A3/wiki/Per-Frame-Handlers#examples

bad code'll break I guess?

@PabstMirror PabstMirror added this to the 3.19.1 milestone Aug 23, 2026
Co-authored-by: PabstMirror <pabstmirror@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants