[PATCH 0/2] drivers: android: binder: Introduce Cluster Aware Thread Selection

From: trieu2.huynh

Date: Tue Jul 14 2026 - 14:36:12 EST


Motivation
----------

On asymmetric multi-cluster ARM64 SoCs, the default binder thread
selection is topology-blind. Cross-cluster thread wakeups incur severe
cache-coherency overhead.

Measured performance test [1], especially with schd-dbg tiered threads [2]
on baseline (10K iter, 16B payload):

Class Tier Avg Latency Count / % of txns
----- ---- ----------- -----------------
SCHED_FIFO Same-core 0.089 ms 9,963 / 99.6%
(max prio) Same-cluster 0.120 ms 13 / 0.1%
Cross-cluster 0.140 ms 24 / 0.2%
-----------------------------------------------------
Normal Same-core 0.130 ms 4,623 / 46.2%
(Other) Same-cluster 0.140 ms 3,290 / 32.9%
Cross-cluster 0.190 ms 2,087 / 20.9%

Key Observations:
(*) For SCHED_FIFO tasks, the scheduler aggressively locks the affinity,
keeping 99.6% of txns on the same core, establishing the hardware's
ideal latency ceiling (~0.089 ms).
(*) For normal tasks, selection is highly fragmented (only 46.2% on
same-core). Cross-cluster transactions are ~46% slower (0.19 vs
0.13 ms) due to interconnect overhead and cache invalidation.
(*) CTABS aims to close this gap for normal threads by enforcing affinity.

Design
------

CTABS optimizes thread dispatching through a two-tiered co-design:

(*) Topology Scoring: Scores waiting threads at selection time:
- Same CPU: Immediate dispatch (optimal L1/L2 locality via early exit)
- Score 1 (same cluster): Local cache reuse within the same cluster
- Score 0 (cross-cluster): Fallback to any available thread

(*) Adaptive Wake-up Nudge: For synchronous transactions yielding a cluster
match, the caller's CPU is stored as 'preferred_cpu'. Right before
wakeup, this value is injected into 'task->wake_cpu' to guide the
scheduler. To prevent runqueue contention under heavy load, this nudge
is adaptively applied only if 'available_idle_cpu(caller_cpu)' returns
true.

Implementation
--------------

[PATCH 1/2] drivers: android: binder: implement CTABS
Core scoring in binder_select_thread_topology_ilocked(),
thread->last_cpu tracking, integration at sync and async paths.

[PATCH 2/2] drivers: android: binder: add CTABS wake-up nudge
Adaptive scheduler hint via task->wake_cpu on top of scoring,
safeguarded by available_idle_cpu() to avoid core contention.

Benchmark Methodology
---------------------

The evaluation is conducted on a Qualcomm SA8155P Automotive platform
featuring an 8-core asymmetric Kryo 485 hierarchy organized into 3 distinct
clusters under a 1 + 3 + 4 configuration:
- Cluster 1 (Prime): 1x Kryo Gold Prime core (Cortex-A76 based).
- Cluster 2 (Gold): 3x Kryo Gold cores (Cortex-A76 based).
- Cluster 3 (Silver):4x Kryo Silver cores (Cortex-A55 based).

The test environment runs AAOSP 14 with a Linux Kernel 6.1 GKI under the
default schedutil governor.

To provide a comprehensive performance profile, two distinct test suites
are leveraged:
(*) schd-dbg [2]: Utilized as a micro-benchmark to isolate and collect
precise latency granularities across different affinity tiers.
(*) binderThroughputTest [3]: Executed under a heavy stress load (8 workers
x 100K iterations, 3 runs) paired with simpleperf to capture
hardware-level metrics (cycles, cache behavior, migrations) that reflect
the macro-level systemic impact of the optimization.

Results
-------

(*) schd-dbg — Tiered Thread Latency (Avg in ms)

Class Tier Baseline Patch 1/2 Patch 2/2 Δ P1/2 Δ P2/2
----- ------------- -------- --------- --------- ------ ------
SCHED_FIFO Same-core 0.089 ms 0.084 ms 0.083 ms -5.6% -6.7%
Same-cluster 0.120 ms 0.110 ms 0.110 ms -8.3% -8.3%
Cross-cluster 0.140 ms 0.130 ms 0.130 ms -7.1% -7.1%
------------------------------------------------------------------
Normal Same-core 0.130 ms 0.140 ms 0.140 ms +7.7% +7.7%
(Other) Same-cluster 0.140 ms 0.140 ms 0.130 ms 0% -7.1%
Cross-cluster 0.190 ms 0.210 ms 0.200 ms +10.5% +5.3%

(*) binderThroughputTest — 8 workers x 100K iter

Metric Baseline Patch 1/2 Patch 2/2 Δ P1/2 Δ P2/2
------ -------- --------- --------- ------ ------
Throughput 41,045/s 46,252/s 46,179/s +12.7% +12.5%
Avg latency 0.168 ms 0.146 ms 0.145 ms -13.1% -13.7%
p50 latency 0.195 ms 0.195 ms 0.117 ms 0% -40.0%
p99 latency 0.586 ms 0.586 ms 0.558 ms 0% -4.8%

CPU cycles 143.15 B 128.66 B 128.94 B -10.1% -9.9%
Cache refs 21.83 B 21.04 B 21.24 B -3.6% -2.7%
Cache misses 1,078 M 968 M 949 M -10.2% -11.9%
CPU migrations 922,848 730,277 739,576 -20.9% -19.9%
Ctx switches 1,697 K 1,691 K 1,692 K -0.4% -0.3%

[1] https://source.android.com/docs/core/tests/vts/performance
[2] https://android-review.googlesource.com/c/platform/frameworks/native/+/4164726
[3] https://android.googlesource.com/platform/frameworks/native/+/master/libs/binder/tests/binderThroughputTest.cpp

trieu2.huynh (2):
drivers: android: binder: implement CTABS heuristic
drivers: android: binder: add preferred CPU wake-up nudge for waiting
threads

drivers/android/binder.c | 111 ++++++++++++++++++++++++++++--
drivers/android/binder_internal.h | 2 +
2 files changed, 109 insertions(+), 4 deletions(-)

--
2.43.0