[patch 02/14] genirq/proc: Avoid formatting zero counts in /proc/interrupts

Thomas Gleixner posted 14 patches 1 month ago
[patch 02/14] genirq/proc: Avoid formatting zero counts in /proc/interrupts
Posted by Thomas Gleixner 1 month ago
A large portion of interrupt count entries are zero. There is no point in
formatting the zero value as it is way cheeper to just emit a constant
string.

Collect the number of consecutive zero counts and emit them in one go
before a non-zero count and at the end of the line.

Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
 include/linux/interrupt.h |    1 +
 kernel/irq/proc.c         |   42 +++++++++++++++++++++++++++++++++++++-----
 2 files changed, 38 insertions(+), 5 deletions(-)

--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -864,6 +864,7 @@ static inline void init_irq_proc(void)
 struct seq_file;
 int show_interrupts(struct seq_file *p, void *v);
 int arch_show_interrupts(struct seq_file *p, int prec);
+void irq_proc_emit_counts(struct seq_file *p, unsigned int __percpu *cnts);
 
 extern int early_irq_init(void);
 extern int arch_probe_nr_irqs(void);
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -450,6 +450,42 @@ int __weak arch_show_interrupts(struct s
 # define ACTUAL_NR_IRQS irq_get_nr_irqs()
 #endif
 
+#define ZSTR1 "          0"
+#define ZSTR1_LEN	11
+#define ZSTR16		ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 \
+			ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1
+#define ZSTR256		ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 \
+			ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16
+
+static inline void irq_proc_emit_zero_counts(struct seq_file *p, unsigned int zeros)
+{
+	if (!zeros)
+		return;
+
+	for (unsigned int n = min(zeros, 256); n; zeros -= n, n = min(zeros, 256))
+		seq_write(p, ZSTR256, n * ZSTR1_LEN);
+}
+
+static inline unsigned int irq_proc_emit_count(struct seq_file *p, unsigned int cnt,
+					       unsigned int zeros)
+{
+	if (!cnt)
+		return zeros + 1;
+
+	irq_proc_emit_zero_counts(p, zeros);
+	seq_put_decimal_ull_width(p, " ", cnt, 10);
+	return 0;
+}
+
+void irq_proc_emit_counts(struct seq_file *p, unsigned int __percpu *cnts)
+{
+	unsigned int cpu, zeros = 0;
+
+	for_each_online_cpu(cpu)
+		zeros = irq_proc_emit_count(p, per_cpu(*cnts, cpu), zeros);
+	irq_proc_emit_zero_counts(p, zeros);
+}
+
 int show_interrupts(struct seq_file *p, void *v)
 {
 	const unsigned int nr_irqs = irq_get_nr_irqs();
@@ -485,11 +521,7 @@ int show_interrupts(struct seq_file *p,
 		return 0;
 
 	seq_printf(p, "%*d:", prec, i);
-	for_each_online_cpu(j) {
-		unsigned int cnt = desc->kstat_irqs ? per_cpu(desc->kstat_irqs->cnt, j) : 0;
-
-		seq_put_decimal_ull_width(p, " ", cnt, 10);
-	}
+	irq_proc_emit_counts(p, &desc->kstat_irqs->cnt);
 	seq_putc(p, ' ');
 
 	guard(raw_spinlock_irq)(&desc->lock);
Re: [patch 02/14] genirq/proc: Avoid formatting zero counts in /proc/interrupts
Posted by Dmitry Ilvokhin 1 month ago
On Wed, Mar 04, 2026 at 07:55:36PM +0100, Thomas Gleixner wrote:
> A large portion of interrupt count entries are zero. There is no point in
> formatting the zero value as it is way cheeper to just emit a constant
> string.
> 
> Collect the number of consecutive zero counts and emit them in one go
> before a non-zero count and at the end of the line.
> 
> Signed-off-by: Thomas Gleixner <tglx@kernel.org>
> ---
>  include/linux/interrupt.h |    1 +
>  kernel/irq/proc.c         |   42 +++++++++++++++++++++++++++++++++++++-----
>  2 files changed, 38 insertions(+), 5 deletions(-)
> 
> --- a/include/linux/interrupt.h
> +++ b/include/linux/interrupt.h
> @@ -864,6 +864,7 @@ static inline void init_irq_proc(void)
>  struct seq_file;
>  int show_interrupts(struct seq_file *p, void *v);
>  int arch_show_interrupts(struct seq_file *p, int prec);
> +void irq_proc_emit_counts(struct seq_file *p, unsigned int __percpu *cnts);
>  
>  extern int early_irq_init(void);
>  extern int arch_probe_nr_irqs(void);
> --- a/kernel/irq/proc.c
> +++ b/kernel/irq/proc.c
> @@ -450,6 +450,42 @@ int __weak arch_show_interrupts(struct s
>  # define ACTUAL_NR_IRQS irq_get_nr_irqs()
>  #endif
>  
> +#define ZSTR1 "          0"
> +#define ZSTR1_LEN	11

Nit: ZSTR1_LEN could be derived from ZSTR1 to avoid a silent mismatch
if the string is ever changed (which is unlikely, but still).

#define ZSTR1_LEN	(sizeof(ZSTR1) - 1)

Reviewed-by: Dmitry Ilvokhin <d@ilvokhin.com>