mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-08 15:04:45 +00:00
vsprintf: rework bitmap_list_string
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>
This commit is contained in:
parent
db7313005e
commit
15325b4f76
@ -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++;
|
||||
if (rtop == rbot + 1)
|
||||
continue;
|
||||
|
||||
buf = number(buf, end, rtop, default_dec_spec);
|
||||
}
|
||||
|
||||
rbot = cur;
|
||||
if (buf < end)
|
||||
*buf = '-';
|
||||
buf = number(++buf, end, rtop - 1, default_dec_spec);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user