diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2012-03-23 18:02:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-23 19:58:42 -0400 |
commit | 1ac101a5d675aca2426c5cd460c73fb95acb8391 (patch) | |
tree | 5d993fde0c5e67de97c0d9ffac54163f06fc90c9 /fs/seq_file.c | |
parent | 59a32e2ce5eb809967cac4e718bc527beca83c59 (diff) |
procfs: add num_to_str() to speed up /proc/stat
== stat_check.py
num = 0
with open("/proc/stat") as f:
while num < 1000 :
data = f.read()
f.seek(0, 0)
num = num + 1
==
perf shows
20.39% stat_check.py [kernel.kallsyms] [k] format_decode
13.41% stat_check.py [kernel.kallsyms] [k] number
12.61% stat_check.py [kernel.kallsyms] [k] vsnprintf
10.85% stat_check.py [kernel.kallsyms] [k] memcpy
4.85% stat_check.py [kernel.kallsyms] [k] radix_tree_lookup
4.43% stat_check.py [kernel.kallsyms] [k] seq_printf
This patch removes most of calls to vsnprintf() by adding num_to_str()
and seq_print_decimal_ull(), which prints decimal numbers without rich
functions provided by printf().
On my 8cpu box.
== Before patch ==
[root@bluextal test]# time ./stat_check.py
real 0m0.150s
user 0m0.026s
sys 0m0.121s
== After patch ==
[root@bluextal test]# time ./stat_check.py
real 0m0.055s
user 0m0.022s
sys 0m0.030s
[akpm@linux-foundation.org: remove incorrect comment, use less statck in num_to_str(), move comment from .h to .c, simplify seq_put_decimal_ull()]
[andrea@betterlinux.com: avoid breaking the ABI in /proc/stat]
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Andrea Righi <andrea@betterlinux.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Glauber Costa <glommer@parallels.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Turner <pjt@google.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/seq_file.c')
-rw-r--r-- | fs/seq_file.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/fs/seq_file.c b/fs/seq_file.c index aa242dc99373..7d19816c4cc9 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c | |||
@@ -644,6 +644,39 @@ int seq_puts(struct seq_file *m, const char *s) | |||
644 | } | 644 | } |
645 | EXPORT_SYMBOL(seq_puts); | 645 | EXPORT_SYMBOL(seq_puts); |
646 | 646 | ||
647 | /* | ||
648 | * A helper routine for putting decimal numbers without rich format of printf(). | ||
649 | * only 'unsigned long long' is supported. | ||
650 | * This routine will put one byte delimiter + number into seq_file. | ||
651 | * This routine is very quick when you show lots of numbers. | ||
652 | * In usual cases, it will be better to use seq_printf(). It's easier to read. | ||
653 | */ | ||
654 | int seq_put_decimal_ull(struct seq_file *m, char delimiter, | ||
655 | unsigned long long num) | ||
656 | { | ||
657 | int len; | ||
658 | |||
659 | if (m->count + 2 >= m->size) /* we'll write 2 bytes at least */ | ||
660 | goto overflow; | ||
661 | |||
662 | m->buf[m->count++] = delimiter; | ||
663 | |||
664 | if (num < 10) { | ||
665 | m->buf[m->count++] = num + '0'; | ||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | len = num_to_str(m->buf + m->count, m->size - m->count, num); | ||
670 | if (!len) | ||
671 | goto overflow; | ||
672 | m->count += len; | ||
673 | return 0; | ||
674 | overflow: | ||
675 | m->count = m->size; | ||
676 | return -1; | ||
677 | } | ||
678 | EXPORT_SYMBOL(seq_put_decimal_ull); | ||
679 | |||
647 | /** | 680 | /** |
648 | * seq_write - write arbitrary data to buffer | 681 | * seq_write - write arbitrary data to buffer |
649 | * @seq: seq_file identifying the buffer to which data should be written | 682 | * @seq: seq_file identifying the buffer to which data should be written |