This is an automated email from the ASF dual-hosted git repository.

He-Pin pushed a commit to branch fix/actor-selection-queue-distribution
in repository https://gitbox.apache.org/repos/asf/pekko.git

commit 0fb44b4ba7985ea552b310ae582328967f42ce8a
Author: 虎鸣 <[email protected]>
AuthorDate: Fri Jun 19 20:17:58 2026 +0800

    fix(artery): distribute ActorSelection messages across outbound lanes by 
target path
    
    Motivation:
    The ActorSelection send-consistency test flakes on CI: 4 sender actors
    each drive 1000 round-trips via ActorSelection. With multi-lane artery
    config (outbound-lanes > 1), all ActorSelection messages are routed to
    the same outbound queue because selectQueue uses the anchor's UID
    (root guardian, which is always 0) as the distribution key. This
    concentrates all ActorSelection traffic on a single lane while other
    lanes sit idle, creating a throughput bottleneck that causes timeouts
    under CI load.
    
    Modification:
    Add a dedicated case for ActorSelectionMessage (non-PriorityMessage)
    in Association.send that computes the queue index from the selection's
    target path elements hash instead of the anchor's UID. This distributes
    ActorSelection messages across lanes by their target path, while
    preserving per-path message ordering (same target path always hashes
    to the same lane).
    
    Result:
    ActorSelection messages are now distributed across all outbound lanes
    based on target path, eliminating the single-lane bottleneck. The
    existing ActorRef-based test and PriorityMessage (heartbeat) routing
    are unaffected.
    
    Tests:
    - sbt "remote / Test / compile" — compile check
    - CI will exercise the artery variants
    
    References:
    Refs #3041 (previous timeout widening), supersedes #3090
---
 .../scala/org/apache/pekko/remote/artery/Association.scala    | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git 
a/remote/src/main/scala/org/apache/pekko/remote/artery/Association.scala 
b/remote/src/main/scala/org/apache/pekko/remote/artery/Association.scala
index eb9bf1176a..8082ef718d 100644
--- a/remote/src/main/scala/org/apache/pekko/remote/artery/Association.scala
+++ b/remote/src/main/scala/org/apache/pekko/remote/artery/Association.scala
@@ -436,6 +436,17 @@ private[remote] class Association(
             // so that the first message can be delivered after the remote 
actor has been created.
             if (!controlQueue.offer(outboundEnvelope))
               dropped(ControlQueueIndex, controlQueueSize, outboundEnvelope)
+          case sel: ActorSelectionMessage =>
+            // Distribute ActorSelection messages across lanes based on the 
target
+            // path hash rather than the anchor's (typically root guardian, 
UID=0).
+            // Without this, all ActorSelection messages concentrate on a 
single
+            // outbound lane, creating a throughput bottleneck.
+            val queueIndex =
+              if (outboundLanes == 1) OrdinaryQueueIndex
+              else OrdinaryQueueIndex + (math.abs(sel.elements.hashCode()) % 
outboundLanes)
+            val queue = queues(queueIndex)
+            if (!queue.offer(outboundEnvelope))
+              dropped(queueIndex, queueSize, outboundEnvelope)
           case _ =>
             val queueIndex = selectQueue(recipient)
             val queue = queues(queueIndex)


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to