-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Topic.doMessageSend() is currently synchronized, holding the intrinsic lock during persistence, dispatch to all subscribers, and persistence completion wait. Under high contention (many concurrent producers + durable subscribers + slow persistence), this serializes all work unnecessarily.
This change replaces synchronized with a ReentrantLock held only during persistence (to guarantee message ordering as javadoc was mentioning). Dispatch to subscribers and result.get() happen outside the lock, allowing concurrent dispatch for messages from different producers.
This is valid per Jakarta Messaging 3.1 Section 6.2.9: message ordering is guaranteed per-session/per-producer only.
JMH benchmarks on my old MacBook Pro M1 show +15% to +41% throughput improvement under contention (10+ producer threads, multiple durable subscribers, H2 JDBC or simulated IO latency). Single-thread performance is unchanged.
On a real production system, the gain under heavy load with a lot of subscribers (several thousands) and a JDBC backend is huge.
I've Included a JMH benchmark (TopicSendLockBenchmark.java, excluded from CI).