Parent directory

basic_profiling.h

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