[i-g-t] gem_userptr_benchmark: Test overlapping bo mmu notifier performance impact
diff mbox

Message ID 1433153475-27649-1-git-send-email-tvrtko.ursulin@linux.intel.com
State New
Headers show

Commit Message

Tvrtko Ursulin June 1, 2015, 10:11 a.m. UTC
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Current userptr kernel implementation downgrades tracking VMA ranges (real
userspace ones) to an inefficient linear walk for any process which has
instantiated overlapping userptr objects.

This adds a test which shows the performance cliff on, most visibly, generic
userspace mmap(2) and munmap(2) operations between unsync, non-overlapping
and overlapping userptr objects.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Thomas Daniel <thomas.daniel@intel.com>
---
 benchmarks/gem_userptr_benchmark.c | 97 +++++++++++++++++++++++++++++---------
 1 file changed, 74 insertions(+), 23 deletions(-)

Comments

Chris Wilson June 2, 2015, 12:52 p.m. UTC | #1
On Mon, Jun 01, 2015 at 11:11:15AM +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> 
> Current userptr kernel implementation downgrades tracking VMA ranges (real
> userspace ones) to an inefficient linear walk for any process which has
> instantiated overlapping userptr objects.
> 
> This adds a test which shows the performance cliff on, most visibly, generic
> userspace mmap(2) and munmap(2) operations between unsync, non-overlapping
> and overlapping userptr objects.
> 
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Thomas Daniel <thomas.daniel@intel.com>

Looked good, pushed.
Thanks,
-Chris

Patch
diff mbox

diff --git a/benchmarks/gem_userptr_benchmark.c b/benchmarks/gem_userptr_benchmark.c
index 4d7442b..b804fdd 100644
--- a/benchmarks/gem_userptr_benchmark.c
+++ b/benchmarks/gem_userptr_benchmark.c
@@ -180,7 +180,7 @@  static int has_userptr(int fd)
 	return handle != 0;
 }
 
-static const unsigned int nr_bos[] = {0, 1, 10, 100, 1000};
+static const unsigned int nr_bos[] = {0, 1, 10, 100, 1000, 10000};
 static const unsigned int test_duration_sec = 3;
 
 static volatile unsigned int run_test;
@@ -334,43 +334,88 @@  static void test_ptr_write(void *ptr)
 	printf("%8lu MB/s\n", iter / test_duration_sec * BO_SIZE / 1000000);
 }
 
-static void test_impact(int fd)
+static void do_impact_tests(unsigned int n, const char *pfix, const char *pfix2,
+			    void *ptr)
+{
+	printf("%s%sptr-read,                   %5u bos = ", pfix, pfix2, n);
+	test_ptr_read(ptr);
+
+	printf("%s%sptr-write                   %5u bos = ", pfix, pfix2, n);
+	test_ptr_write(ptr);
+
+	printf("%s%smalloc-free,                %5u bos = ", pfix, pfix2, n);
+	test_malloc_free(0);
+	printf("%s%smalloc-free-random          %5u bos = ", pfix, pfix2, n);
+	test_malloc_free(1);
+
+	printf("%s%smalloc-realloc-free,        %5u bos = ", pfix, pfix2, n);
+	test_malloc_realloc_free(0);
+	printf("%s%smalloc-realloc-free-random, %5u bos = ", pfix, pfix2, n);
+	test_malloc_realloc_free(1);
+
+	printf("%s%smmap-unmap,                 %5u bos = ", pfix, pfix2, n);
+	test_mmap_unmap(0);
+	printf("%s%smmap-unmap-random,          %5u bos = ", pfix, pfix2, n);
+	test_mmap_unmap(1);
+}
+
+static void test_impact_overlap(int fd, const char *prefix)
 {
 	unsigned int total = sizeof(nr_bos) / sizeof(nr_bos[0]);
 	unsigned int subtest, i;
 	uint32_t handles[nr_bos[total-1]];
+	void *block = NULL;
 	void *ptr;
+	unsigned char *p;
 	char buffer[BO_SIZE];
+	int ret;
 
 	for (subtest = 0; subtest < total; subtest++) {
-		for (i = 0; i < nr_bos[subtest]; i++)
-			handles[i] = create_userptr_bo(fd, BO_SIZE);
+		if (nr_bos[subtest] > 0) {
+			igt_assert(PAGE_SIZE < BO_SIZE);
+			ret = posix_memalign(&block, PAGE_SIZE,
+					PAGE_SIZE * nr_bos[subtest] + BO_SIZE);
+			igt_assert(ret == 0);
+
+			for (i = 0, p = block; i < nr_bos[subtest];
+			     i++, p += PAGE_SIZE)
+				ret = gem_userptr(fd, (uint32_t *)p, BO_SIZE, 0,
+						  &handles[i]);
+				igt_assert(ret == 0);
+		}
 
 		if (nr_bos[subtest] > 0)
-			ptr = get_handle_ptr(handles[0]);
+			ptr = block;
 		else
 			ptr = buffer;
 
-		printf("ptr-read,                   %5u bos = ", nr_bos[subtest]);
-		test_ptr_read(ptr);
+		do_impact_tests(nr_bos[subtest], prefix, "overlap-", ptr);
 
-		printf("ptr-write                   %5u bos = ", nr_bos[subtest]);
-		test_ptr_write(ptr);
+		for (i = 0; i < nr_bos[subtest]; i++)
+			gem_close(fd, handles[i]);
+		if (block)
+			free(block);
+	}
+}
 
-		printf("malloc-free,                %5u bos = ", nr_bos[subtest]);
-		test_malloc_free(0);
-		printf("malloc-free-random          %5u bos = ", nr_bos[subtest]);
-		test_malloc_free(1);
+static void test_impact(int fd, const char *prefix)
+{
+	unsigned int total = sizeof(nr_bos) / sizeof(nr_bos[0]);
+	unsigned int subtest, i;
+	uint32_t handles[nr_bos[total-1]];
+	void *ptr;
+	char buffer[BO_SIZE];
 
-		printf("malloc-realloc-free,        %5u bos = ", nr_bos[subtest]);
-		test_malloc_realloc_free(0);
-		printf("malloc-realloc-free-random, %5u bos = ", nr_bos[subtest]);
-		test_malloc_realloc_free(1);
+	for (subtest = 0; subtest < total; subtest++) {
+		for (i = 0; i < nr_bos[subtest]; i++)
+			handles[i] = create_userptr_bo(fd, BO_SIZE);
 
-		printf("mmap-unmap,                 %5u bos = ", nr_bos[subtest]);
-		test_mmap_unmap(0);
-		printf("mmap-unmap-random,          %5u bos = ", nr_bos[subtest]);
-		test_mmap_unmap(1);
+		if (nr_bos[subtest] > 0)
+			ptr = get_handle_ptr(handles[0]);
+		else
+			ptr = buffer;
+
+		do_impact_tests(nr_bos[subtest], prefix, "no-overlap-", ptr);
 
 		for (i = 0; i < nr_bos[subtest]; i++)
 			free_userptr_bo(fd, handles[i]);
@@ -484,7 +529,10 @@  int main(int argc, char **argv)
 		test_userptr(fd);
 
 	igt_subtest("userptr-impact-unsync")
-		test_impact(fd);
+		test_impact(fd, "unsync-");
+
+	igt_subtest("userptr-impact-unsync-overlap")
+		test_impact_overlap(fd, "unsync-");
 
 	gem_userptr_test_synchronized();
 
@@ -492,7 +540,10 @@  int main(int argc, char **argv)
 		test_userptr(fd);
 
 	igt_subtest("userptr-impact-sync")
-		test_impact(fd);
+		test_impact(fd, "sync-");
+
+	igt_subtest("userptr-impact-sync-overlap")
+		test_impact_overlap(fd, "sync-");
 
 	igt_exit();