• Ming Lei's avatar
    ARM: 7746/1: mm: lazy cache flushing on non-mapped pages · 81f28946
    Ming Lei authored
    Currently flush_dcache_page() thinks pages as non-mapped if
    mapping_mapped(mapping) return false. This approach is very
    coase:
    	- mmap on part of file may cause all pages backed on
    	the file being thought as mmaped
    
    	- file-backed pages aren't mapped into user space actually
    	if the memory mmaped on the file isn't accessed
    
    This patch uses page_mapped() to decide if the page has been
    mapped.
    
    From the attached test code, I find there is much performance
    improvement(>25%) when accessing page caches via read under this
    situations, so memcpy benefits a lot from not flushing cache
    under this situation.
    
    No.   read time without the patch	No. read time with the patch
    ================================================================
    No. 0, time  22615636 us		No. 0, time  22014717 us
    No. 1, time  4387851 us 		No. 1, time  3113184 us
    No. 2, time  4276535 us 		No. 2, time  3005244 us
    No. 3, time  42598219 us 		No. 3, time  3001565 us
    No. 4, time  4263811 us 		No. 4, time  3002748 us
    No. 5, time  4258486 us 		No. 5, time  3004104 us
    No. 6, time  4253009 us 		No. 6, time  3002188 us
    No. 7, time  4262809 us 		No. 7, time  2998196 us
    No. 8, time  4264525 us 		No. 8, time  3007255 us
    No. 9, time  4267795 us 		No. 9, time  3005094 us
    
    1), No.0. is to read the file from storage device, and others are
    to read the file from page caches basically.
    2), file size is 512M, and is on ext4 over usb mass storage.
    3), the test is done on Pandaboard.
    
    unsigned int  sum = 0;
    unsigned long sum_val = 0;
    
    static unsigned long tv_diff(struct timeval *tv1, struct timeval *tv2)
    {
    	return (tv2->tv_sec - tv1->tv_sec) * 1000000 +
    		(tv2->tv_usec - tv1->tv_usec);
    }
    
    int main(int argc, char *argv[])
    {
    	char *mbuf, fbuf;
    	int fd;
    	int i;
    	unsigned long page_size, size;
    	struct stat stat;
    	struct timeval t1, t2;
    	unsigned char *rbuf = malloc(32 * page_size);
    
    	if (!rbuf) {
    		printf("	%sn", "malloc failed");
    		exit(-1);
    	}
    
    	page_size = getpagesize();
    	fd = open(argv[1], O_RDWR);
    	assert(fd >= 0);
    
    	fstat(fd, &stat);
    	size = stat.st_size;
    	printf("%s: file %s, size %lu, page size %lun",
    		argv[0],
    		argv[1], size, page_size);
    
    	gettimeofday(&t1, NULL);
    	mbuf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    	if (!mbuf) {
    		printf("	%sn", "mmap failed");
    		exit(-1);
    	}
    
    	for (i = 0 ; i < size ; i += (page_size * 32)) {
    		int rcnt;
    		lseek(fd, i, SEEK_SET);
    		rcnt = read(fd, rbuf, page_size * 32);
    		if (rcnt != page_size * 32) {
    			printf("%s: read faildn", __func__);
    			exit(-1);
    		}
    	}
    	free(rbuf);
    	munmap(mbuf, size);
    	gettimeofday(&t2, NULL);
    	printf("tread mmaped time: %luusn", tv_diff(&t1, &t2));
    
    	close(fd);
    }
    
    Cc: Michel Lespinasse <walken@google.com>
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
    Reviewed-by: default avatarWill Deacon <will.deacon@arm.com>
    Acked-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    Signed-off-by: default avatarMing Lei <ming.lei@canonical.com>
    Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
    81f28946
flush.c 8.56 KB