Course contentsShow
← Linux
Lesson 1691 of 1,81914. Observability and Performance TroubleshootingFree lesson

Measuring RPC/gRPC Latency Distributions

Capture wire-level latency data for distributed service calls to identify slow downstream dependencies.

In this lesson, you will learn how to capture wire-level latency data for gRPC calls to pinpoint precisely which downstream dependency is dragging down your application’s performance.

When you observe high latency in a microservices environment, the challenge is determining if the slowness exists within your local process, the network transport, or the remote server's execution time. To resolve this, we move beyond simple application-level logs and use low-overhead Linux tracing tools—specifically eBPF via bcc or bpftrace—to hook directly into the socket-level activity of your RPC calls.

The Mechanism of Wire-Level Latency

gRPC typically runs over HTTP/2. To measure the true latency, we need to calculate the delta between the time a request header is serialized and written to the socket (tcp_sendmsg) and the time the first response frame is received (tcp_recvmsg or kretprobe on network stack functions). By using bpftrace, we can attach probes to these kernel functions to calculate the duration of the "round trip" at the syscall interface.

Consider this simplified bpftrace logic:

// Track the start of a request by the thread ID
kprobe:tcp_sendmsg { @start[tid] = nsecs; }

// On receive, measure the duration and histogram the results
kretprobe:tcp_recvmsg /@start[tid]/ {
    @latency = hist(nsecs - @start[tid]);
    delete(@start[tid]);
}

Why Distribution Matters

Simple averages (arithmetic means) are dangerous in distributed systems because they hide "tail latency" (the P99 and P99.9). An average might suggest a healthy 20ms response time, while a distribution histogram reveals a bi-modal distribution where 1% of your requests are hanging for 2 seconds due to head-of-line blocking or downstream lock contention.

By mapping these latency distributions directly to the specific file descriptors associated with your downstream dependencies, you can distinguish between a slow database connection and a saturated service-to-service link. This granular view allows you to verify if the latency is introduced by the kernel’s network stack processing or by the remote dependency itself.

Key Takeaway: Measuring wire-level latency distributions using kernel-level tracing allows you to isolate network transport overhead from actual downstream service processing time, revealing tail-latency patterns that application metrics often mask.