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

Analyzing Kernel Workqueues

Inspect workqueue latency to understand delayed background task execution in the OS.

In this lesson, you will learn how to measure the latency between when a kernel work item is queued and when it actually begins execution.

The Workqueue Bottleneck

Kernel workqueues are the primary mechanism for offloading deferred work into kernel threads (kworker). When a driver or subsystem needs to perform a task (like processing a network packet or handling a disk interrupt) without blocking the current context, it "queues" a work_struct.

However, workqueues are not magic; they are subject to CPU scheduling and thread pool saturation. If your kworker threads are busy or starved, your "asynchronous" tasks sit in a queue, waiting for their turn. This manifests as increased latency for background operations, which can degrade system responsiveness or throughput.

Measuring Latency with BPF

To inspect this latency, we trace the transition from the queuing event to the execution event. We track the work_struct address—a unique identifier for the specific job—as it moves through the kernel.

We hook two primary tracepoints:

  1. workqueue:workqueue_queue_work: Captured when the work is submitted.
  2. workqueue:workqueue_execute_start: Captured when the kworker thread picks it up.

Here is the conceptual logic for calculating this delta:

// Simplified logic for measuring workqueue wait time
SEC("tracepoint/workqueue/workqueue_queue_work")
int trace_queue(struct trace_event_raw_workqueue_execute_start *ctx) {
    u64 ts = bpf_ktime_get_ns();
    bpf_map_update_elem(&start_times, &ctx->work, &ts, BPF_ANY);
    return 0;
}

SEC("tracepoint/workqueue/workqueue_execute_start")
int trace_start(struct trace_event_raw_workqueue_execute_start *ctx) {
    u64 *start = bpf_map_lookup_elem(&start_times, &ctx->work);
    if (start) {
        u64 delta = bpf_ktime_get_ns() - *start;
        // Record 'delta' into a histogram for analysis
        bpf_map_delete_elem(&start_times, &ctx->work);
    }
    return 0;
}

By aggregating these deltas into a histogram, you can identify if your system suffers from "queue buildup," where tasks wait significantly longer than the time taken to execute them. If latency is high, check your kworker thread CPU affinity or look for long-running functions currently hogging the worker threads, as they block all subsequent tasks in that queue.

Key Takeaway: Workqueue latency is the time delta between submission and execution; high latency indicates either a saturated thread pool or systemic CPU contention.