PR #24369 opened by Martin Storsjö (mstorsjo)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24369
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24369.patch

This improves benchmarking on macOS on aarch64, and with Linux perf.



From b12fa2bd7fc4b02faae84e8d59f16dd6e4c09905 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <[email protected]>
Date: Fri, 4 Sep 2026 23:26:27 +0300
Subject: [PATCH] Squashed 'tests/checkasm/ext/' changes from
 e822e429f3..dc9930dd0b

dc9930dd0b Fix linux (perf) timer doesn't increment when affinity is set
41918dba23 perf: Warm up execution on Apple Silicon/macOS before benchmarking

git-subtree-dir: tests/checkasm/ext
git-subtree-split: dc9930dd0b42c572fc57398cacacc71d2e892e6b
---
 src/checkasm.c   |  2 ++
 src/internal.h   |  1 +
 src/perf.c       | 24 ++++++++++++++++++++++++
 src/perf/linux.c | 32 +++++++++++++++++++++++++++++++-
 4 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/src/checkasm.c b/src/checkasm.c
index a47308deac..f8f7646243 100644
--- a/src/checkasm.c
+++ b/src/checkasm.c
@@ -886,6 +886,8 @@ int checkasm_run(const CheckasmConfig *config)
         if (checkasm_perf_init())
             return 1;
 
+        checkasm_perf_warmup();
+
         checkasm_stats_reset(&stats);
         checkasm_measurement_init(&state.nop_cycles);
         checkasm_measurement_init(&state.perf_scale);
diff --git a/src/internal.h b/src/internal.h
index 6192ede221..e4e23a0574 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -161,6 +161,7 @@ int checkasm_perf_init_macos(CheckasmPerf *perf);
 int checkasm_perf_init_arm(CheckasmPerf *perf);
 int checkasm_perf_validate_start(const CheckasmPerf *perf);
 int checkasm_perf_validate_start_stop(const CheckasmPerf *perf);
+void checkasm_perf_warmup(void);
 
 int checkasm_run_on_all_cores(void (*func)(void));
 
diff --git a/src/perf.c b/src/perf.c
index fd9e51203e..b27d8b7e4d 100644
--- a/src/perf.c
+++ b/src/perf.c
@@ -254,3 +254,27 @@ COLD void checkasm_measure_perf_scale(CheckasmMeasurement 
*meas)
 
     checkasm_measurement_update(meas, stats);
 }
+
+COLD void checkasm_perf_warmup(void)
+{
+#if defined(__APPLE__) && ARCH_AARCH64
+    /* On Apple Silicon, we have both performance and efficiency cores.
+     * On macOS, we can't pin the affinity of the process to a specific core.
+     *
+     * Therefore, benchmarks can easily get corrupted a lot by the process
+     * being moved from one core type to another.
+     *
+     * Processes seem to start out on an efficiency core, but get migrated
+     * to a performance core after burning CPU for a while. Try to make sure
+     * we consume CPU for a while before continuing with the program execution.
+     *
+     * This seems to be enough for mostly stable benchmarks without kperf.
+     */
+    uint64_t nsec        = checkasm_gettime_nsec();
+    uint64_t target_nsec = 100 * 1000 * 1000; // 100 ms
+    while (checkasm_gettime_nsec_diff(nsec) < target_nsec) {
+        for (int i = 0; i < 10000; i++)
+            checkasm_noop(NULL);
+    }
+#endif
+}
diff --git a/src/perf/linux.c b/src/perf/linux.c
index 1bf49eb2d5..70c972cc80 100644
--- a/src/perf/linux.c
+++ b/src/perf/linux.c
@@ -39,10 +39,38 @@
   #include <sys/syscall.h>
   #include <unistd.h>
 
+  #if HAVE_PTHREAD_SETAFFINITY_NP
+    #include <pthread.h>
+  #endif
+
   #include "internal.h"
 
 static int perf_sysfd = -1;
 
+/* The pinned CPU index, or -1 unless the thread is pinned to one CPU */
+static int get_pinned_cpu(void)
+{
+#if HAVE_PTHREAD_SETAFFINITY_NP && defined(CPU_SET)
+    cpu_set_t mask;
+    int cpu = -1;
+
+    if (pthread_getaffinity_np(pthread_self(), sizeof(mask), &mask))
+        return -1;
+
+    for (int i = 0; i < CPU_SETSIZE; i++) {
+        if (!CPU_ISSET(i, &mask))
+            continue;
+        if (cpu >= 0)
+            return -1;
+        cpu = i;
+    }
+
+    return cpu;
+#else
+    return -1;
+#endif
+}
+
 static uint64_t perf_start(void)
 {
     ioctl(perf_sysfd, PERF_EVENT_IOC_RESET, 0);
@@ -73,7 +101,9 @@ COLD int checkasm_perf_init_linux(CheckasmPerf *perf)
     };
 
     if (perf_sysfd == -1) {
-        perf_sysfd = (int) syscall(SYS_perf_event_open, &attr, 0, -1, -1, 0);
+        perf_sysfd = (int) syscall(SYS_perf_event_open, &attr, /*pid*/ 0,
+                                   get_pinned_cpu(), /*group_fd*/ -1,
+                                   /*flags*/ 0);
         if (perf_sysfd == -1) {
             perror("perf_event_open");
             return 1;
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to