[FFmpeg-devel] [PATCH 2/6] checkasm: use pointers for start/stop functions

Rémi Denis-Courmont remi at remlab.net
Wed Jul 19 22:55:36 EEST 2023


Linux and MacOS kernel performance APIs are not always available.
This introduces function pointers so that we can fall back to other
timing functions (in later changesets).

If AV_READ_TIME is the only configured timer, then this sticks to
inline assembler since there will be nothing to fall back to (or from),
and some people are concerned than an indirect function call is too
much overhead.
---
 tests/checkasm/checkasm.c | 25 +++++++++++++++++++++++--
 tests/checkasm/checkasm.h | 24 ++++++------------------
 2 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
index 63141e1f7a..933d85bac3 100644
--- a/tests/checkasm/checkasm.c
+++ b/tests/checkasm/checkasm.c
@@ -57,6 +57,14 @@
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#if CONFIG_LINUX_PERF
+#include <sys/ioctl.h>
+#include <asm/unistd.h>
+#include <linux/perf_event.h>
+#endif
+#if CONFIG_MACOS_KPERF
+#include "libavutil/macos_kperf.h"
+#endif
 
 #if !HAVE_ISATTY
 #define isatty(fd) 1
@@ -313,6 +321,8 @@ static struct {
     /* perf */
     int nop_time;
     int sysfd;
+    uint64_t (*start)(void);
+    uint64_t (*stop)(void);
 
     int cpu_flag;
     const char *cpu_flag_name;
@@ -513,6 +523,12 @@ static int measure_nop_time(void)
     uint16_t nops[10000];
     int i, nop_sum = 0;
     av_unused const int sysfd = state.sysfd;
+#if CONFIG_LINUX_PERF || CONFIG_MACOS_KPERF
+    struct {
+         uint64_t (*start)(void);
+         uint64_t (*stop)(void);
+    } p = { state.start, state.stop }, *perf = &p;
+#endif
 
     for (i = 0; i < 10000; i++) {
         uint64_t t = checkasm_bench_start();
@@ -650,7 +666,7 @@ static void print_cpu_name(void)
 }
 
 #if CONFIG_LINUX_PERF
-uint64_t checkasm_bench_linux_perf_start(void)
+static uint64_t checkasm_bench_linux_perf_start(void)
 {
     int fd = state.sysfd;
 
@@ -659,7 +675,7 @@ uint64_t checkasm_bench_linux_perf_start(void)
     return 0;
 }
 
-uint64_t checkasm_bench_linux_perf_stop(void)
+static uint64_t checkasm_bench_linux_perf_stop(void)
 {
     uint64_t t;
     int fd = state.sysfd;
@@ -686,12 +702,15 @@ static int bench_init_linux(void)
         perror("syscall");
         return -1;
     }
+    state.start = checkasm_bench_linux_perf_start;
+    state.stop = checkasm_bench_linux_perf_stop;
     return 0;
 }
 #elif CONFIG_MACOS_KPERF
 static int bench_init_kperf(void)
 {
     ff_kperf_init();
+    state.start = state.stop = ff_kperf_cycles;
     return 0;
 }
 #else
@@ -882,6 +901,8 @@ CheckasmPerf *checkasm_get_perf_context(void)
     CheckasmPerf *perf = &state.current_func_ver->perf;
     memset(perf, 0, sizeof(*perf));
     perf->sysfd = state.sysfd;
+    perf->start = state.start;
+    perf->stop = state.stop;
     return perf;
 }
 
diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h
index 8a62b98f3e..3b3a1ab35b 100644
--- a/tests/checkasm/checkasm.h
+++ b/tests/checkasm/checkasm.h
@@ -26,15 +26,6 @@
 #include <stdint.h>
 #include "config.h"
 
-#if CONFIG_LINUX_PERF
-#include <unistd.h> // read(3)
-#include <sys/ioctl.h>
-#include <asm/unistd.h>
-#include <linux/perf_event.h>
-#elif CONFIG_MACOS_KPERF
-#include "libavutil/macos_kperf.h"
-#endif
-
 #include "libavutil/avstring.h"
 #include "libavutil/cpu.h"
 #include "libavutil/internal.h"
@@ -236,16 +227,13 @@ typedef struct CheckasmPerf {
     int sysfd;
     uint64_t cycles;
     int iterations;
+    uint64_t (*start)(void);
+    uint64_t (*stop)(void);
 } CheckasmPerf;
 
-#if CONFIG_LINUX_PERF
-uint64_t checkasm_bench_linux_perf_start(void);
-uint64_t checkasm_bench_linux_perf_stop(void);
-#define checkasm_bench_start() checkasm_bench_linux_perf_start()
-#define checkasm_bench_stop()  checkasm_bench_linux_perf_stop()
-#elif CONFIG_MACOS_KPERF
-#define checkasm_bench_start() ff_kperf_cycles()
-#define checkasm_bench_stop()  ff_kperf_cycles()
+#if CONFIG_LINUX_PERF || CONFIG_MACOS_KPERF
+#define checkasm_bench_start() (perf->start)()
+#define checkasm_bench_stop()  (perf->stop)()
 #elif defined (AV_READ_TIME)
 #define checkasm_bench_start() AV_READ_TIME()
 #define checkasm_bench_stop()  AV_READ_TIME()
@@ -258,7 +246,7 @@ uint64_t checkasm_bench_linux_perf_stop(void);
 #define bench_new(...)\
     do {\
         if (checkasm_bench_func()) {\
-            struct CheckasmPerf *perf = checkasm_get_perf_context();\
+            struct CheckasmPerf *restrict perf = checkasm_get_perf_context();\
             av_unused const int sysfd = perf->sysfd;\
             func_type *tfunc = func_new;\
             uint64_t tsum = 0;\
-- 
2.40.1



More information about the ffmpeg-devel mailing list