mesure cache misses
authorLaurent MAZET <laurent.mazet@thalesgroup.com>
Wed, 28 Jan 2026 16:06:22 +0000 (17:06 +0100)
committerLaurent MAZET <laurent.mazet@thalesgroup.com>
Wed, 28 Jan 2026 16:06:38 +0000 (17:06 +0100)
generic.c
mq.c
perf.c [new file with mode: 0644]
perf.h [new file with mode: 0644]
pipe.c
udp.c
udp1k.c
udp8k.c

index 3f4f6a58032d84cf67839ac317bcde00d07ba86a..340cd54082fdd6de4ce8ee1379b13b30f0039331 100644 (file)
--- a/generic.c
+++ b/generic.c
@@ -12,6 +12,7 @@
 #include "main.h"
 #include "msg.h"
 #include "mtime.h"
+#include "perf.h"
 
 #include "generic.h"
 
@@ -98,6 +99,12 @@ void *ping (__attribute__((unused)) void *arg)
 
     printf ("Sending ping...\n");
 
+    int fd0 = cachemiss_init (0);
+    int fd1 = cachemiss_init (1);
+    int fd2 = cachemiss_init (2);
+    int fd3 = cachemiss_init (3);
+    int fd4 = cachemiss_init (4);
+    int fd5 = cachemiss_init (5);
 
     for (int i = -1; i < nb_measurements; i++) {
 
@@ -134,6 +141,13 @@ void *ping (__attribute__((unused)) void *arg)
        usleep (TIMER / 10);
     }
 
+    fprintf (stdout, "ping cache miss ratio: %.1f%%\n",
+             cachemiss_end (fd1) / (double)cachemiss_end (fd0) * 100.);
+    fprintf (stdout, "ping cache L1D miss ratio: %.1f%%\n",
+             cachemiss_end (fd3) / (double)cachemiss_end (fd2) * 100.);
+    fprintf (stdout, "ping cache L1I miss ratio: %.1f%%\n",
+             cachemiss_end (fd5) / (double)cachemiss_end (fd4) * 100.);
+
     /* close communication between process */
 
     if (current_mode == 1) {
@@ -165,6 +179,13 @@ void *pong (__attribute__((unused)) void *arg)
 
     printf ("Receiving pong...\n");
 
+    int fd0 = cachemiss_init (0);
+    int fd1 = cachemiss_init (1);
+    int fd2 = cachemiss_init (2);
+    int fd3 = cachemiss_init (3);
+    int fd4 = cachemiss_init (4);
+    int fd5 = cachemiss_init (5);
+
     for (int i = -1; i < nb_measurements; i++) {
 
         usleep (TIMER);
@@ -196,6 +217,13 @@ void *pong (__attribute__((unused)) void *arg)
         }
     }
 
+    fprintf (stdout, "pong cache miss ratio: %.1f%%\n",
+             cachemiss_end (fd1) / (double)cachemiss_end (fd0) * 100.);
+    fprintf (stdout, "pong cache L1D miss ratio: %.1f%%\n",
+             cachemiss_end (fd3) / (double)cachemiss_end (fd2) * 100.);
+    fprintf (stdout, "pong cache L1I miss ratio: %.1f%%\n",
+             cachemiss_end (fd5) / (double)cachemiss_end (fd4) * 100.);
+
     /* close communication between process */
 
     if (current_mode == 1) {
diff --git a/mq.c b/mq.c
index 70040134d21cc17df5974cff9eb1b5e71ed2dca9..16a2757aa043e70e9fb3d967060ed872a9d058be 100644 (file)
--- a/mq.c
+++ b/mq.c
@@ -1,6 +1,6 @@
 /* depend: */
 /* cflags: */
-/* linker: generic.o main.o msg.o mtime.o stat.o -lm -lpthread -lrt */
+/* linker: generic.o main.o msg.o mtime.o perf.o stat.o -lm -lpthread -lrt */
 
 #include <errno.h>
 #include <fcntl.h>
diff --git a/perf.c b/perf.c
new file mode 100644 (file)
index 0000000..56f3ba1
--- /dev/null
+++ b/perf.c
@@ -0,0 +1,96 @@
+#define _GNU_SOURCE
+#include <asm/unistd.h>
+#include <linux/perf_event.h>
+#include <sched.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include "perf.h"
+
+int cachemiss_init (int mode)
+{
+
+    int cpu = -1;
+    cpu_set_t cpu_mask = {0};
+    if (sched_getaffinity (0, sizeof (cpu_set_t), &cpu_mask) != 0) {
+        fprintf (stderr, "error: sched_getaffinity\n");
+        return -1;
+    }
+    for (int i = 0; i < CPU_COUNT (&cpu_mask); i++) {
+        if (CPU_ISSET (i, &cpu_mask)) {
+            if (cpu == -1) {
+                cpu = i;
+            } else {
+                cpu = -1;
+                break;
+            }
+        }
+    }
+
+    struct perf_event_attr pe = {0};
+    pe.size = sizeof (struct perf_event_attr);
+    switch (mode) {
+    case 0:
+        pe.type = PERF_TYPE_HARDWARE;
+        pe.config = PERF_COUNT_HW_CACHE_REFERENCES;
+        break;
+    case 1:
+        pe.type = PERF_TYPE_HARDWARE;
+        pe.config = PERF_COUNT_HW_CACHE_MISSES;
+        break;
+    case 2:
+        pe.type = PERF_TYPE_HW_CACHE;
+        pe.config = PERF_COUNT_HW_CACHE_L1D |
+                    PERF_COUNT_HW_CACHE_OP_READ << 8 |
+                    PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16;
+        break;
+    case 3:
+        pe.type = PERF_TYPE_HW_CACHE;
+        pe.config = PERF_COUNT_HW_CACHE_L1D |
+                    PERF_COUNT_HW_CACHE_OP_READ << 8 |
+                    PERF_COUNT_HW_CACHE_RESULT_MISS << 16;
+        break;
+    case 4:
+        pe.type = PERF_TYPE_HW_CACHE;
+        pe.config = PERF_COUNT_HW_CACHE_L1I |
+                    PERF_COUNT_HW_CACHE_OP_READ << 8 |
+                    PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16;
+        break;
+    case 5:
+        pe.type = PERF_TYPE_HW_CACHE;
+        pe.config = PERF_COUNT_HW_CACHE_L1I |
+                    PERF_COUNT_HW_CACHE_OP_READ << 8 |
+                    PERF_COUNT_HW_CACHE_RESULT_MISS << 16;
+        break;
+    }
+    pe.disabled = 1;
+    pe.exclude_kernel = 1;
+    pe.exclude_hv = 1;
+
+    int fd = syscall(__NR_perf_event_open, &pe, 0, cpu, -1, 0);
+    if (fd == -1) {
+        fprintf (stderr, "Error opening leader %llx\n", pe.config);
+        return -1;
+    }
+
+    ioctl(fd, PERF_EVENT_IOC_RESET, 0);
+    ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
+
+    return fd;
+}
+
+long long int cachemiss_end (int fd)
+{
+
+    ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
+
+    long long int count = 0;
+    read(fd, &count, sizeof(long long int));
+
+    close (fd);
+
+    return count;
+}
diff --git a/perf.h b/perf.h
new file mode 100644 (file)
index 0000000..aebe00c
--- /dev/null
+++ b/perf.h
@@ -0,0 +1,7 @@
+#ifndef __PERF_H__
+#define __PERF_H__
+
+int cachemiss_init (int mode);
+long long int cachemiss_end (int fd);
+
+#endif /* __PERF_H__ */
diff --git a/pipe.c b/pipe.c
index f3bd50fe63dfb35481be1b7c23b047ceceb319e2..c98745fa27cb9e29a0af8426cbc1976503f26886 100644 (file)
--- a/pipe.c
+++ b/pipe.c
@@ -1,7 +1,8 @@
 /* depend: */
 /* cflags: */
-/* linker: generic.o main.o msg.o mtime.o stat.o -lm -lpthread -lrt */
+/* linker: generic.o main.o msg.o mtime.o perf.o stat.o -lm -lpthread -lrt */
 
+#include <stdint.h>
 #include <stdio.h>
 #include <unistd.h>
 
@@ -38,6 +39,26 @@ int ping_init (void)
 
 int ping_test (char *buffer, int len)
 {
+#if 0
+#ifdef __aarch64__ /* 64 bits */
+    int64_t instructions = 0;
+#else /* 32 bits */
+    int32_t instructions = 0;
+#endif
+    while (instructions < 10000000) {
+#define INST0 "add %[i], %[i], #1\n\t"
+#define INST1 INST0 INST0 INST0 INST0  INST0 INST0 INST0 INST0 \
+              INST0 INST0 INST0 INST0  INST0 INST0 INST0 INST0
+#define INST2 INST1 INST1 INST1 INST1  INST1 INST1 INST1 INST1 \
+              INST1 INST1 INST1 INST1  INST1 INST1 INST1 INST1
+#define INST3 INST2 INST2 INST2 INST2  INST2 INST2 INST2 INST2 \
+              INST2 INST2 INST2 INST2  INST2 INST2 INST2 INST2
+#define INST4 INST3 INST3 INST3 INST3  INST3 INST3 INST3 INST3 \
+              INST3 INST3 INST3 INST3  INST3 INST3 INST3 INST3
+        asm volatile (INST4 : [i] "+r" (instructions) :: "cc");
+        asm volatile (INST4 : [i] "+r" (instructions) :: "cc");
+    }
+#endif
     return (write (fdout, buffer, len) == -1);
 }
 
diff --git a/udp.c b/udp.c
index ee360d3f7e21a0925e8ff0e4239cbb77ca2eab88..9e297d29ad1582f8fe0cb90ea95c13944e527286 100644 (file)
--- a/udp.c
+++ b/udp.c
@@ -1,6 +1,6 @@
 /* depend: */
 /* cflags: */
-/* linker: generic.o main.o msg.o mtime.o stat.o -lm -lpthread -lrt */
+/* linker: generic.o main.o msg.o mtime.o perf.o stat.o -lm -lpthread -lrt */
 
 #include <arpa/inet.h>
 #include <netdb.h>
diff --git a/udp1k.c b/udp1k.c
index 739eea3369c8d664610840b49e87bf2794bb5c8a..f30b776e573ff486109e8c75148007ac47dd9e8d 100644 (file)
--- a/udp1k.c
+++ b/udp1k.c
@@ -1,6 +1,6 @@
 /* depend: */
 /* cflags: */
-/* linker: main.o msg.o mtime.o stat.o -lm -lpthread -lrt */
+/* linker: main.o msg.o mtime.o stat.o perf.o -lm -lpthread -lrt */
 
 #define __TESTNAME__
 char *message = "UDP socket latency (1k)";
diff --git a/udp8k.c b/udp8k.c
index 08d5070b0aed2bec5f351b81f50cd7510d70829e..bfebc67ac84087b8cf6b76dcae6a97ff62901910 100644 (file)
--- a/udp8k.c
+++ b/udp8k.c
@@ -1,6 +1,6 @@
 /* depend: */
 /* cflags: */
-/* linker: main.o msg.o mtime.o stat.o -lm -lpthread -lrt */
+/* linker: main.o msg.o mtime.o perf.o stat.o -lm -lpthread -lrt */
 
 #define __TESTNAME__
 char *message = "UDP socket latency (8k)";