Skip to content

Optimize event envelope serialization in EventSubscription.executeAll#126

Open
greenart7c3 wants to merge 1 commit intomasterfrom
claude/improve-executeall-performance-fVEjl
Open

Optimize event envelope serialization in EventSubscription.executeAll#126
greenart7c3 wants to merge 1 commit intomasterfrom
claude/improve-executeall-performance-fVEjl

Conversation

@greenart7c3
Copy link
Copy Markdown
Owner

Summary

Optimize the performance of broadcasting events to multiple subscriptions by pre-serializing the event envelope once instead of serializing it separately for each subscription.

Key Changes

  • Pre-serialize event JSON: The event is now serialized to a JSON string once before the broadcast loop, rather than being serialized multiple times (once per subscription)
  • Cache escaped subscription IDs: Subscription IDs are escaped and cached at subscription creation time in the Subscription data class, eliminating repeated escaping during broadcasts
  • Simplify envelope construction: Replace Jackson object serialization with direct string concatenation for the envelope structure ["EVENT", <escapedId>, <eventJson>]
  • Improve filter matching: Use any() to short-circuit filter evaluation instead of nested forEach loops
  • Add connection validation: Check if the WebSocket connection is closed before attempting to send

Implementation Details

  • Added a module-level ENVELOPE_MAPPER using JacksonMapper.mapper for consistent serialization
  • The Subscription class now pre-computes escapedId during initialization
  • The executeAll function now constructs envelopes via string concatenation rather than Jackson serialization, reducing object allocation and GC pressure
  • Added comprehensive micro-benchmarks (ExecuteAllFanOutBenchmark) demonstrating the performance improvement with realistic event and subscription ID data, showing significant speedup especially when broadcasting to many subscribers

https://claude.ai/code/session_01N5q663coA5rYbnsrq5hMF1

Pre-serialize the event JSON once per fan-out and stamp it into a
per-subscription envelope by string concatenation, instead of asking
Jackson to re-walk the JsonNode tree for every matching subscription.
The subscription id is escaped once at construction (Subscription.escapedId)
so the hot path performs no JSON serialization per subscription. Also
short-circuits filter testing with `any { test }` (fixing a duplicate-send
when multiple filters in one subscription matched the same event) and
skips subscriptions whose websocket is already closed for send.

Includes a JVM-only micro-benchmark
(ExecuteAllFanOutBenchmark) that compares the strategies; on a 200-sub
fan-out of a typical kind-1 event it shows ~3-4x improvement.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants