aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAndrei Vagin <avagin@openvz.org>2018-04-10 19:30:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-11 13:28:32 -0400
commit0e3dc019143104a6e676287b1e453cccd7add404 (patch)
treeb3aa6e165b872e86fdf5be2fe113adae58e2ee6e /fs
parent69ca372c100fba99c78ef826a1795aa86e4f01a8 (diff)
procfs: add seq_put_hex_ll to speed up /proc/pid/maps
seq_put_hex_ll() prints a number in hexadecimal notation and works faster than seq_printf(). == test.py num = 0 with open("/proc/1/maps") as f: while num < 10000 : data = f.read() f.seek(0, 0) num = num + 1 == == Before patch == $ time python test.py real 0m1.561s user 0m0.257s sys 0m1.302s == After patch == $ time python test.py real 0m0.986s user 0m0.279s sys 0m0.707s $ perf -g record python test.py: == Before patch == - 67.42% 2.82% python [kernel.kallsyms] [k] show_map_vma.isra.22 - 64.60% show_map_vma.isra.22 - 44.98% seq_printf - seq_vprintf - vsnprintf + 14.85% number + 12.22% format_decode 5.56% memcpy_erms + 15.06% seq_path + 4.42% seq_pad + 2.45% __GI___libc_read == After patch == - 47.35% 3.38% python [kernel.kallsyms] [k] show_map_vma.isra.23 - 43.97% show_map_vma.isra.23 + 20.84% seq_path - 15.73% show_vma_header_prefix 10.55% seq_put_hex_ll + 2.65% seq_put_decimal_ull 0.95% seq_putc + 6.96% seq_pad + 2.94% __GI___libc_read [avagin@openvz.org: use unsigned int instead of int where it is suitable] Link: http://lkml.kernel.org/r/20180214025619.4005-1-avagin@openvz.org [avagin@openvz.org: v2] Link: http://lkml.kernel.org/r/20180117082050.25406-1-avagin@openvz.org Link: http://lkml.kernel.org/r/20180112185812.7710-1-avagin@openvz.org Signed-off-by: Andrei Vagin <avagin@openvz.org> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/proc/task_mmu.c21
-rw-r--r--fs/seq_file.c46
2 files changed, 58 insertions, 9 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index ec6d2983a5cb..b66fc8de7d34 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -287,15 +287,18 @@ static void show_vma_header_prefix(struct seq_file *m,
287 dev_t dev, unsigned long ino) 287 dev_t dev, unsigned long ino)
288{ 288{
289 seq_setwidth(m, 25 + sizeof(void *) * 6 - 1); 289 seq_setwidth(m, 25 + sizeof(void *) * 6 - 1);
290 seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ", 290 seq_put_hex_ll(m, NULL, start, 8);
291 start, 291 seq_put_hex_ll(m, "-", end, 8);
292 end, 292 seq_putc(m, ' ');
293 flags & VM_READ ? 'r' : '-', 293 seq_putc(m, flags & VM_READ ? 'r' : '-');
294 flags & VM_WRITE ? 'w' : '-', 294 seq_putc(m, flags & VM_WRITE ? 'w' : '-');
295 flags & VM_EXEC ? 'x' : '-', 295 seq_putc(m, flags & VM_EXEC ? 'x' : '-');
296 flags & VM_MAYSHARE ? 's' : 'p', 296 seq_putc(m, flags & VM_MAYSHARE ? 's' : 'p');
297 pgoff, 297 seq_put_hex_ll(m, " ", pgoff, 8);
298 MAJOR(dev), MINOR(dev), ino); 298 seq_put_hex_ll(m, " ", MAJOR(dev), 2);
299 seq_put_hex_ll(m, ":", MINOR(dev), 2);
300 seq_put_decimal_ull(m, " ", ino);
301 seq_putc(m, ' ');
299} 302}
300 303
301static void 304static void
diff --git a/fs/seq_file.c b/fs/seq_file.c
index eea09f6d8830..cde1bdbf7801 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -715,6 +715,52 @@ overflow:
715} 715}
716EXPORT_SYMBOL(seq_put_decimal_ull); 716EXPORT_SYMBOL(seq_put_decimal_ull);
717 717
718/**
719 * seq_put_hex_ll - put a number in hexadecimal notation
720 * @m: seq_file identifying the buffer to which data should be written
721 * @delimiter: a string which is printed before the number
722 * @v: the number
723 * @width: a minimum field width
724 *
725 * seq_put_hex_ll(m, "", v, 8) is equal to seq_printf(m, "%08llx", v)
726 *
727 * This routine is very quick when you show lots of numbers.
728 * In usual cases, it will be better to use seq_printf(). It's easier to read.
729 */
730void seq_put_hex_ll(struct seq_file *m, const char *delimiter,
731 unsigned long long v, unsigned int width)
732{
733 unsigned int len;
734 int i;
735
736 if (delimiter && delimiter[0]) {
737 if (delimiter[1] == 0)
738 seq_putc(m, delimiter[0]);
739 else
740 seq_puts(m, delimiter);
741 }
742
743 /* If x is 0, the result of __builtin_clzll is undefined */
744 if (v == 0)
745 len = 1;
746 else
747 len = (sizeof(v) * 8 - __builtin_clzll(v) + 3) / 4;
748
749 if (len < width)
750 len = width;
751
752 if (m->count + len > m->size) {
753 seq_set_overflow(m);
754 return;
755 }
756
757 for (i = len - 1; i >= 0; i--) {
758 m->buf[m->count + i] = hex_asc[0xf & v];
759 v = v >> 4;
760 }
761 m->count += len;
762}
763
718void seq_put_decimal_ll(struct seq_file *m, const char *delimiter, long long num) 764void seq_put_decimal_ll(struct seq_file *m, const char *delimiter, long long num)
719{ 765{
720 int len; 766 int len;