seq_file: Optimize seq_puts()
authorChristophe JAILLET <christophe.jaillet@wanadoo.fr>
Mon, 22 Apr 2024 10:24:06 +0000 (12:24 +0200)
committerChristian Brauner <brauner@kernel.org>
Thu, 2 May 2024 14:28:15 +0000 (16:28 +0200)
Most of seq_puts() usages are done with a string literal. In such cases,
the length of the string car be computed at compile time in order to save
a strlen() call at run-time. seq_putc() or seq_write() can then be used
instead.

This saves a few cycles.

To have an estimation of how often this optimization triggers:
   $ git grep seq_puts.*\" | wc -l
   3436

   $ git grep seq_puts.*\".\" | wc -l
   84

Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Link: https://lore.kernel.org/r/a8589bffe4830dafcb9111e22acf06603fea7132.1713781332.git.christophe.jaillet@wanadoo.fr
Signed-off-by: Christian Brauner <brauner@kernel.org>
The output for seq_putc() generation has also be checked and works.

fs/seq_file.c
include/linux/seq_file.h

index f5fdaf3b157286d20c5c9c252df7d0885723e2e4..8ef0a07033ca37d81a1004e81a1b9ff6361c1822 100644 (file)
@@ -669,7 +669,7 @@ void seq_putc(struct seq_file *m, char c)
 }
 EXPORT_SYMBOL(seq_putc);
 
-void seq_puts(struct seq_file *m, const char *s)
+void __seq_puts(struct seq_file *m, const char *s)
 {
        int len = strlen(s);
 
@@ -680,7 +680,7 @@ void seq_puts(struct seq_file *m, const char *s)
        memcpy(m->buf + m->count, s, len);
        m->count += len;
 }
-EXPORT_SYMBOL(seq_puts);
+EXPORT_SYMBOL(__seq_puts);
 
 /**
  * seq_put_decimal_ull_width - A helper routine for putting decimal numbers
index 234bcdb1fba459916635067154bedd17d8cfd423..8bd4fda6e02752433832ef78d1afb0cea7870178 100644 (file)
@@ -118,7 +118,18 @@ void seq_vprintf(struct seq_file *m, const char *fmt, va_list args);
 __printf(2, 3)
 void seq_printf(struct seq_file *m, const char *fmt, ...);
 void seq_putc(struct seq_file *m, char c);
-void seq_puts(struct seq_file *m, const char *s);
+void __seq_puts(struct seq_file *m, const char *s);
+
+static __always_inline void seq_puts(struct seq_file *m, const char *s)
+{
+       if (!__builtin_constant_p(*s))
+               __seq_puts(m, s);
+       else if (s[0] && !s[1])
+               seq_putc(m, s[0]);
+       else
+               seq_write(m, s, __builtin_strlen(s));
+}
+
 void seq_put_decimal_ull_width(struct seq_file *m, const char *delimiter,
                               unsigned long long num, unsigned int width);
 void seq_put_decimal_ull(struct seq_file *m, const char *delimiter,