summaryrefslogtreecommitdiff
path: root/cesar/lib/perf.h
blob: 8e535a009d482f6d895893539c3d32329d5f54e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#ifndef lib_perf_h
#define lib_perf_h
/* Cesar project {{{
 *
 * Copyright (C) 2009 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    lib/perf.h
 * \brief   Performance measure tool.
 * \ingroup lib
 *
 * This can be used to instrument code in order to measure its performance.
 *
 * The user must define a configuration item which starts with CONFIG_PERF.
 * It will be used to conditionally include the measurement code for a
 * particular piece of code.
 *
 * Results can be stored in a trace buffer.
 *
 * The CONFIG_PERF item (without suffix) is the global switch to disable all
 * performance measurement.
 */

/* Include all user defined configuration items. */
#include "config/perf.h"

#if CONFIG_PERF

# include "lib/trace.h"
# include "hal/arch/time.h"

/**
 * To be used at begin of function to measure its execution time.
 * \param  config  configuration item suffix to activate this measurement
 */
# define PERF_FUNC_BEGIN(config) \
    PASTE_EXPAND (PERF_FUNC_BEGIN_, CONFIG_PERF_ ## config) ()
# define PERF_FUNC_BEGIN_0()
# define PERF_FUNC_BEGIN_1() \
    TRACE_FAST_SHORT (PERF_TRACE_, &perf_global.trace, FUNC_BEGIN, ARCH_TIME, \
                      __PRETTY_FUNCTION__)

/**
 * To be used inside a function to measure its execution time.
 * \param  config  configuration item suffix to activate this measurement
 * \param  step  step identifier
 */
# define PERF_FUNC_STEP(config, step) \
    PASTE_EXPAND (PERF_FUNC_STEP_, CONFIG_PERF_ ## config) (#step)
# define PERF_FUNC_STEP_0(step)
# define PERF_FUNC_STEP_1(step) \
    TRACE_FAST_SHORT (PERF_TRACE_, &perf_global.trace, FUNC_STEP, ARCH_TIME, \
                      __PRETTY_FUNCTION__, step)

/**
 * To be used at end of function to measure its execution time.
 * \param  config  configuration item suffix to activate this measurement
 */
# define PERF_FUNC_END(config) \
    PASTE_EXPAND (PERF_FUNC_END_, CONFIG_PERF_ ## config) ()
# define PERF_FUNC_END_0()
# define PERF_FUNC_END_1() \
    TRACE_FAST_SHORT (PERF_TRACE_, &perf_global.trace, FUNC_END, ARCH_TIME, \
                      __PRETTY_FUNCTION__)

/**
 * Can be used to measure a small code chunk:
 *
 * \code
 * uint i;
 * u32 start = PERF_TIME;
 * for (i = 0; i = MANY; i++)
 *     run_my_code ();
 * u32 stop = PERF_TIME;
 * test_verbose_print ("run_my_code: %d us/%d",
 *                     (stop - start) / PERF_FREQ_MHZ, MANY);
 * \endcode
 */
# define PERF_TIME ARCH_TIME

/** Frequency of the measurement clock. */
# define PERF_FREQ_MHZ ARCH_TIME_FREQ_MHZ

/** Context. */
struct perf_t
{
#if CONFIG_TRACE
    /** Trace performance results. */
    trace_buffer_t trace;
#endif /* CONFIG_TRACE */
};
typedef struct perf_t perf_t;

/** Global context. */
extern perf_t perf_global;

/** Trace events. */
enum
{
    PERF_TRACE_FUNC_BEGIN,
    PERF_TRACE_FUNC_STEP,
    PERF_TRACE_FUNC_END,
};

BEGIN_DECLS

/**
 * Initialise this module.
 */
void
perf_init (void);

/**
 * Uninitialise this module.
 */
void
perf_uninit (void);

END_DECLS

#else

# define PERF_FUNC_BEGIN(config)
# define PERF_FUNC_STEP(config, step)
# define PERF_FUNC_END(config)
# define perf_init()
# define perf_uninit()

#endif

#endif /* lib_perf_h */