timer.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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. * @file
  22. * high precision timer, useful to profile code
  23. */
  24. #ifndef AVUTIL_TIMER_H
  25. #define AVUTIL_TIMER_H
  26. #include "config.h"
  27. #if CONFIG_LINUX_PERF
  28. # ifndef _GNU_SOURCE
  29. # define _GNU_SOURCE
  30. # endif
  31. # include <unistd.h> // read(3)
  32. # include <sys/ioctl.h>
  33. # include <asm/unistd.h>
  34. # include <linux/perf_event.h>
  35. #endif
  36. #include <stdlib.h>
  37. #include <stdint.h>
  38. #include <inttypes.h>
  39. #if HAVE_MACH_ABSOLUTE_TIME
  40. #include <mach/mach_time.h>
  41. #endif
  42. #include "log.h"
  43. #if ARCH_AARCH64
  44. # include "aarch64/timer.h"
  45. #elif ARCH_ARM
  46. # include "arm/timer.h"
  47. #elif ARCH_PPC
  48. # include "ppc/timer.h"
  49. #elif ARCH_X86
  50. # include "x86/timer.h"
  51. #endif
  52. #if !defined(AV_READ_TIME)
  53. # if HAVE_GETHRTIME
  54. # define AV_READ_TIME gethrtime
  55. # elif HAVE_MACH_ABSOLUTE_TIME
  56. # define AV_READ_TIME mach_absolute_time
  57. # endif
  58. #endif
  59. #ifndef FF_TIMER_UNITS
  60. # define FF_TIMER_UNITS "UNITS"
  61. #endif
  62. #define TIMER_REPORT(id, tdiff) \
  63. { \
  64. static uint64_t tsum = 0; \
  65. static int tcount = 0; \
  66. static int tskip_count = 0; \
  67. static int thistogram[32] = {0}; \
  68. thistogram[av_log2(tdiff)]++; \
  69. if (tcount < 2 || \
  70. (tdiff) < 8 * tsum / tcount || \
  71. (tdiff) < 2000) { \
  72. tsum += (tdiff); \
  73. tcount++; \
  74. } else \
  75. tskip_count++; \
  76. if (((tcount + tskip_count) & (tcount + tskip_count - 1)) == 0) { \
  77. int i; \
  78. av_log(NULL, AV_LOG_ERROR, \
  79. "%7"PRIu64" " FF_TIMER_UNITS " in %s,%8d runs,%7d skips", \
  80. tsum * 10 / tcount, id, tcount, tskip_count); \
  81. for (i = 0; i < 32; i++) \
  82. av_log(NULL, AV_LOG_VERBOSE, " %2d", av_log2(2*thistogram[i]));\
  83. av_log(NULL, AV_LOG_ERROR, "\n"); \
  84. } \
  85. }
  86. #if CONFIG_LINUX_PERF
  87. #define START_TIMER \
  88. static int linux_perf_fd; \
  89. uint64_t tperf; \
  90. if (!linux_perf_fd) { \
  91. struct perf_event_attr attr = { \
  92. .type = PERF_TYPE_HARDWARE, \
  93. .size = sizeof(struct perf_event_attr), \
  94. .config = PERF_COUNT_HW_CPU_CYCLES, \
  95. .disabled = 1, \
  96. .exclude_kernel = 1, \
  97. .exclude_hv = 1, \
  98. }; \
  99. linux_perf_fd = syscall(__NR_perf_event_open, &attr, \
  100. 0, -1, -1, 0); \
  101. } \
  102. if (linux_perf_fd == -1) { \
  103. av_log(NULL, AV_LOG_ERROR, "perf_event_open failed: %s\n", \
  104. av_err2str(AVERROR(errno))); \
  105. } else { \
  106. ioctl(linux_perf_fd, PERF_EVENT_IOC_RESET, 0); \
  107. ioctl(linux_perf_fd, PERF_EVENT_IOC_ENABLE, 0); \
  108. }
  109. #define STOP_TIMER(id) \
  110. ioctl(linux_perf_fd, PERF_EVENT_IOC_DISABLE, 0); \
  111. read(linux_perf_fd, &tperf, sizeof(tperf)); \
  112. TIMER_REPORT(id, tperf)
  113. #elif defined(AV_READ_TIME)
  114. #define START_TIMER \
  115. uint64_t tend; \
  116. uint64_t tstart = AV_READ_TIME(); \
  117. #define STOP_TIMER(id) \
  118. tend = AV_READ_TIME(); \
  119. TIMER_REPORT(id, tend - tstart)
  120. #else
  121. #define START_TIMER
  122. #define STOP_TIMER(id) { }
  123. #endif
  124. #endif /* AVUTIL_TIMER_H */