Skip to content

Commit

Permalink
lib: Add memperf test
Browse files Browse the repository at this point in the history
This patch adds a custom test for measuring performance of
memcpy(), memset(), and memmove() functions

DO NOT UPSTREAM !!!!!

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
  • Loading branch information
avpatel committed Jan 28, 2022
1 parent e7c36e9 commit ad86979
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
7 changes: 7 additions & 0 deletions lib/Kconfig
Expand Up @@ -8,6 +8,13 @@ config BINARY_PRINTF

menu "Library routines"

config MEMPERF_TEST
tristate "Mem* performance tests"
depends on CONTIG_ALLOC
default n
help
Check performance of memcpy, memset, and memmove functions.

config RAID6_PQ
tristate

Expand Down
2 changes: 2 additions & 0 deletions lib/Makefile
Expand Up @@ -366,6 +366,8 @@ obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o

obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o

obj-$(CONFIG_MEMPERF_TEST) += memperf_test.o

# FORTIFY_SOURCE compile-time behavior tests
TEST_FORTIFY_SRCS = $(wildcard $(srctree)/$(src)/test_fortify/*-*.c)
TEST_FORTIFY_LOGS = $(patsubst $(srctree)/$(src)/%.c, %.log, $(TEST_FORTIFY_SRCS))
Expand Down
107 changes: 107 additions & 0 deletions lib/memperf_test.c
@@ -0,0 +1,107 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timekeeping.h>

static unsigned long memorder = 12;
module_param(memorder, ulong, 0600);
MODULE_PARM_DESC(memorder, "Log2 of number of pages");

static unsigned long linesz = sizeof(long);
module_param(linesz, ulong, 0600);
MODULE_PARM_DESC(linesz, "Size of cache line");

#define MEM_ORDER memorder
#define MEM_PAGES BIT(MEM_ORDER)
#define MEM_SIZE (PAGE_SIZE * MEM_PAGES)

static __init void memset_perf_test(void)
{
int i;
void *dst;
ktime_t t0, t1;
struct page *dpage;
unsigned long long mbps;

printk("memperf: memset test linesz=%lu memorder=%lu memsize=%luMB\n\n",
linesz, MEM_ORDER, MEM_SIZE / 1048576UL);

dpage = alloc_contig_pages(MEM_PAGES, GFP_KERNEL, NUMA_NO_NODE, 0);
dst = page_to_virt(dpage);

for (i = 0; i < linesz; i++) {
t0 = ktime_get();
memset(dst + i, 0 + i, MEM_SIZE - i);
t1 = ktime_get();
mbps = MEM_SIZE * (1000000000ULL / 1048576ULL) * 8ULL;
mbps = mbps / (t1 - t0);
printk("memperf: memset(dst+%d): %llu Mb/s\n", i, mbps);
}

free_contig_range(page_to_pfn(dpage), MEM_PAGES);

printk("\n");
}

static __init void memcpy_memmove_perf_test(bool cpy)
{
int i, j;
ktime_t t0, t1;
void *src, *dst;
unsigned long long mbps;
struct page *spage, *dpage;

printk("memperf: %s test linesz=%lu memorder=%lu memsize=%luMB,\n\n",
(cpy) ? "memcpy" : "memmove", linesz,
MEM_ORDER, MEM_SIZE / 1048576UL);

spage = alloc_contig_pages(MEM_PAGES, GFP_KERNEL, NUMA_NO_NODE, 0);
src = page_to_virt(spage);
dpage = alloc_contig_pages(MEM_PAGES, GFP_KERNEL, NUMA_NO_NODE, 0);
dst = page_to_virt(dpage);

for (i = 0; i < linesz; i++) {
for (j = 0; j < linesz; j++) {
t0 = ktime_get();
if (cpy)
memcpy(dst + i, src + j, MEM_SIZE - max(i, j));
else
memmove(dst + i, src + j, MEM_SIZE - max(i, j));
t1 = ktime_get();
mbps = MEM_SIZE * (1000000000ULL / 1048576ULL) * 8ULL;
mbps = mbps / (t1 - t0);
printk("memperf: %s(dst+%d, src+%d), distance %lu: %llu Mb/s\n",
(cpy) ? "memcpy" : "memmove", i, j,
(j - i) % sizeof(long), mbps);
}
printk("\n");
}

free_contig_range(page_to_pfn(dpage), MEM_PAGES);
free_contig_range(page_to_pfn(spage), MEM_PAGES);
}

static __init int memperf_test_init(void)
{
/* Do memset() performance test */
memset_perf_test();

/* Do memcpy() performance test */
memcpy_memmove_perf_test(true);

/* Do memmove() performance test */
memcpy_memmove_perf_test(false);

return 0;
}

static __exit void memperf_test_exit(void)
{
}

module_init(memperf_test_init);
module_exit(memperf_test_exit);
MODULE_LICENSE("GPL v2");

0 comments on commit ad86979

Please sign in to comment.