summaryrefslogtreecommitdiff
path: root/schulung_tools/pgflt
diff options
context:
space:
mode:
authorJohn Ogness <john.ogness@linutronix.de>2018-02-20 15:03:14 +0100
committerJohn Ogness <john.ogness@linutronix.de>2018-02-20 15:03:14 +0100
commit021b32acd3cec8e255dd47681939797ec64b8206 (patch)
treef6aa8e57b5bbc8045ae9ec87f4cebac764149ebf /schulung_tools/pgflt
parentdba99eeb7689d594f9d704d8b7de15432279aa82 (diff)
tools: rename 'rtex' tool to 'pgflt'
The rtex tool only demonstrates prefaultingn to avoid runtime page faults. It makes more sense to call it pgflt. Signed-off-by: John Ogness <john.ogness@linutronix.de>
Diffstat (limited to 'schulung_tools/pgflt')
-rw-r--r--schulung_tools/pgflt/Makefile7
-rw-r--r--schulung_tools/pgflt/README.txt46
-rw-r--r--schulung_tools/pgflt/func.c69
-rw-r--r--schulung_tools/pgflt/main.c60
-rw-r--r--schulung_tools/pgflt/rt.c72
5 files changed, 254 insertions, 0 deletions
diff --git a/schulung_tools/pgflt/Makefile b/schulung_tools/pgflt/Makefile
new file mode 100644
index 0000000..fb70f96
--- /dev/null
+++ b/schulung_tools/pgflt/Makefile
@@ -0,0 +1,7 @@
+pgflt: main.c func.c rt.c
+ gcc -O0 -o$@ $+ -lrt
+
+clean:
+ rm -f pgflt
+
+.PHONY: clean
diff --git a/schulung_tools/pgflt/README.txt b/schulung_tools/pgflt/README.txt
new file mode 100644
index 0000000..6bc49ba
--- /dev/null
+++ b/schulung_tools/pgflt/README.txt
@@ -0,0 +1,46 @@
+The pgflt program demonstrates the importance of using several tricks to
+avoid page faults and memory allocation during critical runtime. It displays
+the amount of time taken and generated page faults when performing various
+tasks. This clearly shows the expense due to page faults.
+
+Running the program without any (or invalid) arguments shows the usage
+help. The program argument specifies which rt tweak should be performed
+and if the runtime tests should be performed.
+
+The tests can be performed on any Linux system (embedded, desktop, server,
+with or without PREEMPT_RT). The results will be the same.
+
+The following is a summary of the most important results:
+
+running the test without any rt tweaks
+ - main setup very fast
+ - first big malloc+access very expensive
+ - second big malloc+access very expensive
+ - first big stack very expensive
+$ sudo ./pgflt 0x10
+options: 0x10
+ 5715 ns 0 faults : main setup
+ 17466150 ns 2561 faults : testfunc_malloc (0)
+ 14963662 ns 2560 faults : testfunc_malloc (1)
+ 2517772 ns 0 faults : testfunc_malloc (2)
+ 2577208 ns 0 faults : testfunc_malloc (3)
+ 6113558 ns 1847 faults : testfunc_deepstack (0)
+ 390386 ns 0 faults : testfunc_deepstack (1)
+ 321146 ns 0 faults : testfunc_deepstack (2)
+ 317585 ns 0 faults : testfunc_deepstack (3)
+
+running the test with all rt tweaks
+ - main setup very slow (does it really matter?)
+ - no expensive malloc+access calls
+ - no expensive big stacks
+$ sudo ./pgflt 0x1f
+options: 0x1f
+ 31276098 ns 7083 faults : main setup
+ 2657466 ns 0 faults : testfunc_malloc (0)
+ 2519973 ns 0 faults : testfunc_malloc (1)
+ 2543506 ns 0 faults : testfunc_malloc (2)
+ 2750682 ns 0 faults : testfunc_malloc (3)
+ 526604 ns 0 faults : testfunc_deepstack (0)
+ 324543 ns 0 faults : testfunc_deepstack (1)
+ 318580 ns 0 faults : testfunc_deepstack (2)
+ 317265 ns 0 faults : testfunc_deepstack (3)
diff --git a/schulung_tools/pgflt/func.c b/schulung_tools/pgflt/func.c
new file mode 100644
index 0000000..4b88166
--- /dev/null
+++ b/schulung_tools/pgflt/func.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+void timestamp(const char *msg, int val)
+{
+ static struct timespec tsl;
+ static long minfltl;
+
+ struct timespec ts;
+ unsigned long diff;
+ struct rusage r;
+ long rdiff;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ getrusage(RUSAGE_SELF, &r);
+
+ if (tsl.tv_sec != 0) {
+ diff = (ts.tv_sec - tsl.tv_sec) * 1000000000;
+ diff += ts.tv_nsec - tsl.tv_nsec;
+
+ rdiff = r.ru_minflt - minfltl;
+
+ printf("% 10d ns % 5ld faults : %s", diff, rdiff, msg);
+ if (val >= 0)
+ printf(" (%d)", val);
+ printf("\n");
+ }
+
+ tsl = ts;
+ minfltl = r.ru_minflt;
+}
+
+/* 10 MiB */
+#define SIZE (10 * 1024 * 1024)
+
+void testfunc_malloc(void)
+{
+ char *p;
+
+ p = malloc(SIZE);
+ if (!p) {
+ fprintf(stderr, "MALLOC FAILED: %s:%d\n", __FILE__, __LINE__);
+ return;
+ }
+
+ memset(p, 42, SIZE);
+
+ if (p[SIZE - 1] != 42)
+ fprintf(stderr, "MEMSET FAILED: %s:%d\n", __FILE__, __LINE__);
+
+ free(p);
+}
+
+void recursive_stack(int i)
+{
+ char buf[1024];
+ if (i > 0)
+ recursive_stack(i - 1);
+}
+
+void testfunc_deepstack(void)
+{
+ char buf[1024];
+ recursive_stack(7 * 1024);
+}
diff --git a/schulung_tools/pgflt/main.c b/schulung_tools/pgflt/main.c
new file mode 100644
index 0000000..a68baf4
--- /dev/null
+++ b/schulung_tools/pgflt/main.c
@@ -0,0 +1,60 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+extern void timestamp(const char *msg, int val);
+extern void testfunc_malloc(void);
+extern void testfunc_deepstack(void);
+extern void setup_rt(unsigned int opts);
+
+static void usage(const char *cmd)
+{
+ printf("usage: %s [opts-bitmask]\n", cmd);
+ printf(" opts-bits:\n");
+ printf(" 0x01 = mallopt\n");
+ printf(" 0x02 = mlockall\n");
+ printf(" 0x04 = prefault-stack\n");
+ printf(" 0x08 = prefault-heap\n");
+ printf(" 0x10 = run tests\n");
+ printf("\n");
+ printf(" 0x10 = no rt tweaks + tests\n");
+ printf(" 0x1f = full rt tweaks + tests\n");
+ printf("\n");
+}
+
+int main(int argc, char *argv[])
+{
+ unsigned int i;
+
+ if (argc != 2) {
+ usage(argv[0]);
+ return 1;
+ }
+
+ if (sscanf(argv[1], "%x", &i) != 1) {
+ usage(argv[0]);
+ return 1;
+ }
+
+ printf("options: 0x%x\n", i);
+
+ timestamp("init", -1);
+
+ setup_rt(i);
+
+ timestamp("main setup", -1);
+
+ if (i & 0x10) {
+ for (i = 0; i < 4; i++) {
+ testfunc_malloc();
+ timestamp("testfunc_malloc", i);
+ }
+
+ for (i = 0; i < 4; i++) {
+ testfunc_deepstack();
+ timestamp("testfunc_deepstack", i);
+ }
+ }
+
+ return 0;
+}
diff --git a/schulung_tools/pgflt/rt.c b/schulung_tools/pgflt/rt.c
new file mode 100644
index 0000000..86a6506
--- /dev/null
+++ b/schulung_tools/pgflt/rt.c
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <sys/mman.h>
+
+extern void timestamp(const char *msg, int val);
+extern void testfunc_malloc(void);
+extern void testfunc_deepstack(void);
+
+void prefault_stack(void)
+{
+#define STACK_SIZE (7680 * 1024) /* 7.5 MiB */
+ char buf[STACK_SIZE];
+ long pagesize;
+ int i;
+
+ pagesize = sysconf(_SC_PAGESIZE);
+
+ for (i = 0; i < STACK_SIZE; i += pagesize)
+ buf[i] = 0;
+}
+
+void prefault_heap(void)
+{
+#define HEAP_SIZE (20 * 1024 * 1024) /* 20 MiB */
+ long pagesize;
+ char *buf;
+ int i;
+
+ pagesize = sysconf(_SC_PAGESIZE);
+
+ buf = malloc(HEAP_SIZE);
+ if (!buf) {
+ fprintf(stderr, "MALLOC FAILED: %s:%d\n", __FILE__, __LINE__);
+ return;
+ }
+
+ for (i = 0; i < HEAP_SIZE; i += pagesize)
+ buf[i] = 0;
+
+ free(buf);
+}
+
+void setup_rt(unsigned int opts)
+{
+ if (opts & 0x1) {
+ if (mallopt(M_TRIM_THRESHOLD, -1) == 0) {
+ fprintf(stderr, "MALLOPT FAILED: %s:%d\n",
+ __FILE__, __LINE__);
+ }
+
+ if (mallopt(M_MMAP_MAX, 0) == 0) {
+ fprintf(stderr, "MALLOPT FAILED: %s:%d\n",
+ __FILE__, __LINE__);
+ }
+ }
+
+ if (opts & 0x2) {
+ if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
+ fprintf(stderr, "MLOCKALL FAILED: %s:%d\n",
+ __FILE__, __LINE__);
+ }
+ }
+
+ if (opts & 0x4)
+ prefault_stack();
+
+ if (opts & 0x8)
+ prefault_heap();
+}
+