vsprintf: rework bitmap_list_string
authorYury Norov <yury.norov@gmail.com>
Sat, 14 Aug 2021 21:17:13 +0000 (14:17 -0700)
committerYury Norov <yury.norov@gmail.com>
Sat, 15 Jan 2022 16:47:31 +0000 (08:47 -0800)
bitmap_list_string() is very ineffective when printing bitmaps with long
ranges of set bits because it calls find_next_bit for each bit in the
bitmap.  We can do better by detecting ranges of set bits.

In my environment, before/after is 943008/31008 ns.

Signed-off-by: Yury Norov <yury.norov@gmail.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
lib/vsprintf.c

index 58d5e56..d4b4e48 100644 (file)
@@ -1241,20 +1241,13 @@ char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap,
                         struct printf_spec spec, const char *fmt)
 {
        int nr_bits = max_t(int, spec.field_width, 0);
-       /* current bit is 'cur', most recently seen range is [rbot, rtop] */
-       int cur, rbot, rtop;
        bool first = true;
+       int rbot, rtop;
 
        if (check_pointer(&buf, end, bitmap, spec))
                return buf;
 
-       rbot = cur = find_first_bit(bitmap, nr_bits);
-       while (cur < nr_bits) {
-               rtop = cur;
-               cur = find_next_bit(bitmap, nr_bits, cur + 1);
-               if (cur < nr_bits && cur <= rtop + 1)
-                       continue;
-
+       for_each_set_bitrange(rbot, rtop, bitmap, nr_bits) {
                if (!first) {
                        if (buf < end)
                                *buf = ',';
@@ -1263,15 +1256,12 @@ char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap,
                first = false;
 
                buf = number(buf, end, rbot, default_dec_spec);
-               if (rbot < rtop) {
-                       if (buf < end)
-                               *buf = '-';
-                       buf++;
-
-                       buf = number(buf, end, rtop, default_dec_spec);
-               }
+               if (rtop == rbot + 1)
+                       continue;
 
-               rbot = cur;
+               if (buf < end)
+                       *buf = '-';
+               buf = number(++buf, end, rtop - 1, default_dec_spec);
        }
        return buf;
 }