Binder Thread Pool Limits and Latency Under Concurrent Transactions
0 reputation · 12 Oct 2021, 01:45 UTC
0 reputation · 12 Oct 2021, 01:45 UTC
Android’s Binder driver exposes a per‑process thread pool whose default size is 16 threads. When an application issues more concurrent IBinder.transact() calls than the pool can service, the excess transactions are queued by the kernel rather than rejected. This queuing introduces latency that is invisible in sequential benchmarks but can become significant under bursty workloads.
The framework constant that defines the pool size is not exposed via the public SDK, and the exact scheduling policy for queued transactions—whether it follows a strict FIFO order or is influenced by thread priority—is not documented. Consequently, architects lack a definitive worst‑case latency model for concurrent Binder traffic.
What is the precise scheduling policy applied to queued Binder transactions when the thread pool is saturated? Does the queue maintain a strict FIFO order, or does it consider thread priority or other factors? Can the pool size be altered through system properties or is it fixed per process for all builds?
Android does not document a strict FIFO or priority-based scheduling policy for Binder transactions queued when a process thread pool is saturated. The kernel driver wakes threads waiting in binder_thread_read or the framework looper, and the transaction that proceeds depends on wake-up order, thread availability, buffer state, and release-specific driver behavior—not a guaranteed arrival-order queue. There is also no standard, stable Android system property that sets the per-process Binder thread-pool size across all builds. Pool size is configured natively in libbinder, typically through ProcessState::setThreadPoolMaxThreadCount() before startThreadPool(); the default is not public SDK API and varies by Android release, device, and vendor kernel.
IBinder.transact() blocks the calling thread until a pool thread services the transaction or the call fails.ProcessState::setThreadPoolMaxThreadCount() must be called before the pool starts; changes afterward are not generally supported.Under bursty concurrent traffic, callers block waiting for a free pool thread. The driver then wakes a waiting thread, allocates a transaction buffer, and copies data. Observed p99 and p999 latency is therefore driven by thread wake-up contention and buffer pressure, not by a documented kernel FIFO. Whether thread priority influences wake-up order is release- and vendor-specific and should not be assumed.
ProcessState implementation for the default max thread count and any property reads.transact() calls than pool threads to the same service, and trace with Perfetto or systrace while recording p50, p99, and p999 latency and errors.What Android release, kernel or Binder driver version, and process type are you targeting? Exact defaults and scheduling behavior are release- and vendor-specific, so this detail changes which verification path applies. Review this draft against the target build before using it for capacity planning.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.