From Wave 5 performance audit, finding F-R-01. Severity: medium. Measured.
Code
`kalshi/ws/backpressure.py:80-82`:
```python
def qsize(self) -> int:
return sum(1 for item in self._buffer if item is not _SENTINEL)
```
Measurement
- `qsize()` with 1000 items: 22.474 µs/call
- `len(buffer)`: 0.035 µs/call
Three orders of magnitude — 600× regression on every call.
Why this matters
Anyone polling `qsize()` from a monitoring loop, a hot consumer, or a backpressure-aware throttle pays 22 µs per call at `maxsize=1000`. The linear scan exists only to subtract the sentinel; at most one sentinel ever sits in the deque, and only at shutdown.
Fix
Either:
- (a) Track a counter (increment in `put`, decrement in `get`). O(1).
- (b) Return `len(self._buffer) - (1 if self._closed and self._buffer and self._buffer[-1] is _SENTINEL else 0)`. O(1).
(b) is the smaller change.
Related (low priority)
F-R-02 / F-P-15: the `_buffer` is also `collections.deque(maxlen=None)`. The bound is enforced manually in `put()`, but `maxlen=None` defeats the deque's own ring-buffer safety. Worth setting `maxlen=maxsize + 1` (reserve one slot for sentinel) as defense-in-depth.
From Wave 5 performance audit, finding F-R-01. Severity: medium. Measured.
Code
`kalshi/ws/backpressure.py:80-82`:
```python
def qsize(self) -> int:
return sum(1 for item in self._buffer if item is not _SENTINEL)
```
Measurement
Three orders of magnitude — 600× regression on every call.
Why this matters
Anyone polling `qsize()` from a monitoring loop, a hot consumer, or a backpressure-aware throttle pays 22 µs per call at `maxsize=1000`. The linear scan exists only to subtract the sentinel; at most one sentinel ever sits in the deque, and only at shutdown.
Fix
Either:
(b) is the smaller change.
Related (low priority)
F-R-02 / F-P-15: the `_buffer` is also `collections.deque(maxlen=None)`. The bound is enforced manually in `put()`, but `maxlen=None` defeats the deque's own ring-buffer safety. Worth setting `maxlen=maxsize + 1` (reserve one slot for sentinel) as defense-in-depth.