[PATCH v2 1/2] Use memset() to improve the 1st bitmap initialization performance

HATAYAMA Daisuke d.hatayama at jp.fujitsu.com
Mon Nov 4 10:22:43 EST 2013


Currently, 1st bitmap is initialized per bits. This is very slow, in
particular, on large memory system more than tera bytes. Instead, use
memset() to initialize bitmap quickly.

This helps next patch that changes the 1st bitmap creation to be done
at each cycle.

Here area a simple benchmark program that measures initialization time
for 384 MiB bitmap corresponding to 12 TiB memory.

On Xeon E7-4820 2.00GHz, output example is as follows:

$ ./bench
17.420970
0.340347

Also, the average result of 10 times excluding max and min are:

old: 17.453785 sec
new:  0.340808 sec

==
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

enum {
        PAGE_SIZE = 4096,
        BITSPERBYTE = 8,
};

static inline double getdtime(void)
{
        struct timeval tv;
        gettimeofday(&tv, NULL);
        return (double)tv.tv_sec + (double)tv.tv_usec * 1.0e-6;
}

int main(int argc, char **argv)
{
        const unsigned long long mem_size = 12ULL << 40;
        const unsigned long long max_pfn = mem_size / PAGE_SIZE;
        const size_t bitmap_size = max_pfn / BITSPERBYTE;
        char *bitmap1 = calloc(bitmap_size, sizeof(char));
        char *bitmap2 = calloc(bitmap_size, sizeof(char));
        unsigned long long pfn;
        double t1, t2;

        t1 = getdtime();
        for (pfn = 0; pfn < max_pfn; ++pfn) {
                bitmap1[pfn >> 3] |= 1 << (pfn & 7);
        }
        t2 = getdtime();

        printf("%lf\n", t2 - t1);

        t1 = getdtime();
        memset(bitmap2, 0xff, bitmap_size);
        t2 = getdtime();

        printf("%lf\n", t2 - t1);

        return 0;
}
==

Signed-off-by: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com>
---
 makedumpfile.c |   28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index 428c53e..4b6c0ed 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -4317,6 +4317,8 @@ create_1st_bitmap_cyclic()
 	unsigned long long pfn, pfn_bitmap1;
 	unsigned long long phys_start, phys_end;
 	unsigned long long pfn_start, pfn_end;
+	unsigned long long pfn_start_roundup, pfn_end_round;
+	unsigned long pfn_start_byte, pfn_end_byte;
 
 	/*
 	 * At first, clear all the bits on the 1st-bitmap.
@@ -4329,10 +4331,30 @@ create_1st_bitmap_cyclic()
 	 */
 	pfn_bitmap1 = 0;
 	for (i = 0; get_pt_load(i, &phys_start, &phys_end, NULL, NULL); i++) {
-		pfn_start = paddr_to_pfn(phys_start);
-		pfn_end   = paddr_to_pfn(phys_end);
+		pfn_start = MAX(paddr_to_pfn(phys_start), info->cyclic_start_pfn);
+		pfn_end   = MIN(paddr_to_pfn(phys_end), info->cyclic_end_pfn);
 
-		for (pfn = pfn_start; pfn < pfn_end; pfn++) {
+		if (pfn_start >= pfn_end)
+			continue;
+
+		pfn_start_roundup = roundup(pfn_start, BITPERBYTE);
+		pfn_end_round = round(pfn_end, BITPERBYTE);
+
+		for (pfn = pfn_start; pfn < pfn_start_roundup; pfn++) {
+			if (set_bit_on_1st_bitmap(pfn))
+				pfn_bitmap1++;
+		}
+
+		pfn_start_byte = (pfn_start_roundup - info->cyclic_start_pfn) >> 3;
+		pfn_end_byte = (pfn_end_round - info->cyclic_start_pfn) >> 3;
+
+		memset(info->partial_bitmap1 + pfn_start_byte,
+		       0xff,
+		       pfn_end_byte - pfn_start_byte);
+
+		pfn_bitmap1 += (pfn_end_byte - pfn_start_byte) * BITPERBYTE;
+
+		for (pfn = pfn_end_round; pfn < pfn_end; pfn++) {
 			if (set_bit_on_1st_bitmap(pfn))
 				pfn_bitmap1++;
 		}




More information about the kexec mailing list