Commit | Line | Data |
---|---|---|
b64eb60f MW |
1 | /* -*-c-*- |
2 | * | |
3 | * Benchmarking support | |
4 | * | |
5 | * (c) 2023 Straylight/Edgeware | |
6 | */ | |
7 | ||
8 | /*----- Licensing notice --------------------------------------------------* | |
9 | * | |
10 | * This file is part of the mLib utilities library. | |
11 | * | |
12 | * mLib is free software: you can redistribute it and/or modify it under | |
13 | * the terms of the GNU Library General Public License as published by | |
14 | * the Free Software Foundation; either version 2 of the License, or (at | |
15 | * your option) any later version. | |
16 | * | |
17 | * mLib is distributed in the hope that it will be useful, but WITHOUT | |
18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
19 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public | |
20 | * License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU Library General Public | |
23 | * License along with mLib. If not, write to the Free Software | |
24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
25 | * USA. | |
26 | */ | |
27 | ||
28 | #ifndef MLIB_BENCH_H | |
29 | #define MLIB_BENCH_H | |
30 | ||
31 | #ifdef __cplusplus | |
32 | extern "C" { | |
33 | #endif | |
34 | ||
35 | /*----- Header files ------------------------------------------------------*/ | |
36 | ||
37 | #ifndef MLIB_BITS_H | |
38 | # include "bits.h" | |
39 | #endif | |
40 | ||
41 | /*----- Data structures ---------------------------------------------------*/ | |
42 | ||
43 | struct bench_time { | |
67b5031e MW |
44 | unsigned f; /* flags */ |
45 | #define BTF_TIMEOK 1u /* @s@ ad @ns@ slots are value */ | |
46 | #define BTF_CYOK 2u /* @cy@ slot is valid */ | |
47 | #define BTF_ANY (BTF_TIMEOK | BTF_CYOK) /* some part is useful */ | |
c91413e6 MW |
48 | kludge64 s; uint32 ns; /* real time, seconds and nanos */ |
49 | kludge64 cy; /* count of CPU cycles */ | |
b64eb60f MW |
50 | }; |
51 | ||
52 | struct bench_timing { | |
c91413e6 | 53 | unsigned f; /* flags (@BTF_...@) */ |
67b5031e | 54 | double n, t, cy; /* count, time, and cycles */ |
b64eb60f MW |
55 | }; |
56 | ||
57 | struct bench_timer { const struct bench_timerops *ops; }; | |
58 | ||
59 | struct bench_timerops { | |
60 | void (*now)(struct bench_timer */*bt*/, struct bench_time */*t_out*/); | |
67b5031e MW |
61 | /* Fill in @*t_out@ with the current time. v*/ |
62 | ||
b64eb60f | 63 | void (*destroy)(struct bench_timer */*bt*/); |
67b5031e | 64 | /* Release the timer and any resources it holds. */ |
b64eb60f MW |
65 | }; |
66 | ||
67 | struct bench_state { | |
67b5031e MW |
68 | struct bench_timer *tm; /* a timer */ |
69 | double target_s; /* target time to run benchmarks */ | |
c91413e6 | 70 | unsigned f; /* calibration flags (@BTF_...@) */ |
67b5031e | 71 | struct { double m, c; } clk, cy; /* calculated overheads */ |
b64eb60f MW |
72 | }; |
73 | ||
67b5031e | 74 | typedef void bench_fn(unsigned long /*n*/, void */*ctx*/); |
c91413e6 | 75 | /* Run the benchmark @n@ times, given a context pointer @ctx@. */ |
b64eb60f MW |
76 | |
77 | /*----- Functions provided ------------------------------------------------*/ | |
78 | ||
67b5031e MW |
79 | /* --- @bench_createtimer@ --- * |
80 | * | |
81 | * Arguments: --- | |
82 | * | |
83 | * Returns: A freshly constructed standard timer object. | |
84 | * | |
85 | * Use: Allocate a timer. Dispose of it by calling | |
86 | * @tm->ops->destroy(tm)@ when you're done. | |
87 | */ | |
88 | ||
b64eb60f MW |
89 | extern struct bench_timer *bench_createtimer(void); |
90 | ||
67b5031e MW |
91 | /* --- @bench_init@ --- * |
92 | * | |
93 | * Arguments: @struct bench_state *b@ = bench state to initialize | |
94 | * @struct bench_timer *tm@ = timer to attach | |
95 | * | |
96 | * Returns: --- | |
97 | * | |
98 | * Use: Initialize the benchmark state. It still needs to be | |
99 | * calibrated (use @bench_calibrate@) before it can be used, but | |
100 | * this will be done automatically by @bench_measure@ if it's | |
101 | * not done by hand earlier. The timer is now owned by the | |
102 | * benchmark state and will be destroyed by @bench_destroy@. | |
103 | */ | |
104 | ||
e63124bc MW |
105 | extern void bench_init(struct bench_state */*b*/, |
106 | struct bench_timer */*tm*/); | |
b64eb60f | 107 | |
67b5031e MW |
108 | /* --- @bench_destroy@ --- * |
109 | * | |
110 | * Arguments: @struct bench_state *b@ = bench state | |
111 | * | |
112 | * Returns: --- | |
113 | * | |
114 | * Use: Destroy the benchmark state, releasing the resources that it | |
115 | * holds. | |
116 | */ | |
117 | ||
e63124bc | 118 | extern void bench_destroy(struct bench_state */*b*/); |
b64eb60f | 119 | |
67b5031e MW |
120 | /* --- @bench_calibrate@ --- * |
121 | * | |
122 | * Arguments: @struct bench_state *b@ = bench state | |
123 | * | |
124 | * Returns: Zero on success, @-1@ if calibration failed. | |
125 | * | |
126 | * Use: Calibrate the benchmark state, so that it can be used to | |
127 | * measure performance reasonably accurately. | |
128 | */ | |
129 | ||
b64eb60f MW |
130 | extern int bench_calibrate(struct bench_state */*b*/); |
131 | ||
67b5031e MW |
132 | /* --- @bench_measure@ --- * |
133 | * | |
134 | * Arguments: @struct bench_timing *t_out@ = where to leave the timing | |
135 | * @struct bench_state *b@ = benchmark state | |
136 | * @double base@ = number of internal units per call | |
137 | * @bench_fn *fn@, @void *ctx@ = benchmark function to run | |
138 | * | |
139 | * Returns: Zero on success, @-1@ if timing failed. | |
140 | * | |
141 | * Use: Measure a function. The function @fn@ is called adaptively | |
142 | * with an iteration count @n@ set so as to run for | |
143 | * approximately @b->target_s@ seconds. | |
144 | * | |
145 | * The result is left in @*t_out@, with @t_out->n@ counting the | |
146 | * final product of the iteration count and @base@ (which might, | |
147 | * e.g., reflect the number of inner iterations the function | |
148 | * performs, or the number of bytes it processes per iteration). | |
149 | */ | |
150 | ||
b64eb60f MW |
151 | extern int bench_measure(struct bench_timing */*t_out*/, |
152 | struct bench_state */*b*/, | |
67b5031e | 153 | double /*base*/, bench_fn */*fn*/, void */*ctx*/); |
b64eb60f MW |
154 | |
155 | /*----- That's all, folks -------------------------------------------------*/ | |
156 | ||
157 | #ifdef __cplusplus | |
158 | } | |
159 | #endif | |
160 | ||
161 | #endif |