From 9481c4d758fe02f820703a1fea3903bd6fe6bcbe Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Sat, 25 Oct 2025 21:20:25 +0300 Subject: [PATCH] combine cas --- internal/pool/conn_state.go | 7 +++++-- internal/pool/pool.go | 17 +++++------------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/internal/pool/conn_state.go b/internal/pool/conn_state.go index b0142320..8e334354 100644 --- a/internal/pool/conn_state.go +++ b/internal/pool/conn_state.go @@ -122,7 +122,7 @@ func (sm *ConnStateMachine) GetState() ConnState { } // TryTransitionFast is an optimized version for the hot path (Get/Put operations). -// It only handles simple IDLE ⇄ IN_USE transitions without waiter notification. +// It only handles simple state transitions without waiter notification. // This is safe because: // 1. Get/Put don't need to wait for state changes // 2. Background operations (handoff/reauth) use UNUSABLE state, which this won't match @@ -130,8 +130,11 @@ func (sm *ConnStateMachine) GetState() ConnState { // // Returns true if transition succeeded, false otherwise. // Use this for performance-critical paths where you don't need error details. +// +// Performance: Single CAS operation - as fast as the old atomic bool! +// For multiple from states, use: sm.TryTransitionFast(State1, Target) || sm.TryTransitionFast(State2, Target) +// The || operator short-circuits, so only 1 CAS is executed in the common case. func (sm *ConnStateMachine) TryTransitionFast(fromState, targetState ConnState) bool { - // Single CAS operation - as fast as the old atomic bool! return sm.state.CompareAndSwap(uint32(fromState), uint32(targetState)) } diff --git a/internal/pool/pool.go b/internal/pool/pool.go index 598d0096..e92a3fd7 100644 --- a/internal/pool/pool.go +++ b/internal/pool/pool.go @@ -599,19 +599,12 @@ func (p *ConnPool) popIdle() (*Conn, error) { } attempts++ - // Hot path optimization: try fast IDLE → IN_USE transition first - // This is a single CAS operation, as fast as the old atomic bool + // Hot path optimization: try IDLE → IN_USE or CREATED → IN_USE transition + // Most connections will be IDLE (1 CAS), new connections will be CREATED (2 CAS) + // We inline both attempts to avoid function call overhead sm := cn.GetStateMachine() - if sm.TryTransitionFast(StateIdle, StateInUse) { - // Successfully acquired the connection (common case) - p.idleConnsLen.Add(-1) - break - } - - // Fast path failed - connection might be CREATED (uninitialized) or UNUSABLE (handoff/reauth) - // Try CREATED → IN_USE for new connections - if sm.TryTransitionFast(StateCreated, StateInUse) { - // Successfully acquired uninitialized connection + if sm.TryTransitionFast(StateIdle, StateInUse) || sm.TryTransitionFast(StateCreated, StateInUse) { + // Successfully acquired the connection p.idleConnsLen.Add(-1) break }