/src/ffmpeg/libavutil/timer.h
Line | Count | Source |
1 | | /* |
2 | | * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> |
3 | | * |
4 | | * This file is part of FFmpeg. |
5 | | * |
6 | | * FFmpeg is free software; you can redistribute it and/or |
7 | | * modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation; either |
9 | | * version 2.1 of the License, or (at your option) any later version. |
10 | | * |
11 | | * FFmpeg is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with FFmpeg; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | */ |
20 | | |
21 | | /** |
22 | | * @file |
23 | | * high precision timer, useful to profile code |
24 | | */ |
25 | | |
26 | | #ifndef AVUTIL_TIMER_H |
27 | | #define AVUTIL_TIMER_H |
28 | | |
29 | | #include "config.h" |
30 | | |
31 | | #if CONFIG_LINUX_PERF |
32 | | # ifndef _GNU_SOURCE |
33 | | # define _GNU_SOURCE |
34 | | # endif |
35 | | # include <unistd.h> // read(3) |
36 | | # include <sys/ioctl.h> |
37 | | # include <asm/unistd.h> |
38 | | # include <linux/perf_event.h> |
39 | | #endif |
40 | | |
41 | | #include <stdlib.h> |
42 | | #include <stdint.h> |
43 | | #include <inttypes.h> |
44 | | |
45 | | #if CONFIG_MACOS_KPERF |
46 | | #include "macos_kperf.h" |
47 | | #endif |
48 | | |
49 | | #if HAVE_MACH_ABSOLUTE_TIME |
50 | | #include <mach/mach_time.h> |
51 | | #elif HAVE_CLOCK_GETTIME |
52 | | #include <time.h> |
53 | | #endif |
54 | | |
55 | | #include "common.h" |
56 | | #include "log.h" |
57 | | |
58 | | #if ARCH_AARCH64 |
59 | | # include "aarch64/timer.h" |
60 | | #elif ARCH_ARM |
61 | | # include "arm/timer.h" |
62 | | #elif ARCH_PPC |
63 | | # include "ppc/timer.h" |
64 | | #elif ARCH_X86 |
65 | | # include "x86/timer.h" |
66 | | #elif ARCH_LOONGARCH |
67 | | # include "loongarch/timer.h" |
68 | | #endif |
69 | | |
70 | | #if !defined(AV_READ_TIME) |
71 | | # if HAVE_GETHRTIME |
72 | | # define AV_READ_TIME gethrtime |
73 | | # elif HAVE_MACH_ABSOLUTE_TIME |
74 | | # define AV_READ_TIME mach_absolute_time |
75 | | # elif HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC) |
76 | | static inline int64_t ff_read_time(void) |
77 | 0 | { |
78 | 0 | struct timespec ts; |
79 | 0 | clock_gettime(CLOCK_MONOTONIC, &ts); |
80 | 0 | return ts.tv_sec * INT64_C(1000000000) + ts.tv_nsec; |
81 | 0 | } |
82 | 0 | # define AV_READ_TIME ff_read_time |
83 | | # define FF_TIMER_UNITS "ns" |
84 | | # endif |
85 | | #endif |
86 | | |
87 | | #ifndef FF_TIMER_UNITS |
88 | | # define FF_TIMER_UNITS "UNITS" |
89 | | #endif |
90 | | |
91 | | #define TIMER_REPORT(id, tdiff) \ |
92 | | { \ |
93 | | static uint64_t tsum = 0; \ |
94 | | static int tcount = 0; \ |
95 | | static int tskip_count = 0; \ |
96 | | static int thistogram[32] = {0}; \ |
97 | | thistogram[av_log2(tdiff)]++; \ |
98 | | if (tcount < 2 || \ |
99 | | (tdiff) < 8 * tsum / tcount || \ |
100 | | (tdiff) < 2000) { \ |
101 | | tsum += (tdiff); \ |
102 | | tcount++; \ |
103 | | } else \ |
104 | | tskip_count++; \ |
105 | | if (((tcount + tskip_count) & (tcount + tskip_count - 1)) == 0) { \ |
106 | | int i; \ |
107 | | av_log(NULL, AV_LOG_ERROR, \ |
108 | | "%7" PRIu64 " " FF_TIMER_UNITS " in %s,%8d runs,%7d skips",\ |
109 | | tsum * 10 / tcount, id, tcount, tskip_count); \ |
110 | | for (i = 0; i < 32; i++) \ |
111 | | av_log(NULL, AV_LOG_VERBOSE, " %2d", av_log2(2*thistogram[i]));\ |
112 | | av_log(NULL, AV_LOG_ERROR, "\n"); \ |
113 | | } \ |
114 | | } |
115 | | |
116 | | #if CONFIG_LINUX_PERF |
117 | | |
118 | | #define START_TIMER \ |
119 | | static int linux_perf_fd = -1; \ |
120 | | uint64_t tperf; \ |
121 | | if (linux_perf_fd == -1) { \ |
122 | | struct perf_event_attr attr = { \ |
123 | | .type = PERF_TYPE_HARDWARE, \ |
124 | | .size = sizeof(struct perf_event_attr), \ |
125 | | .config = PERF_COUNT_HW_CPU_CYCLES, \ |
126 | | .disabled = 1, \ |
127 | | .exclude_kernel = 1, \ |
128 | | .exclude_hv = 1, \ |
129 | | }; \ |
130 | | linux_perf_fd = syscall(__NR_perf_event_open, &attr, \ |
131 | | 0, -1, -1, 0); \ |
132 | | } \ |
133 | | if (linux_perf_fd == -1) { \ |
134 | | av_log(NULL, AV_LOG_ERROR, "perf_event_open failed: %s\n", \ |
135 | | av_err2str(AVERROR(errno))); \ |
136 | | } else { \ |
137 | | ioctl(linux_perf_fd, PERF_EVENT_IOC_RESET, 0); \ |
138 | | ioctl(linux_perf_fd, PERF_EVENT_IOC_ENABLE, 0); \ |
139 | | } |
140 | | |
141 | | #define STOP_TIMER(id) \ |
142 | | ioctl(linux_perf_fd, PERF_EVENT_IOC_DISABLE, 0); \ |
143 | | read(linux_perf_fd, &tperf, sizeof(tperf)); \ |
144 | | TIMER_REPORT(id, tperf) |
145 | | |
146 | | #elif CONFIG_MACOS_KPERF |
147 | | |
148 | | #define START_TIMER \ |
149 | | uint64_t tperf; \ |
150 | | ff_kperf_init(); \ |
151 | | tperf = ff_kperf_cycles(); |
152 | | |
153 | | #define STOP_TIMER(id) \ |
154 | | TIMER_REPORT(id, ff_kperf_cycles() - tperf); |
155 | | |
156 | | #elif defined(AV_READ_TIME) |
157 | | #define START_TIMER \ |
158 | | uint64_t tend; \ |
159 | | uint64_t tstart = AV_READ_TIME(); \ |
160 | | |
161 | | #define STOP_TIMER(id) \ |
162 | | tend = AV_READ_TIME(); \ |
163 | | TIMER_REPORT(id, tend - tstart) |
164 | | #else |
165 | | #define START_TIMER |
166 | | #define STOP_TIMER(id) { } |
167 | | #endif |
168 | | |
169 | | #endif /* AVUTIL_TIMER_H */ |