diff options
author | Christophe JAILLET <christophe.jaillet@wanadoo.fr> | 2024-04-22 12:24:06 +0200 |
---|---|---|
committer | Christian Brauner <brauner@kernel.org> | 2024-05-02 16:28:15 +0200 |
commit | 45751097aeb386eb239f6a8ed0ccfd7dabce068e (patch) | |
tree | 1dea3dfa299c70189a729c6343d9941df709f536 | |
parent | 0a960ba49869ebe8ff859d000351504dd6b93b68 (diff) |
seq_file: Optimize seq_puts()
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.
-rw-r--r-- | fs/seq_file.c | 4 | ||||
-rw-r--r-- | include/linux/seq_file.h | 13 |
2 files changed, 14 insertions, 3 deletions
diff --git a/fs/seq_file.c b/fs/seq_file.c index f5fdaf3b1572..8ef0a07033ca 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -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 diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index 234bcdb1fba4..8bd4fda6e027 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h @@ -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, |