update_position runs per tracked object per frame. While a position has
fewer than 10 samples it calls np.percentile four times, and average_boxes
(per stationary object per frame) calls np.mean four times - all on lists of
at most 10 ints, where numpy's per-call dispatch/validation overhead
dominates the actual work.
Replace them with pure-Python equivalents:
- average_boxes: sum()/len() instead of np.mean (bit-identical output)
- interpolated_percentile(): linear-interpolated percentile matching
numpy.percentile (including its lerp branch at frac>=0.5) for the small
lists used here, in place of np.percentile
Measured in the release image (numpy 1.26.4) on a 10-element list:
np.percentile 18735 ns -> 191 ns/call (98x); np.mean-based average_boxes
7480 ns -> 591 ns (12.7x); ~74 us saved per object-frame in update_position.
A live py-spy --gil profile of a camera process_frames worker showed
np.percentile (update_position) and np.mean (average_boxes) among the top
Frigate-owned on-CPU frames.
Output is unchanged: added tests assert both helpers are bit-identical to
numpy over randomized small inputs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* CenterFocusString icon
* Add CenterFocusString to multiselect
* Rename CenterFocusString.jsx
* Rename icon and make it smaller
* Rename icon
* Fix lint and use icon
for speech
* remove unused vars
* Remove unused import