mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Optimize performance of my_bitmap
MDEV-33502 Slowdown when running nested statement with many partitions This change was triggered to help some MariaDB users with close to 10000 bits in their bitmaps. - Change underlaying storage to be 64 bit instead of 32bit. - This reduses number of loops to scan bitmaps. - This can cause some bitmaps to be 4 byte large. - Ensure that all not used top-bits are always 0 (simplifes code as the last 64 bit storage is not a special case anymore). - Use my_find_first_bit() to find the first set bit which is much faster than scanning trough things byte by byte and then bit by bit. Other things: - Added a bool to remember if my_bitmap_init() did allocate the bitmap array. my_bitmap_free() will only free arrays it did allocate. This allowed me to remove setting 'bitmap=0' before calling my_bitmap_free() for cases where the bitmap's where allocated externally. - my_bitmap_init() sets bitmap to 0 in case of failure. - Added 'universal' asserts to most bitmap functions. - Change all remaining calls to bitmap_init() to my_bitmap_init(). - To finish the change from 2014. - Changed all usage of uint32 in my_bitmap.h to my_bitmap_map. - Updated bitmap_copy() to handle bitmaps of different size. - Removed const from bitmap_exists_intersection() as this caused casts on all usage. - Removed not used function bitmap_set_above(). - Renamed create_last_word_mask() to create_last_bit_mask() (to match name changes in my_bitmap.cc) - Extended bitmap-t with test for more bitmap functions.
This commit is contained in:
@@ -29,6 +29,8 @@
|
||||
|
||||
uint get_rand_bit(uint bitsize)
|
||||
{
|
||||
if (bitsize == 0)
|
||||
return 0;
|
||||
return (rand() % bitsize);
|
||||
}
|
||||
|
||||
@@ -266,7 +268,7 @@ my_bool test_get_first_bit(MY_BITMAP *map, uint bitsize)
|
||||
bitmap_clear_all(map);
|
||||
for (i=0; i < bitsize; i++)
|
||||
bitmap_set_bit(map, i);
|
||||
if (bitmap_get_first(map) != MY_BIT_NONE)
|
||||
if (bitmap_get_first_clear(map) != MY_BIT_NONE)
|
||||
goto error2;
|
||||
bitmap_clear_all(map);
|
||||
|
||||
@@ -278,7 +280,7 @@ my_bool test_get_first_bit(MY_BITMAP *map, uint bitsize)
|
||||
goto error1;
|
||||
bitmap_set_all(map);
|
||||
bitmap_clear_bit(map, test_bit);
|
||||
if (bitmap_get_first(map) != test_bit)
|
||||
if (bitmap_get_first_clear(map) != test_bit)
|
||||
goto error2;
|
||||
bitmap_clear_all(map);
|
||||
}
|
||||
@@ -297,14 +299,45 @@ my_bool test_get_next_bit(MY_BITMAP *map, uint bitsize)
|
||||
uint no_loops= bitsize > 128 ? 128 : bitsize;
|
||||
for (i=0; i < no_loops; i++)
|
||||
{
|
||||
uint count= 0, bits_set= 0;
|
||||
bitmap_clear_all(map);
|
||||
test_bit=get_rand_bit(bitsize);
|
||||
for (j=0; j < test_bit; j++)
|
||||
bitmap_set_next(map);
|
||||
if (!bitmap_is_prefix(map, test_bit))
|
||||
goto error1;
|
||||
j= bitmap_get_first_set(map);
|
||||
if (j == MY_BIT_NONE)
|
||||
{
|
||||
if (test_bit != 0)
|
||||
goto error1;
|
||||
continue;
|
||||
}
|
||||
count= 1;
|
||||
while ((j= bitmap_get_next_set(map,j)) != MY_BIT_NONE)
|
||||
count++;
|
||||
if (count != test_bit)
|
||||
goto error1;
|
||||
|
||||
if (test_bit < 3)
|
||||
continue;
|
||||
bitmap_clear_all(map);
|
||||
for (j=1; j < test_bit; j+=2)
|
||||
{
|
||||
bits_set++;
|
||||
bitmap_set_bit(map, j);
|
||||
}
|
||||
if ((j= bitmap_get_first_set(map)) == MY_BIT_NONE)
|
||||
goto error1;
|
||||
count= 1;
|
||||
while ((j= bitmap_get_next_set(map,j)) != MY_BIT_NONE)
|
||||
count++;
|
||||
if (count != bits_set)
|
||||
goto error1;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
error1:
|
||||
diag("get_next error bitsize= %u, prefix_size= %u", bitsize,test_bit);
|
||||
return TRUE;
|
||||
@@ -371,7 +404,7 @@ error5:
|
||||
my_bool test_compare(MY_BITMAP *map, uint bitsize)
|
||||
{
|
||||
MY_BITMAP map2;
|
||||
uint32 map2buf[MAX_TESTED_BITMAP_SIZE];
|
||||
my_bitmap_map map2buf[MAX_TESTED_BITMAP_SIZE];
|
||||
uint i, test_bit;
|
||||
uint no_loops= bitsize > 128 ? 128 : bitsize;
|
||||
if (my_bitmap_init(&map2, map2buf, bitsize, FALSE))
|
||||
@@ -431,7 +464,7 @@ my_bool test_intersect(MY_BITMAP *map, uint bitsize)
|
||||
{
|
||||
uint bitsize2 = 1 + get_rand_bit(MAX_TESTED_BITMAP_SIZE - 1);
|
||||
MY_BITMAP map2;
|
||||
uint32 map2buf[MAX_TESTED_BITMAP_SIZE];
|
||||
my_bitmap_map map2buf[MAX_TESTED_BITMAP_SIZE];
|
||||
uint i, test_bit1, test_bit2, test_bit3;
|
||||
if (my_bitmap_init(&map2, map2buf, bitsize2, FALSE))
|
||||
{
|
||||
@@ -477,6 +510,94 @@ error:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
my_bool test_copy(MY_BITMAP *map, uint bitsize)
|
||||
{
|
||||
my_bitmap_map buff[16];
|
||||
MY_BITMAP map2;
|
||||
my_bitmap_init(&map2, buff, sizeof(buff)*8, FALSE);
|
||||
memset((void*) buff, 0xff, sizeof(buff));
|
||||
|
||||
bitsize= MY_MIN(bitsize, map2.n_bits);
|
||||
bitmap_copy(map, &map2);
|
||||
if (bitmap_bits_set(map) != bitsize)
|
||||
{
|
||||
diag("bitmap_copy failed on bitsize %d", bitsize);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static my_bool exec_bitmap_exists_intersection(MY_BITMAP **maps, uint bitsize,
|
||||
uint start, uint end, uint bit)
|
||||
{
|
||||
bitmap_clear_all(maps[0]);
|
||||
bitmap_clear_all(maps[1]);
|
||||
bitmap_set_bit(maps[0], bit);
|
||||
bitmap_set_bit(maps[1], bit);
|
||||
return bitmap_exists_intersection(maps, 2, start, end);
|
||||
}
|
||||
|
||||
my_bool test_bitmap_exists_intersection(MY_BITMAP *map, uint bitsize)
|
||||
{
|
||||
MY_BITMAP map2;
|
||||
uint start_bit, end_bit, rnd_bit;
|
||||
MY_BITMAP *maps[2];
|
||||
maps[0]= map;
|
||||
maps[1]= &map2;
|
||||
|
||||
my_bitmap_init(&map2, 0, bitsize, FALSE);
|
||||
bitmap_clear_all(map);
|
||||
bitmap_clear_all(&map2);
|
||||
|
||||
start_bit= get_rand_bit(bitsize);
|
||||
end_bit= get_rand_bit(bitsize);
|
||||
if (start_bit > end_bit)
|
||||
swap_variables(uint, start_bit, end_bit);
|
||||
rnd_bit= start_bit+get_rand_bit(end_bit-start_bit);
|
||||
|
||||
if (!exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit,
|
||||
rnd_bit))
|
||||
goto err;
|
||||
|
||||
start_bit= end_bit= rnd_bit= 0;
|
||||
if (!exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit,
|
||||
rnd_bit))
|
||||
goto err;
|
||||
|
||||
start_bit= rnd_bit= 0 ; end_bit= bitsize-1;
|
||||
if (!exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit,
|
||||
rnd_bit))
|
||||
goto err;
|
||||
|
||||
start_bit= rnd_bit= end_bit= bitsize-1;
|
||||
if (!exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit,
|
||||
rnd_bit))
|
||||
goto err;
|
||||
|
||||
if (bitsize > 1)
|
||||
{
|
||||
start_bit= end_bit= 1 ; rnd_bit= 0;
|
||||
if (exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit,
|
||||
rnd_bit))
|
||||
goto err;
|
||||
|
||||
start_bit= end_bit= bitsize-1 ; rnd_bit= bitsize-2;
|
||||
if (exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit,
|
||||
rnd_bit))
|
||||
goto err;
|
||||
}
|
||||
|
||||
my_bitmap_free(&map2);
|
||||
return 0;
|
||||
err:
|
||||
diag("bitmap_exist_intersection failed on bitsize: %d start_bit: %d "
|
||||
"end_bit: %d rnd_bit: %d",
|
||||
bitsize, start_bit, end_bit, rnd_bit);
|
||||
my_bitmap_free(&map2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
my_bool do_test(uint bitsize)
|
||||
{
|
||||
MY_BITMAP map;
|
||||
@@ -515,6 +636,11 @@ my_bool do_test(uint bitsize)
|
||||
bitmap_clear_all(&map);
|
||||
if (test_intersect(&map,bitsize))
|
||||
goto error;
|
||||
bitmap_clear_all(&map);
|
||||
if (test_copy(&map,bitsize))
|
||||
goto error;
|
||||
if (test_bitmap_exists_intersection(&map, bitsize))
|
||||
goto error;
|
||||
return FALSE;
|
||||
error:
|
||||
return TRUE;
|
||||
|
Reference in New Issue
Block a user