Repository navigation
Description
Problem
_BookState.to_orderbook constructs 2 * N OrderbookLevel instances and one Orderbook instance via the full BaseModel.__init__ pipeline on every cache miss. DollarDecimal's BeforeValidator(_coerce_decimal) and FixedPointCount's validator re-run on values that are already Decimal, plus pydantic's per-field type check / extra-field collection runs for every level.
The _BookState.yes / .no dicts are an invariant of the manager — _apply_snapshot_inplace and _apply_delta_inplace only ever store Decimal values into them. The re-validation work is therefore pure overhead. With the #244 cache invalidated on every delta, the _OrderbookIterator hot path pays this on every frame; on a 200-level book that's 401 unnecessary model_validate invocations per delta.
Evidence
kalshi/ws/orderbook.py:55-73— every cache miss goes throughOrderbookLevel(price=..., quantity=...)andOrderbook(...)
def to_orderbook(self) -> Orderbook:
if self._cached is not None:
return self._cached
yes_levels = [
OrderbookLevel(price=price, quantity=qty) for price, qty in sorted(self.yes.items())
]
no_levels = [
OrderbookLevel(price=price, quantity=qty) for price, qty in sorted(self.no.items())
]
ob = Orderbook(ticker=self.ticker, yes=yes_levels, no=no_levels)
self._cached = ob
return obkalshi/models/markets.py:146—OrderbookLevelfields areDollarDecimal/FixedPointCount(both carryBeforeValidator(_coerce_decimal)).scripts/bench_orderbook_iterator.py— existing WS perf: subscribe_book iterator re-materializes the entire orderbook on every delta #244 hot-path benchmark.
Suggested fix
Replace the constructor calls with model_construct, which skips the validator pipeline:
yes_levels = [
OrderbookLevel.model_construct(price=price, quantity=qty)
for price, qty in sorted(self.yes.items())
]
no_levels = [
OrderbookLevel.model_construct(price=price, quantity=qty)
for price, qty in sorted(self.no.items())
]
ob = Orderbook.model_construct(ticker=self.ticker, yes=yes_levels, no=no_levels)Inputs are already-typed Decimal from the manager's invariant, so skipping validation is safe. Document the invariant at the top of _BookState. Existing tests in tests/ws/test_orderbook.py cover the public Decimal-typed shape. scripts/bench_orderbook_iterator.py is the regression harness — expect a measurable reduction in per-delta materialization cost.
Source
Round-3 independent audit (reviewer: performance).
Activity