From nobody Mon Jun 8 20:54:06 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3A564403E8F; Tue, 26 May 2026 14:22:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779805362; cv=none; b=H//p/E38g2zYYXcX2HtV5vNOjCEsW+FX13dYs2SaJnsqROJUZWcZ4Nb643kXJgCS3WIt4mjhoJX6DH4Ia9DSHKFv8/cT3NNLFnmJ631/aIPFaSec1WtdyFPOqFF4PCZ0NKGmcOtLeYr12h4kVL/KJvGdFYb/fa6XP7SZimfusUs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779805362; c=relaxed/simple; bh=h6KA3YaSgKC2rbgaKZfNMznN4+uBHOeF9LemqGWGmVc=; h=Date:From:To:Subject:Cc:In-Reply-To:References:MIME-Version: Message-ID:Content-Type; b=njivaaap9hf+zP2cT/qU39YIIdHRuXwEWlOL05JNIURqUSJmvcqo9sTFC0YO/6inFDBPnpWW1O5960XCOY+SYA6vJcFGC2K+PHLfDsAPZUVvwVvXyvlGpFqrJT8nIFbXy7u3W4DPxHtTnkWixl7Uil9zX6joVIaGrx/lkQXRbA0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=VNZJIc4G; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=4y9pm0ZG; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="VNZJIc4G"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="4y9pm0ZG" Date: Tue, 26 May 2026 14:22:38 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1779805359; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pnBCTHd1Sz1Nm7uH5RhKX1MlNgvOtKySL7T7Prrm0ow=; b=VNZJIc4GMaJ3gLdN3he7g2xa9cWlm2haEaERZVUmYF6HfObzbB1w1LlsCbKW2fmxFnMJqT SW3P4LP/Ty6XrifA1wzBv2RQl78Yc/ItptyxSsSQI4A9gGeO3MBsIgu7Q5+537q01Kx7Nt INndqaRQBTMKoNgeuUNbd4j3wrLkf4pw1R/fB+rv0OPr0U2UjwJ8AvlS4An3sFtSHzgsHk dRtq4/RfmBOi6sFURok2Dacgt5eZBRKCwui/MfFEbOQaBCpHfu+NDTyzGZm9gGnClNFiHk lG76MA73dvJG4b29qpd0o67p6nfo53klHPskPvnUmYLIb3EmjBLl10ikwUFtVw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1779805359; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pnBCTHd1Sz1Nm7uH5RhKX1MlNgvOtKySL7T7Prrm0ow=; b=4y9pm0ZG5JQF1jqNtfoDnvPlISO6pAxTFKfo429/4YiMUXGgr6cNttynjmYXYCZphBPZ2u od3u9R4xok/PwlDg== From: "tip-bot2 for Dmitry Ilvokhin" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: irq/core] x86/irq: Optimize interrupts decimals printing Cc: Dmitry Ilvokhin , Thomas Gleixner , Michael Kelley , Radu Rendec , x86@kernel.org, linux-kernel@vger.kernel.org, maz@kernel.org In-Reply-To: <20260517194930.949709489@kernel.org> References: <20260517194930.949709489@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <177980535839.1039918.13711604620348048378.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Precedence: bulk Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The following commit has been merged into the irq/core branch of tip: Commit-ID: 115bbf0c1b60cb7bed348c64694eb88e21e7d458 Gitweb: https://git.kernel.org/tip/115bbf0c1b60cb7bed348c64694eb88e2= 1e7d458 Author: Dmitry Ilvokhin AuthorDate: Sun, 17 May 2026 22:01:33 +02:00 Committer: Thomas Gleixner CommitterDate: Tue, 26 May 2026 16:21:11 +02:00 x86/irq: Optimize interrupts decimals printing Monitoring tools periodically scan /proc/interrupts to export metrics as a timeseries for future analysis and investigation. In large fleets, /proc/interrupts is polled (often every few seconds) on every machine. The cumulative overhead adds up quickly across thousands of nodes, so reducing the cost of generating these stats does have a measurable operational impact. With the ongoing trend toward higher core counts per machine, this cost becomes even more noticeable over time, since interrupt counters are per-CPU. In Meta's fleet, we have observed this overhead at scale. Although a binary /proc interface would be a better long-term solution due to lower formatting (kernel side) and parsing (userspace side) overhead, the text interface will remain in use for some time, even if better solutions will be available. Optimizing the /proc/interrupts printing code is therefore still beneficial. Function seq_printf() supports rich format string for decimals printing, but it doesn't required for printing /proc/interrupts per CPU counters, seq_put_decimal_ull_width() function can be used instead to print per CPU counters, because very limited formatting is required for this case. Similar optimization idea is already used in show_interrupts(). As a side effect this aligns the x86 decriptions with the generic interrupts event descriptions. Performance counter stats (truncated) for 'sh -c cat /proc/interrupts Before: 3.42 msec task-clock # 0.802 CPUs utilized ( +- 0.05% ) 1 context-switches # 291.991 /sec ( +- 0.74% ) 0 cpu-migrations # 0.000 /sec 343 page-faults # 100.153 K/sec ( +- 0.01% ) 8,932,242 instructions # 1.66 insn per cycle ( +- 0.34% ) 5,374,427 cycles # 1.569 GHz ( +- 0.04% ) 1,483,154 branches # 433.068 M/sec ( +- 0.22% ) 28,768 branch-misses # 1.94% of all branches ( +- 0.31% ) 0.00427182 +- 0.00000215 seconds time elapsed ( +- 0.05% ) After: 2.39 msec task-clock # 0.796 CPUs utilized ( +- 0.06% ) 1 context-switches # 418.541 /sec ( +- 0.70% ) 0 cpu-migrations # 0.000 /sec 343 page-faults # 143.560 K/sec ( +- 0.01% ) 7,020,982 instructions # 1.30 insn per cycle ( +- 0.52% ) 5,397,266 cycles # 2.259 GHz ( +- 0.06% ) 1,569,648 branches # 656.962 M/sec ( +- 0.08% ) 25,419 branch-misses # 1.62% of all branches ( +- 0.72% ) 0.00299996 +- 0.00000206 seconds time elapsed ( +- 0.07% ) Relative speed up in time elapsed is around 29%. [ tglx: Fixed it up so it applies to current mainline ] Signed-off-by: Dmitry Ilvokhin Signed-off-by: Thomas Gleixner Tested-by: Michael Kelley Reviewed-by: Thomas Gleixner Reviewed-by: Radu Rendec Link: https://patch.msgid.link/aQj5mGZ6_BBlAm3B@shell.ilvokhin.com Link: https://patch.msgid.link/20260517194930.949709489@kernel.org --- arch/x86/kernel/irq.c | 112 +++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 53 deletions(-) diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index ec77be2..963690b 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -62,6 +62,18 @@ void ack_bad_irq(unsigned int irq) apic_eoi(); } =20 +/* + * A helper routine for putting space and decimal number without overhead + * from rich format of printf(). + */ +static void put_decimal(struct seq_file *p, unsigned long long num) +{ + const char *delimiter =3D " "; + unsigned int width =3D 10; + + seq_put_decimal_ull_width(p, delimiter, num, width); +} + #define irq_stats(x) (&per_cpu(irq_stat, x)) /* * /proc/interrupts printing for arch specific interrupts @@ -70,103 +82,101 @@ int arch_show_interrupts(struct seq_file *p, int prec) { int j; =20 - seq_printf(p, "%*s: ", prec, "NMI"); + seq_printf(p, "%*s:", prec, "NMI"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->__nmi_count); + put_decimal(p, irq_stats(j)->__nmi_count); seq_puts(p, " Non-maskable interrupts\n"); #ifdef CONFIG_X86_LOCAL_APIC - seq_printf(p, "%*s: ", prec, "LOC"); + seq_printf(p, "%*s:", prec, "LOC"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs); + put_decimal(p, irq_stats(j)->apic_timer_irqs); seq_puts(p, " Local timer interrupts\n"); =20 - seq_printf(p, "%*s: ", prec, "SPU"); + seq_printf(p, "%*s:", prec, "SPU"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count); + put_decimal(p, irq_stats(j)->irq_spurious_count); seq_puts(p, " Spurious interrupts\n"); - seq_printf(p, "%*s: ", prec, "PMI"); + seq_printf(p, "%*s:", prec, "PMI"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs); + put_decimal(p, irq_stats(j)->apic_perf_irqs); seq_puts(p, " Performance monitoring interrupts\n"); - seq_printf(p, "%*s: ", prec, "IWI"); + seq_printf(p, "%*s:", prec, "IWI"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->apic_irq_work_irqs); + put_decimal(p, irq_stats(j)->apic_irq_work_irqs); seq_puts(p, " IRQ work interrupts\n"); - seq_printf(p, "%*s: ", prec, "RTR"); + seq_printf(p, "%*s:", prec, "RTR"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->icr_read_retry_count); + put_decimal(p, irq_stats(j)->icr_read_retry_count); seq_puts(p, " APIC ICR read retries\n"); if (x86_platform_ipi_callback) { - seq_printf(p, "%*s: ", prec, "PLT"); + seq_printf(p, "%*s:", prec, "PLT"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->x86_platform_ipis); + put_decimal(p, irq_stats(j)->x86_platform_ipis); seq_puts(p, " Platform interrupts\n"); } #endif #ifdef CONFIG_SMP - seq_printf(p, "%*s: ", prec, "RES"); + seq_printf(p, "%*s:", prec, "RES"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count); + put_decimal(p, irq_stats(j)->irq_resched_count); seq_puts(p, " Rescheduling interrupts\n"); - seq_printf(p, "%*s: ", prec, "CAL"); + seq_printf(p, "%*s:", prec, "CAL"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->irq_call_count); + put_decimal(p, irq_stats(j)->irq_call_count); seq_puts(p, " Function call interrupts\n"); - seq_printf(p, "%*s: ", prec, "TLB"); + seq_printf(p, "%*s:", prec, "TLB"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count); + put_decimal(p, irq_stats(j)->irq_tlb_count); seq_puts(p, " TLB shootdowns\n"); #endif #ifdef CONFIG_X86_THERMAL_VECTOR - seq_printf(p, "%*s: ", prec, "TRM"); + seq_printf(p, "%*s:", prec, "TRM"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count); + put_decimal(p, irq_stats(j)->irq_thermal_count); seq_puts(p, " Thermal event interrupts\n"); #endif #ifdef CONFIG_X86_MCE_THRESHOLD - seq_printf(p, "%*s: ", prec, "THR"); + seq_printf(p, "%*s:", prec, "THR"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count); + put_decimal(p, irq_stats(j)->irq_threshold_count); seq_puts(p, " Threshold APIC interrupts\n"); #endif #ifdef CONFIG_X86_MCE_AMD - seq_printf(p, "%*s: ", prec, "DFR"); + seq_printf(p, "%*s:", prec, "DFR"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->irq_deferred_error_count); + put_decimal(p, irq_stats(j)->irq_deferred_error_count); seq_puts(p, " Deferred Error APIC interrupts\n"); #endif #ifdef CONFIG_X86_MCE - seq_printf(p, "%*s: ", prec, "MCE"); + seq_printf(p, "%*s:", prec, "MCE"); for_each_online_cpu(j) - seq_printf(p, "%10u ", per_cpu(mce_exception_count, j)); + put_decimal(p, per_cpu(mce_exception_count, j)); seq_puts(p, " Machine check exceptions\n"); - seq_printf(p, "%*s: ", prec, "MCP"); + seq_printf(p, "%*s:", prec, "MCP"); for_each_online_cpu(j) - seq_printf(p, "%10u ", per_cpu(mce_poll_count, j)); + put_decimal(p, per_cpu(mce_poll_count, j)); seq_puts(p, " Machine check polls\n"); #endif #ifdef CONFIG_X86_HV_CALLBACK_VECTOR if (test_bit(HYPERVISOR_CALLBACK_VECTOR, system_vectors)) { - seq_printf(p, "%*s: ", prec, "HYP"); + seq_printf(p, "%*s:", prec, "HYP"); for_each_online_cpu(j) - seq_printf(p, "%10u ", - irq_stats(j)->irq_hv_callback_count); + put_decimal(p, irq_stats(j)->irq_hv_callback_count); seq_puts(p, " Hypervisor callback interrupts\n"); } #endif #if IS_ENABLED(CONFIG_HYPERV) if (test_bit(HYPERV_REENLIGHTENMENT_VECTOR, system_vectors)) { - seq_printf(p, "%*s: ", prec, "HRE"); + seq_printf(p, "%*s:", prec, "HRE"); for_each_online_cpu(j) - seq_printf(p, "%10u ", - irq_stats(j)->irq_hv_reenlightenment_count); + put_decimal(p, + irq_stats(j)->irq_hv_reenlightenment_count); seq_puts(p, " Hyper-V reenlightenment interrupts\n"); } if (test_bit(HYPERV_STIMER0_VECTOR, system_vectors)) { - seq_printf(p, "%*s: ", prec, "HVS"); + seq_printf(p, "%*s:", prec, "HVS"); for_each_online_cpu(j) - seq_printf(p, "%10u ", - irq_stats(j)->hyperv_stimer0_count); + put_decimal(p, irq_stats(j)->hyperv_stimer0_count); seq_puts(p, " Hyper-V stimer0 interrupts\n"); } #endif @@ -175,35 +185,31 @@ int arch_show_interrupts(struct seq_file *p, int prec) seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count)); #endif #if IS_ENABLED(CONFIG_KVM) - seq_printf(p, "%*s: ", prec, "PIN"); + seq_printf(p, "%*s:", prec, "PIN"); for_each_online_cpu(j) - seq_printf(p, "%10u ", irq_stats(j)->kvm_posted_intr_ipis); + put_decimal(p, irq_stats(j)->kvm_posted_intr_ipis); seq_puts(p, " Posted-interrupt notification event\n"); =20 - seq_printf(p, "%*s: ", prec, "NPI"); + seq_printf(p, "%*s:", prec, "NPI"); for_each_online_cpu(j) - seq_printf(p, "%10u ", - irq_stats(j)->kvm_posted_intr_nested_ipis); + put_decimal(p, irq_stats(j)->kvm_posted_intr_nested_ipis); seq_puts(p, " Nested posted-interrupt event\n"); =20 - seq_printf(p, "%*s: ", prec, "PIW"); + seq_printf(p, "%*s:", prec, "PIW"); for_each_online_cpu(j) - seq_printf(p, "%10u ", - irq_stats(j)->kvm_posted_intr_wakeup_ipis); + put_decimal(p, irq_stats(j)->kvm_posted_intr_wakeup_ipis); seq_puts(p, " Posted-interrupt wakeup event\n"); #endif #ifdef CONFIG_GUEST_PERF_EVENTS - seq_printf(p, "%*s: ", prec, "VPMI"); + seq_printf(p, "%*s:", prec, "VPMI"); for_each_online_cpu(j) - seq_printf(p, "%10u ", - irq_stats(j)->perf_guest_mediated_pmis); + put_decimal(p, irq_stats(j)->perf_guest_mediated_pmis); seq_puts(p, " Perf Guest Mediated PMI\n"); #endif #ifdef CONFIG_X86_POSTED_MSI - seq_printf(p, "%*s: ", prec, "PMN"); + seq_printf(p, "%*s:", prec, "PMN"); for_each_online_cpu(j) - seq_printf(p, "%10u ", - irq_stats(j)->posted_msi_notification_count); + put_decimal(p, irq_stats(j)->posted_msi_notification_count); seq_puts(p, " Posted MSI notification event\n"); #endif return 0;