2022-12-05 15:44:03

by Keith Busch

[permalink] [raw]
Subject: [PATCH 01/11] dmapool: add alloc/free performance test

From: Keith Busch <[email protected]>

Provide a module that allocates and frees many blocks of various sizes
and report how long it takes. This is intended to provide a consistent
way to measure how changes to the dma_pool_alloc/free routines affect
timing.

Signed-off-by: Keith Busch <[email protected]>
---
mm/Kconfig | 9 +++
mm/Makefile | 1 +
mm/dmapool_test.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 148 insertions(+)
create mode 100644 mm/dmapool_test.c

diff --git a/mm/Kconfig b/mm/Kconfig
index 57e1d8c5b5052..12a78d64eeb72 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -1044,6 +1044,15 @@ config GUP_TEST
comment "GUP_TEST needs to have DEBUG_FS enabled"
depends on !GUP_TEST && !DEBUG_FS

+config DMAPOOL_TEST
+ tristate "Enable a module to run time tests on dma_pool"
+ depends on HAS_DMA
+ help
+ Provides a module that will allocate and free many blocks of various
+ sizes and report how long it takes. This is intended to provide a
+ consistent way to measure how changes to the dma_pool_alloc/free
+ routines affect performance.
+
config GUP_GET_PTE_LOW_HIGH
bool

diff --git a/mm/Makefile b/mm/Makefile
index 8e105e5b3e293..3a08f5d7b1782 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -103,6 +103,7 @@ obj-$(CONFIG_MEMCG) += swap_cgroup.o
endif
obj-$(CONFIG_CGROUP_HUGETLB) += hugetlb_cgroup.o
obj-$(CONFIG_GUP_TEST) += gup_test.o
+obj-$(CONFIG_DMAPOOL_TEST) += dmapool_test.o
obj-$(CONFIG_MEMORY_FAILURE) += memory-failure.o
obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o
obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o
diff --git a/mm/dmapool_test.c b/mm/dmapool_test.c
new file mode 100644
index 0000000000000..2873d91f509b4
--- /dev/null
+++ b/mm/dmapool_test.c
@@ -0,0 +1,138 @@
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/kernel.h>
+#include <linux/ktime.h>
+#include <linux/module.h>
+
+#define NR_TESTS (100)
+
+struct dma_pool_pair {
+ dma_addr_t dma;
+ void *v;
+};
+
+static const int block_sizes[] = {
+ 16,
+ 64,
+ 256,
+ 1024,
+ 4096
+};
+
+static struct dma_pool *pool;
+struct device test_dev;
+u64 dma_mask;
+
+static inline int nr_blocks(int size)
+{
+ return clamp_t(int, (PAGE_SIZE / size) * 512, 1024, 8192);
+}
+
+static int dmapool_test_alloc(struct dma_pool_pair *p, int blocks)
+{
+ int i;
+
+ for (i = 0; i < blocks; i++) {
+ p[i].v = dma_pool_alloc(pool, GFP_KERNEL,
+ &p[i].dma);
+ if (!p[i].v)
+ goto pool_fail;
+ }
+
+ for (i = 0; i < blocks; i++)
+ dma_pool_free(pool, p[i].v, p[i].dma);
+
+ return 0;
+
+pool_fail:
+ for (--i; i >= 0; i--)
+ dma_pool_free(pool, p[i].v, p[i].dma);
+ return -ENOMEM;
+}
+
+static int dmapool_test_block(int block_size)
+{
+ int blocks = nr_blocks(block_size);
+ ktime_t start_time, end_time;
+ struct dma_pool_pair *p;
+ int i, ret;
+
+ p = kcalloc(blocks, sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ pool = dma_pool_create("test pool", &test_dev, block_size,
+ block_size, 0);
+ if (!pool) {
+ ret = -ENOMEM;
+ goto free_pairs;
+ }
+
+ start_time = ktime_get();
+ for (i = 0; i < NR_TESTS; i++) {
+ ret = dmapool_test_alloc(p, blocks);
+ if (ret)
+ goto free_pool;
+ if (need_resched())
+ cond_resched();
+ }
+ end_time = ktime_get();
+
+ printk("dmapool test: size:%-4d blocks:%-6d time:%llu\n", block_size,
+ blocks, ktime_us_delta(end_time, start_time));
+
+free_pool:
+ dma_pool_destroy(pool);
+free_pairs:
+ kfree(p);
+ return ret;
+}
+
+static void dmapool_test_release(struct device *dev)
+{
+}
+
+static int dmapool_checks(void)
+{
+ int i, ret;
+
+ ret = dev_set_name(&test_dev, "dmapool-test");
+ if (ret)
+ return ret;
+
+ ret = device_register(&test_dev);
+ if (ret) {
+ printk("%s: register failed:%d\n", __func__, ret);
+ goto put_device;
+ }
+
+ test_dev.release = dmapool_test_release;
+ test_dev.dma_ops = NULL;
+ test_dev.dma_mask = &dma_mask;
+ ret = dma_set_mask_and_coherent(&test_dev, DMA_BIT_MASK(64));
+ if (ret) {
+ printk("%s: mask failed:%d\n", __func__, ret);
+ goto del_device;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(block_sizes); i++) {
+ ret = dmapool_test_block(block_sizes[i]);
+ if (ret)
+ break;
+ }
+
+del_device:
+ device_del(&test_dev);
+put_device:
+ put_device(&test_dev);
+ return ret;
+}
+
+static void dmapool_exit(void)
+{
+}
+
+module_init(dmapool_checks);
+module_exit(dmapool_exit);
+MODULE_LICENSE("GPL");
--
2.30.2


2022-12-06 03:10:42

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 01/11] dmapool: add alloc/free performance test

Hi Keith,

I love your patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.1-rc8]
[cannot apply to next-20221205]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Keith-Busch/dmapool-enhancements/20221205-232116
patch link: https://lore.kernel.org/r/20221205145937.54367-2-kbusch%40meta.com
patch subject: [PATCH 01/11] dmapool: add alloc/free performance test
config: powerpc-randconfig-c041-20221205
compiler: powerpc-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/68ca0ec415bed31d06a536a0832c305b9d14b1b9
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Keith-Busch/dmapool-enhancements/20221205-232116
git checkout 68ca0ec415bed31d06a536a0832c305b9d14b1b9
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=powerpc SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

mm/dmapool_test.c: In function 'dmapool_checks':
>> mm/dmapool_test.c:111:17: error: 'struct device' has no member named 'dma_ops'
111 | test_dev.dma_ops = NULL;
| ^


vim +111 mm/dmapool_test.c

95
96 static int dmapool_checks(void)
97 {
98 int i, ret;
99
100 ret = dev_set_name(&test_dev, "dmapool-test");
101 if (ret)
102 return ret;
103
104 ret = device_register(&test_dev);
105 if (ret) {
106 printk("%s: register failed:%d\n", __func__, ret);
107 goto put_device;
108 }
109
110 test_dev.release = dmapool_test_release;
> 111 test_dev.dma_ops = NULL;
112 test_dev.dma_mask = &dma_mask;
113 ret = dma_set_mask_and_coherent(&test_dev, DMA_BIT_MASK(64));
114 if (ret) {
115 printk("%s: mask failed:%d\n", __func__, ret);
116 goto del_device;
117 }
118
119 for (i = 0; i < ARRAY_SIZE(block_sizes); i++) {
120 ret = dmapool_test_block(block_sizes[i]);
121 if (ret)
122 break;
123 }
124
125 del_device:
126 device_del(&test_dev);
127 put_device:
128 put_device(&test_dev);
129 return ret;
130 }
131

--
0-DAY CI Kernel Test Service
https://01.org/lkp


Attachments:
(No filename) (2.83 kB)
config (137.57 kB)
Download all attachments