basic_profiling.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. // Copyright 2023 Nick Brassel (@tzarc)
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. /*
  5. This API allows for basic profiling information to be printed out over console.
  6. Usage example:
  7. #include "basic_profiling.h"
  8. // Original code:
  9. matrix_task();
  10. // Delete the original, replace with the following (variant 1, automatic naming):
  11. PROFILE_CALL(1000, matrix_task());
  12. // Delete the original, replace with the following (variant 2, explicit naming):
  13. PROFILE_CALL_NAMED(1000, "matrix_task", {
  14. matrix_task();
  15. });
  16. */
  17. #if defined(PROTOCOL_LUFA) || defined(PROTOCOL_VUSB)
  18. # define TIMESTAMP_GETTER TCNT0
  19. #elif defined(PROTOCOL_CHIBIOS)
  20. # define TIMESTAMP_GETTER chSysGetRealtimeCounterX()
  21. #elif defined(PROTOCOL_ARM_ATSAM)
  22. # error arm_atsam not currently supported
  23. #else
  24. # error Unknown protocol in use
  25. #endif
  26. #ifndef CONSOLE_ENABLE
  27. // Can't do anything if we don't have console output enabled.
  28. # define PROFILE_CALL_NAMED(count, name, call) \
  29. do { \
  30. } while (0)
  31. #else
  32. # define PROFILE_CALL_NAMED(count, name, call) \
  33. do { \
  34. static uint64_t inner_sum = 0; \
  35. static uint64_t outer_sum = 0; \
  36. uint32_t start_ts; \
  37. static uint32_t end_ts; \
  38. static uint32_t write_location = 0; \
  39. start_ts = TIMESTAMP_GETTER; \
  40. if (write_location > 0) { \
  41. outer_sum += start_ts - end_ts; \
  42. } \
  43. do { \
  44. call; \
  45. } while (0); \
  46. end_ts = TIMESTAMP_GETTER; \
  47. inner_sum += end_ts - start_ts; \
  48. ++write_location; \
  49. if (write_location >= ((uint32_t)count)) { \
  50. uint32_t inner_avg = inner_sum / (((uint32_t)count) - 1); \
  51. uint32_t outer_avg = outer_sum / (((uint32_t)count) - 1); \
  52. dprintf("%s -- Percentage time spent: %d%%\n", (name), (int)(inner_avg * 100 / (inner_avg + outer_avg))); \
  53. inner_sum = 0; \
  54. outer_sum = 0; \
  55. write_location = 0; \
  56. } \
  57. } while (0)
  58. #endif // CONSOLE_ENABLE
  59. #define PROFILE_CALL(count, call) PROFILE_CALL_NAMED(count, #call, call)