Skip to content

WS: pluggable JSON loader/dumper hook (orjson opt-in) for recv/send hot path #209

Closed

Description

@TexasCoding

Summary

Every WS frame is parsed via stdlib json.loads(raw) and every outbound subscribe/unsubscribe is serialized via json.dumps(msg). There is no configuration hook to swap in orjson.loads/ujson.loads, and no documentation mentions the option.

stdlib json.loads is roughly 2–3× slower than orjson on real-world Kalshi frames. For a trader streaming orderbook_delta on multiple deep markets at >5–10k msg/s, that gap dominates recv-loop CPU and starves the dispatch coroutine. The dispatcher already takes a pre-parsed dict via pre_validated, so the recv loop is the only critical-path json.loads call site — a single injection point covers the hot path.

Location

  • kalshi/ws/client.py:253 — data = json.loads(raw) (recv hot path)
  • kalshi/ws/channels.py:136 — data = json.loads(raw) (subscribe-ack wait)
  • kalshi/ws/connection.py:215 — await self._ws.send(json.dumps(msg)) (sends)

Evidence

# kalshi/ws/client.py:252-256
assert self._dispatcher is not None
data = json.loads(raw)                # always stdlib
sid = data.get("sid")
seq = data.get("seq")
msg_type = data.get("type", "")

Recommended fix

Add to KalshiConfig:

ws_json_loads: Callable[[bytes | str], Any] | None = None
ws_json_dumps: Callable[[Any], bytes | str] | None = None

Resolve once at WS-client init:

self._json_loads = config.ws_json_loads or json.loads
self._json_dumps = config.ws_json_dumps or json.dumps

Use from _process_frame, SubscriptionManager._wait_for_response, and ConnectionManager.send. Mention orjson/ujson in docs/websockets.md performance section with example:

import orjson
KalshiConfig(ws_json_loads=orjson.loads, ws_json_dumps=lambda v: orjson.dumps(v).decode())

No new SDK dependency required; users opt in.

Tests:

  • test_custom_json_loads_called_for_recv_frames
  • test_custom_json_dumps_called_for_subscribe_commands
  • test_default_uses_stdlib_json_loads

Severity & category

medium / performance, dx, ws

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestperformancePerformance / hot-path concernwsWebSocket-related

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions