* [RFC In-kernel benchmarks 0/3] Introduce in kernel benchmarks
@ 2009-10-13 20:02 Christoph Lameter
2009-10-13 20:02 ` [RFC In-kernel benchmarks 1/3] Add slab performance tests Christoph Lameter
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Christoph Lameter @ 2009-10-13 20:02 UTC (permalink / raw)
To: Mel Gorman
Cc: linux-kernel, Pekka Enberg, Tejun Heo, Mathieu Desnoyers, akpm,
Ingo Molnar, Eric Dumazet
In kernel benchmarks are benchmarks that directly run in kernel space.
The test modules are regular kernel modules that can be loaded with
modprobe slab_test
or so.
The initialization function of the module will then run the test
and fail so that the module is not loaded. The output of the test
results will be written to the system log.
This is a rough draft. I have used these in the past to benchmark
page allocator, slab allocator and vmstat performance.
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC In-kernel benchmarks 1/3] Add slab performance tests
2009-10-13 20:02 [RFC In-kernel benchmarks 0/3] Introduce in kernel benchmarks Christoph Lameter
@ 2009-10-13 20:02 ` Christoph Lameter
2009-10-13 20:02 ` [RFC In-kernel benchmarks 2/3] Vm statistics performance test Christoph Lameter
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Christoph Lameter @ 2009-10-13 20:02 UTC (permalink / raw)
To: Mel Gorman
Cc: linux-kernel, Pekka Enberg, Tejun Heo, Mathieu Desnoyers, akpm,
Ingo Molnar, Eric Dumazet
[-- Attachment #1: 0001-Add-slab-performance-tests.patch --]
[-- Type: text/plain, Size: 11422 bytes --]
This is a test of slab allocator performance tests.
Run
modprobe slab_test
to execute. Output will be written to the syslog.
Signed-off-by: Christoph Lameter <cl@linux-foundation.org>
---
Makefile | 2
include/Kbuild | 1
lib/Kconfig.debug | 1
tests/Kconfig | 19 ++
tests/Makefile | 2
tests/slab_test.c | 373 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 397 insertions(+), 1 deletion(-)
create mode 100644 tests/Makefile
create mode 100644 tests/slab_test.c
Index: linux-2.6/Makefile
===================================================================
--- linux-2.6.orig/Makefile 2009-10-12 15:32:26.000000000 -0500
+++ linux-2.6/Makefile 2009-10-12 15:32:30.000000000 -0500
@@ -686,7 +686,7 @@ export mod_strip_cmd
ifeq ($(KBUILD_EXTMOD),)
-core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
+core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ tests/
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
Index: linux-2.6/include/Kbuild
===================================================================
--- linux-2.6.orig/include/Kbuild 2009-10-12 15:32:26.000000000 -0500
+++ linux-2.6/include/Kbuild 2009-10-12 15:32:30.000000000 -0500
@@ -10,3 +10,4 @@ header-y += video/
header-y += drm/
header-y += xen/
header-y += scsi/
+header-y += tests/
Index: linux-2.6/tests/Makefile
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/tests/Makefile 2009-10-12 15:32:30.000000000 -0500
@@ -0,0 +1,2 @@
+obj-$(CONFIG_BENCHMARK_SLAB) += slab_test.o
+
Index: linux-2.6/tests/slab_test.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/tests/slab_test.c 2009-10-12 15:32:47.000000000 -0500
@@ -0,0 +1,373 @@
+/* test-slab.c
+ *
+ * Test module for synthetic in kernel slab allocator testing.
+ *
+ * The test is triggered by loading the module (which will fail).
+ *
+ * (C) 2009 Linux Foundation <cl@linux-foundation.org>
+ */
+
+
+#include <linux/jiffies.h>
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/timex.h>
+#include <asm/system.h>
+
+#define TEST_COUNT 10000
+
+#ifdef CONFIG_SMP
+#include <linux/completion.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/kthread.h>
+
+static struct test_struct {
+ struct task_struct *task;
+ int cpu;
+ int size;
+ int count;
+ void **v;
+ void (*test_p1)(struct test_struct *);
+ void (*test_p2)(struct test_struct *);
+ unsigned long start1;
+ unsigned long stop1;
+ unsigned long start2;
+ unsigned long stop2;
+} test[NR_CPUS];
+
+/*
+ * Allocate TEST_COUNT objects on cpus > 0 and then all the
+ * objects later on cpu 0
+ */
+static void remote_free_test_p1(struct test_struct *t)
+{
+ int i;
+
+ /* Perform no allocations on cpu 0 */
+ for (i = 0; i < t->count; i++) {
+ u8 *p;
+
+ if (smp_processor_id()) {
+ p = kmalloc(t->size, GFP_KERNEL);
+ /* Use object */
+ *p = 17;
+ } else
+ p = NULL;
+ t->v[i] = p;
+ }
+}
+
+static void remote_free_test_p2(struct test_struct *t)
+{
+ int i;
+ int cpu;
+
+ /* All frees are completed on cpu zero */
+ if (smp_processor_id())
+ return;
+
+ for_each_online_cpu(cpu)
+ for (i = 0; i < t->count; i++) {
+ u8 *p = test[cpu].v[i];
+
+ if (!p)
+ continue;
+
+ *p = 16;
+ kfree(p);
+ }
+}
+
+/*
+ * Allocate TEST_COUNT objects on cpu 0 and free them immediately on the
+ * other processors.
+ */
+static void alloc_n_free_test_p1(struct test_struct *t)
+{
+ int i;
+ int cpu;
+ char *p;
+
+ if (smp_processor_id()) {
+ /* Consumer */
+ for (i = 0; i < t->count / num_online_cpus(); i++) {
+ do {
+ p = t->v[i];
+ if (!p)
+ cpu_relax();
+ else
+ *p = 17;
+ } while (!p);
+ kfree(p);
+ t->v[i] = NULL;
+ }
+ return;
+ }
+ /* Producer */
+ for (i = 0; i < t->count; i++) {
+ for_each_online_cpu(cpu) {
+ if (cpu) {
+ p = kmalloc(t->size, GFP_KERNEL);
+ /* Use object */
+ *p = 17;
+ test[cpu].v[i] = p;
+ }
+ }
+ }
+}
+
+/*
+ * Allocate TEST_COUNT objects and later free them all again
+ */
+static void kmalloc_alloc_then_free_test_p1(struct test_struct *t)
+{
+ int i;
+
+ for (i = 0; i < t->count; i++) {
+ u8 *p = kmalloc(t->size, GFP_KERNEL);
+
+ *p = 14;
+ t->v[i] = p;
+ }
+}
+
+static void kmalloc_alloc_then_free_test_p2(struct test_struct *t)
+{
+ int i;
+
+ for (i = 0; i < t->count; i++) {
+ u8 *p = t->v[i];
+
+ *p = 13;
+ kfree(p);
+ }
+}
+
+/*
+ * Allocate TEST_COUNT objects. Free them immediately.
+ */
+static void kmalloc_alloc_free_test_p1(struct test_struct *t)
+{
+ int i;
+
+ for (i = 0; i < TEST_COUNT; i++) {
+ u8 *p = kmalloc(t->size, GFP_KERNEL);
+
+ *p = 12;
+ kfree(p);
+ }
+}
+
+static atomic_t tests_running;
+static atomic_t phase1_complete;
+static DECLARE_COMPLETION(completion1);
+static DECLARE_COMPLETION(completion2);
+static int started;
+
+static int test_func(void *private)
+{
+ struct test_struct *t = private;
+ cpumask_t newmask = CPU_MASK_NONE;
+
+ cpu_set(t->cpu, newmask);
+ set_cpus_allowed(current, newmask);
+ t->v = kzalloc(t->count * sizeof(void *), GFP_KERNEL);
+
+ atomic_inc(&tests_running);
+ wait_for_completion(&completion1);
+ t->start1 = get_cycles();
+ t->test_p1(t);
+ t->stop1 = get_cycles();
+ atomic_inc(&phase1_complete);
+ wait_for_completion(&completion2);
+ t->start2 = get_cycles();
+ if (t->test_p2)
+ t->test_p2(t);
+ t->stop2 = get_cycles();
+ kfree(t->v);
+ atomic_dec(&tests_running);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule();
+ return 0;
+}
+
+static void do_concurrent_test(void (*p1)(struct test_struct *),
+ void (*p2)(struct test_struct *),
+ int size, const char *name)
+{
+ int cpu;
+ unsigned long time1 = 0;
+ unsigned long time2 = 0;
+ unsigned long sum1 = 0;
+ unsigned long sum2 = 0;
+
+ atomic_set(&tests_running, 0);
+ atomic_set(&phase1_complete, 0);
+ started = 0;
+ init_completion(&completion1);
+ init_completion(&completion2);
+
+ for_each_online_cpu(cpu) {
+ struct test_struct *t = &test[cpu];
+
+ t->cpu = cpu;
+ t->count = TEST_COUNT;
+ t->test_p1 = p1;
+ t->test_p2 = p2;
+ t->size = size;
+ t->task = kthread_run(test_func, t, "test%d", cpu);
+ if (IS_ERR(t->task)) {
+ printk("Failed to start test func\n");
+ return;
+ }
+ }
+
+ /* Wait till all processes are running */
+ while (atomic_read(&tests_running) < num_online_cpus()) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(10);
+ }
+ complete_all(&completion1);
+
+ /* Wait till all processes have completed phase 1 */
+ while (atomic_read(&phase1_complete) < num_online_cpus()) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(10);
+ }
+ complete_all(&completion2);
+
+ while (atomic_read(&tests_running)) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(10);
+ }
+
+ for_each_online_cpu(cpu)
+ kthread_stop(test[cpu].task);
+
+ printk(KERN_ALERT "%s(%d):", name, size);
+ for_each_online_cpu(cpu) {
+ struct test_struct *t = &test[cpu];
+
+ time1 = t->stop1 - t->start1;
+ time2 = t->stop2 - t->start2;
+ sum1 += time1;
+ sum2 += time2;
+ printk(" %d=%lu", cpu, time1 / TEST_COUNT);
+ if (p2)
+ printk("/%lu", time2 / TEST_COUNT);
+ }
+ printk(" Average=%lu", sum1 / num_online_cpus() / TEST_COUNT);
+ if (p2)
+ printk("/%lu", sum2 / num_online_cpus() / TEST_COUNT);
+ printk("\n");
+ schedule_timeout(200);
+}
+#endif
+
+static int slab_test_init(void)
+{
+ void **v = kmalloc(TEST_COUNT * sizeof(void *), GFP_KERNEL);
+ unsigned int i;
+ cycles_t time1, time2, time;
+ int rem;
+ int size;
+
+ printk(KERN_ALERT "test init\n");
+
+ printk(KERN_ALERT "Single thread testing\n");
+ printk(KERN_ALERT "=====================\n");
+ printk(KERN_ALERT "1. Kmalloc: Repeatedly allocate then free test\n");
+ for (size = 8; size <= PAGE_SIZE << 2; size <<= 1) {
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++) {
+ u8 *p = kmalloc(size, GFP_KERNEL);
+
+ *p = 22;
+ v[i] = p;
+ }
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ printk(KERN_ALERT "%i times kmalloc(%d) ", i, size);
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ printk("-> %llu cycles ", time);
+
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++) {
+ u8 *p = v[i];
+
+ *p = 23;
+ kfree(p);
+ }
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ printk("kfree ");
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ printk("-> %llu cycles\n", time);
+ }
+
+ printk(KERN_ALERT "2. Kmalloc: alloc/free test\n");
+ for (size = 8; size <= PAGE_SIZE << 2; size <<= 1) {
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++) {
+ u8 *p = kmalloc(size, GFP_KERNEL);
+
+ kfree(p);
+ }
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ printk(KERN_ALERT "%i times kmalloc(%d)/kfree ", i, size);
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ printk("-> %llu cycles\n", time);
+ }
+ kfree(v);
+#ifdef CONFIG_SMP
+ printk(KERN_INFO "Concurrent allocs\n");
+ printk(KERN_INFO "=================\n");
+ for (i = 3; i <= PAGE_SHIFT; i++) {
+ do_concurrent_test(kmalloc_alloc_then_free_test_p1,
+ kmalloc_alloc_then_free_test_p2,
+ 1 << i, "Kmalloc N*alloc N*free");
+ }
+ for (i = 3; i <= PAGE_SHIFT; i++) {
+ do_concurrent_test(kmalloc_alloc_free_test_p1, NULL,
+ 1 << i, "Kmalloc N*(alloc free)");
+ }
+
+ printk(KERN_INFO "Remote free test\n");
+ printk(KERN_INFO "================\n");
+ for (i = 3; i <= PAGE_SHIFT; i++) {
+ do_concurrent_test(remote_free_test_p1,
+ remote_free_test_p2,
+ 1 << i, "N*remote free");
+ }
+
+ printk(KERN_INFO "1 alloc N free test\n");
+ printk(KERN_INFO "===================\n");
+ for (i = 3; i <= PAGE_SHIFT; i++) {
+ do_concurrent_test(alloc_n_free_test_p1,
+ NULL,
+ 1 << i, "1 alloc N free");
+ }
+
+#endif
+ return -EAGAIN; /* Fail will directly unload the module */
+}
+
+static void slab_test_exit(void)
+{
+ printk(KERN_ALERT "test exit\n");
+}
+
+module_init(slab_test_init)
+module_exit(slab_test_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christoph Lameter and Mathieu Desnoyers");
+MODULE_DESCRIPTION("SLAB test");
+
Index: linux-2.6/lib/Kconfig.debug
===================================================================
--- linux-2.6.orig/lib/Kconfig.debug 2009-10-12 15:32:26.000000000 -0500
+++ linux-2.6/lib/Kconfig.debug 2009-10-12 15:32:30.000000000 -0500
@@ -920,6 +920,7 @@ config SYSCTL_SYSCALL_CHECK
source mm/Kconfig.debug
source kernel/trace/Kconfig
+source tests/Kconfig
config PROVIDE_OHCI1394_DMA_INIT
bool "Remote debugging over FireWire early on boot"
Index: linux-2.6/tests/Kconfig
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/tests/Kconfig 2009-10-12 15:32:30.000000000 -0500
@@ -0,0 +1,19 @@
+menuconfig BENCHMARKS
+ bool "In kernel benchmarks"
+ def_bool n
+ help
+ Includes in kernel benchmark modules in the build. These modules can
+ be loaded later to trigger benchmarking kernel subsystems.
+ Output will be generated in the system log.
+
+if BENCHMARKS
+
+config BENCHMARK_SLAB
+ tristate "Slab allocator Benchmark"
+ depends on m
+ default m
+ help
+ A benchmark that measures slab allocator performance.
+
+endif # BENCHMARKS
+
--
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC In-kernel benchmarks 2/3] Vm statistics performance test
2009-10-13 20:02 [RFC In-kernel benchmarks 0/3] Introduce in kernel benchmarks Christoph Lameter
2009-10-13 20:02 ` [RFC In-kernel benchmarks 1/3] Add slab performance tests Christoph Lameter
@ 2009-10-13 20:02 ` Christoph Lameter
2009-10-13 20:02 ` [RFC In-kernel benchmarks 3/3] Page allocator test Christoph Lameter
2009-10-15 8:09 ` [RFC In-kernel benchmarks 0/3] Introduce in kernel benchmarks David Rientjes
3 siblings, 0 replies; 5+ messages in thread
From: Christoph Lameter @ 2009-10-13 20:02 UTC (permalink / raw)
To: Mel Gorman
Cc: linux-kernel, Pekka Enberg, Tejun Heo, Mathieu Desnoyers, akpm,
Ingo Molnar, Eric Dumazet
[-- Attachment #1: 0002-Vm-statistics-performance-test.patch --]
[-- Type: text/plain, Size: 3891 bytes --]
Tests the performance of some key vm statistics functions.
Signed-off-by: Christoph Lameter <cl@linux-foundation.org>
---
tests/Kconfig | 7 +++
tests/Makefile | 1
tests/vmstat_test.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 105 insertions(+)
create mode 100644 tests/vmstat_test.c
Index: linux-2.6/tests/Makefile
===================================================================
--- linux-2.6.orig/tests/Makefile 2009-10-12 15:13:04.000000000 -0500
+++ linux-2.6/tests/Makefile 2009-10-12 15:15:08.000000000 -0500
@@ -1,2 +1,3 @@
obj-$(CONFIG_BENCHMARK_SLAB) += slab_test.o
+obj-#(CONFIG_BENCHMARK_VMSTAT) += vmstat_test.o
Index: linux-2.6/tests/vmstat_test.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/tests/vmstat_test.c 2009-10-12 15:15:08.000000000 -0500
@@ -0,0 +1,97 @@
+/* test-vmstat.c
+ *
+ * Test module for in kernel synthetic vm statistics performance.
+ *
+ * execute
+ *
+ * modprobe test-vmstat
+ *
+ * to run this test
+ *
+ * (C) 2009 Linux Foundation, Christoph Lameter <cl@linux-foundation.org>
+ */
+
+#include <linux/jiffies.h>
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/timex.h>
+#include <asm/system.h>
+
+#define TEST_COUNT 10000
+
+static int vmstat_test_init(void)
+{
+ unsigned int i;
+ cycles_t time1, time2, time;
+ int rem;
+ struct page *page = alloc_page(GFP_KERNEL);
+
+ printk(KERN_ALERT "VMstat testing\n");
+ printk(KERN_ALERT "=====================\n");
+ printk(KERN_ALERT "1. inc_zone_page_state() then dec_zone_page_state()\n");
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++)
+ inc_zone_page_state(page, NR_BOUNCE);
+
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ printk(KERN_ALERT "%i times inc_zone_page_state() ", i);
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ printk("-> %llu cycles ", time);
+
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++)
+ __dec_zone_page_state(page, NR_BOUNCE);
+
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ printk("__dec_z_p_s() ");
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ printk("-> %llu cycles\n", time);
+
+ printk(KERN_ALERT "2. inc_zone_page_state()/dec_zone_page_state()\n");
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++) {
+ inc_zone_page_state(page, NR_BOUNCE);
+ dec_zone_page_state(page, NR_BOUNCE);
+ }
+
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ printk(KERN_ALERT "%i times inc/dec ", i);
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ printk("-> %llu cycles\n", time);
+
+ printk(KERN_ALERT "3. count_vm_event()\n");
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++)
+ count_vm_event(SLABS_SCANNED);
+
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ count_vm_events(SLABS_SCANNED, -TEST_COUNT);
+ printk(KERN_ALERT "%i count_vm_events ", i);
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ printk("-> %llu cycles\n", time);
+ __free_page(page);
+ return -EAGAIN; /* Fail will directly unload the module */
+}
+
+static void vmstat_test_exit(void)
+{
+ printk(KERN_ALERT "test exit\n");
+}
+
+module_init(vmstat_test_init)
+module_exit(vmstat_test_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christoph Lameter");
+MODULE_DESCRIPTION("VM statistics test");
+
Index: linux-2.6/tests/Kconfig
===================================================================
--- linux-2.6.orig/tests/Kconfig 2009-10-12 15:14:54.000000000 -0500
+++ linux-2.6/tests/Kconfig 2009-10-12 15:15:55.000000000 -0500
@@ -15,5 +15,12 @@ config BENCHMARK_SLAB
help
A benchmark that measures slab allocator performance.
+config BENCHMARK_VMSTAT
+ tristate "VM statistics Benchmark"
+ default m
+ depends on m
+ help
+ A benchmark measuring the performance of vm statistics.
+
endif # BENCHMARKS
--
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC In-kernel benchmarks 3/3] Page allocator test
2009-10-13 20:02 [RFC In-kernel benchmarks 0/3] Introduce in kernel benchmarks Christoph Lameter
2009-10-13 20:02 ` [RFC In-kernel benchmarks 1/3] Add slab performance tests Christoph Lameter
2009-10-13 20:02 ` [RFC In-kernel benchmarks 2/3] Vm statistics performance test Christoph Lameter
@ 2009-10-13 20:02 ` Christoph Lameter
2009-10-15 8:09 ` [RFC In-kernel benchmarks 0/3] Introduce in kernel benchmarks David Rientjes
3 siblings, 0 replies; 5+ messages in thread
From: Christoph Lameter @ 2009-10-13 20:02 UTC (permalink / raw)
To: Mel Gorman
Cc: linux-kernel, Pekka Enberg, Tejun Heo, Mathieu Desnoyers, akpm,
Ingo Molnar, Eric Dumazet
[-- Attachment #1: 0003-Page-allocator-test.patch --]
[-- Type: text/plain, Size: 9560 bytes --]
Implement a test of the page allocator speed in the same way as for the
slab allocators.
Signed-off-by: Christoph Lameter <cl@linux-foundation.org>
---
tests/Kconfig | 7 +
tests/Makefile | 3
tests/pagealloc_test.c | 334 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 343 insertions(+), 1 deletion(-)
create mode 100644 tests/page_test.c
Index: linux-2.6/tests/Makefile
===================================================================
--- linux-2.6.orig/tests/Makefile 2009-10-12 15:17:45.000000000 -0500
+++ linux-2.6/tests/Makefile 2009-10-12 15:17:46.000000000 -0500
@@ -1,3 +1,4 @@
obj-$(CONFIG_BENCHMARK_SLAB) += slab_test.o
-obj-#(CONFIG_BENCHMARK_VMSTAT) += vmstat_test.o
+obj-$(CONFIG_BENCHMARK_VMSTAT) += vmstat_test.o
+obj-$(CONFIG_BENCHMARK_PAGEALLOC) += pagealloc_test.o
Index: linux-2.6/tests/pagealloc_test.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/tests/pagealloc_test.c 2009-10-12 15:17:46.000000000 -0500
@@ -0,0 +1,334 @@
+/* pagealloc_test.c
+ *
+ * Test module for in kernel synthetic page allocator testing.
+ *
+ * Compiled as a module. The module needs to be loaded to run.
+ *
+ * (C) 2009 Linux Foundation, Christoph Lameter <cl@linux-foundation.org>
+ */
+
+
+#include <linux/jiffies.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <asm/timex.h>
+#include <asm/system.h>
+
+#define TEST_COUNT 1000
+
+#define CONCURRENT_MAX_ORDER 6
+
+#ifdef CONFIG_SMP
+#include <linux/completion.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/kthread.h>
+
+static struct test_struct {
+ struct task_struct *task;
+ int cpu;
+ int order;
+ int count;
+ struct page **v;
+ void (*test_p1)(struct test_struct *);
+ void (*test_p2)(struct test_struct *);
+ unsigned long start1;
+ unsigned long stop1;
+ unsigned long start2;
+ unsigned long stop2;
+} test[NR_CPUS];
+
+/*
+ * Allocate TEST_COUNT objects on cpus > 0 and then all the
+ * objects later on cpu 0
+ */
+static void remote_free_test_p1(struct test_struct *t)
+{
+ int i;
+
+ /* Perform no allocations on cpu 0 */
+ for (i = 0; i < t->count; i++) {
+ struct page *p;
+
+ if (smp_processor_id()) {
+ p = alloc_pages(GFP_KERNEL | __GFP_COMP, t->order);
+ /* Use object */
+ memset(page_address(p), 17, 4);
+ } else
+ p = NULL;
+ t->v[i] = p;
+ }
+}
+
+static void remote_free_test_p2(struct test_struct *t)
+{
+ int i;
+ int cpu;
+
+ /* All frees are completed on cpu zero */
+ if (smp_processor_id())
+ return;
+
+ for_each_online_cpu(cpu)
+ for (i = 0; i < t->count; i++) {
+ struct page *p = test[cpu].v[i];
+
+ if (!p)
+ continue;
+
+ __free_pages(p, t->order);
+ }
+}
+
+/*
+ * Allocate TEST_COUNT objects and later free them all again
+ */
+static void alloc_then_free_test_p1(struct test_struct *t)
+{
+ int i;
+
+ for (i = 0; i < t->count; i++) {
+ struct page *p = alloc_pages(GFP_KERNEL | __GFP_COMP, t->order);
+
+ memset(page_address(p), 14, 4);
+ t->v[i] = p;
+ }
+}
+
+static void alloc_then_free_test_p2(struct test_struct *t)
+{
+ int i;
+
+ for (i = 0; i < t->count; i++) {
+ struct page *p = t->v[i];
+
+ __free_pages(p, t->order);
+ }
+}
+
+/*
+ * Allocate TEST_COUNT objects. Free them immediately.
+ */
+static void alloc_free_test_p1(struct test_struct *t)
+{
+ int i;
+
+ for (i = 0; i < TEST_COUNT; i++) {
+ struct page *p = alloc_pages(GFP_KERNEL | __GFP_COMP, t->order);
+
+ memset(page_address(p), 12, 4);
+ __free_pages(p, t->order);
+ }
+}
+
+static atomic_t tests_running;
+static atomic_t phase1_complete;
+static DECLARE_COMPLETION(completion1);
+static DECLARE_COMPLETION(completion2);
+static int started;
+
+static int test_func(void *private)
+{
+ struct test_struct *t = private;
+ cpumask_t newmask = CPU_MASK_NONE;
+
+ cpu_set(t->cpu, newmask);
+ set_cpus_allowed(current, newmask);
+ t->v = kmalloc(t->count * sizeof(struct page *), GFP_KERNEL);
+
+ atomic_inc(&tests_running);
+ wait_for_completion(&completion1);
+ t->start1 = get_cycles();
+ t->test_p1(t);
+ t->stop1 = get_cycles();
+ atomic_inc(&phase1_complete);
+ wait_for_completion(&completion2);
+ t->start2 = get_cycles();
+ if (t->test_p2)
+ t->test_p2(t);
+ t->stop2 = get_cycles();
+ kfree(t->v);
+ atomic_dec(&tests_running);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule();
+ return 0;
+}
+
+static void do_concurrent_test(void (*p1)(struct test_struct *),
+ void (*p2)(struct test_struct *),
+ int order, const char *name)
+{
+ int cpu;
+ unsigned long time1 = 0;
+ unsigned long time2 = 0;
+ unsigned long sum1 = 0;
+ unsigned long sum2 = 0;
+
+ atomic_set(&tests_running, 0);
+ atomic_set(&phase1_complete, 0);
+ started = 0;
+ init_completion(&completion1);
+ init_completion(&completion2);
+
+ for_each_online_cpu(cpu) {
+ struct test_struct *t = &test[cpu];
+
+ t->cpu = cpu;
+ t->count = TEST_COUNT;
+ t->test_p1 = p1;
+ t->test_p2 = p2;
+ t->order = order;
+ t->task = kthread_run(test_func, t, "test%d", cpu);
+ if (IS_ERR(t->task)) {
+ printk("Failed to start test func\n");
+ return;
+ }
+ }
+
+ /* Wait till all processes are running */
+ while (atomic_read(&tests_running) < num_online_cpus()) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(10);
+ }
+ complete_all(&completion1);
+
+ /* Wait till all processes have completed phase 1 */
+ while (atomic_read(&phase1_complete) < num_online_cpus()) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(10);
+ }
+ complete_all(&completion2);
+
+ while (atomic_read(&tests_running)) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(10);
+ }
+
+ for_each_online_cpu(cpu)
+ kthread_stop(test[cpu].task);
+
+ printk(KERN_ALERT "%s(%d):", name, order);
+ for_each_online_cpu(cpu) {
+ struct test_struct *t = &test[cpu];
+
+ time1 = t->stop1 - t->start1;
+ time2 = t->stop2 - t->start2;
+ sum1 += time1;
+ sum2 += time2;
+ printk(" %d=%lu", cpu, time1 / TEST_COUNT);
+ if (p2)
+ printk("/%lu", time2 / TEST_COUNT);
+ }
+ printk(" Average=%lu", sum1 / num_online_cpus() / TEST_COUNT);
+ if (p2)
+ printk("/%lu", sum2 / num_online_cpus() / TEST_COUNT);
+ printk("\n");
+ schedule_timeout(200);
+}
+#endif
+
+static int pagealloc_test_init(void)
+{
+ void **v = kmalloc(TEST_COUNT * sizeof(void *), GFP_KERNEL);
+ unsigned int i;
+ cycles_t time1, time2, time;
+ int rem;
+ int order;
+
+ printk(KERN_ALERT "test init\n");
+
+ printk(KERN_ALERT "Single thread testing\n");
+ printk(KERN_ALERT "=====================\n");
+ printk(KERN_ALERT "1. Repeatedly allocate then free test\n");
+ for (order = 0; order < MAX_ORDER; order++) {
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++) {
+ struct page *p = alloc_pages(GFP_KERNEL | __GFP_COMP,
+ order);
+
+ if (!p) {
+ printk("Cannot allocate order=%d\n", order);
+ break;
+ }
+
+ /* Touch page */
+ memset(page_address(p), 22, 4);
+ v[i] = p;
+ }
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ printk(KERN_ALERT "%i times alloc_page(,%d) ", i, order);
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ printk("-> %llu cycles ", time);
+
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++) {
+ struct page *p = v[i];
+
+ __free_pages(p, order);
+ }
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ printk("__free_pages(,%d)", order);
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ printk("-> %llu cycles\n", time);
+ }
+
+ printk(KERN_ALERT "2. alloc/free test\n");
+ for (order = 0; order < MAX_ORDER; order++) {
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++) {
+ struct page *p = alloc_pages(GFP_KERNEL| __GFP_COMP, order);
+
+ __free_pages(p, order);
+ }
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ printk(KERN_ALERT "%i times alloc( ,%d)/free ", i, order);
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ printk("-> %llu cycles\n", time);
+ }
+ kfree(v);
+#ifdef CONFIG_SMP
+ printk(KERN_INFO "Concurrent allocs\n");
+ printk(KERN_INFO "=================\n");
+ for (order = 0; order < CONCURRENT_MAX_ORDER; order++) {
+ do_concurrent_test(alloc_then_free_test_p1,
+ alloc_then_free_test_p2,
+ order, "Page alloc N*alloc N*free");
+ }
+ printk("----Fastpath---\n");
+ for (order = 0; order < CONCURRENT_MAX_ORDER; order++) {
+ do_concurrent_test(alloc_free_test_p1, NULL,
+ order, "Page N*(alloc free)");
+ }
+
+ printk(KERN_INFO "Remote free test\n");
+ printk(KERN_INFO "================\n");
+ for (order = 0; order < CONCURRENT_MAX_ORDER; order++) {
+ do_concurrent_test(remote_free_test_p1,
+ remote_free_test_p2,
+ order, "N*remote free");
+ }
+
+#endif
+
+ return -EAGAIN; /* Fail will directly unload the module */
+}
+
+static void pagealloc_test_exit(void)
+{
+ printk(KERN_ALERT "test exit\n");
+}
+
+module_init(pagealloc_test_init)
+module_exit(pagealloc_test_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christoph Lameter");
+MODULE_DESCRIPTION("page allocator performance test");
+
Index: linux-2.6/tests/Kconfig
===================================================================
--- linux-2.6.orig/tests/Kconfig 2009-10-12 15:17:45.000000000 -0500
+++ linux-2.6/tests/Kconfig 2009-10-12 15:17:46.000000000 -0500
@@ -22,5 +22,12 @@ config BENCHMARK_VMSTAT
help
A benchmark measuring the performance of vm statistics.
+config BENCHMARK_PAGEALLOC
+ tristate "Page Allocator Benchmark"
+ default m
+ depends on m
+ help
+ A benchmark measuring the performance of the page allocator.
+
endif # BENCHMARKS
--
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC In-kernel benchmarks 0/3] Introduce in kernel benchmarks
2009-10-13 20:02 [RFC In-kernel benchmarks 0/3] Introduce in kernel benchmarks Christoph Lameter
` (2 preceding siblings ...)
2009-10-13 20:02 ` [RFC In-kernel benchmarks 3/3] Page allocator test Christoph Lameter
@ 2009-10-15 8:09 ` David Rientjes
3 siblings, 0 replies; 5+ messages in thread
From: David Rientjes @ 2009-10-15 8:09 UTC (permalink / raw)
To: Christoph Lameter
Cc: Mel Gorman, linux-kernel, Pekka Enberg, Tejun Heo,
Mathieu Desnoyers, akpm, Ingo Molnar, Eric Dumazet
On Tue, 13 Oct 2009, Christoph Lameter wrote:
> In kernel benchmarks are benchmarks that directly run in kernel space.
>
> The test modules are regular kernel modules that can be loaded with
>
> modprobe slab_test
>
> or so.
>
> The initialization function of the module will then run the test
> and fail so that the module is not loaded. The output of the test
> results will be written to the system log.
>
> This is a rough draft. I have used these in the past to benchmark
> page allocator, slab allocator and vmstat performance.
>
I like the addition of these benchmarks to the kernel source, I've been
adding Mathieu's slab benchmark to my tree for a while. It looks like
they all need some degree of cleanup, though: they have checkpatch
warnings, they frequently do not handle memory allocation failures, and it
would be nice to have a consistent loglevel for all the results.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2009-10-15 8:10 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-13 20:02 [RFC In-kernel benchmarks 0/3] Introduce in kernel benchmarks Christoph Lameter
2009-10-13 20:02 ` [RFC In-kernel benchmarks 1/3] Add slab performance tests Christoph Lameter
2009-10-13 20:02 ` [RFC In-kernel benchmarks 2/3] Vm statistics performance test Christoph Lameter
2009-10-13 20:02 ` [RFC In-kernel benchmarks 3/3] Page allocator test Christoph Lameter
2009-10-15 8:09 ` [RFC In-kernel benchmarks 0/3] Introduce in kernel benchmarks David Rientjes
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®