@@@ fltfmt mess
[mLib] / test / tvec-bench.h
1 /* -*-c-*-
2 *
3 * Test-vector framework benchmark extension
4 *
5 * (c) 2024 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_TVEC_BENCH_H
29 #define MLIB_TVEC_BENCH_H
30
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #ifndef MLIB_BENCH_H
38 # include "bench.h"
39 #endif
40
41 #ifndef MLIB_CONTROL_H
42 # include "control.h"
43 #endif
44
45 #ifndef MLIB_GPRINTF_H
46 # include "gprintf.h"
47 #endif
48
49 #ifndef MLIB_TVEC_H
50 # include "tvec.h"
51 #endif
52
53 #ifndef MLIB_TVEC_OUTPUT_H
54 # include "tvec-output.h"
55 #endif
56
57 /*----- Test environment --------------------------------------------------*/
58
59 struct tvec_benchenv {
60 /* Benchmark environment definition. */
61
62 struct tvec_env _env; /* benchmarking is an environment */
63 struct bench_state **bst; /* benchmark state anchor or null */
64 unsigned long niter; /* iterations done per unit */
65 int riter, rbuf; /* iterations and buffer registers */
66 const struct tvec_env *env; /* subordinate environment */
67 };
68
69 struct tvec_benchctx {
70 /* Benchmark environment context; private. */
71
72 const struct tvec_benchenv *be; /* environment configuration */
73 struct bench_state *bst; /* benchmark state */
74 double dflt_target; /* default time in seconds */
75 unsigned f; /* flags */
76 #define TVBF_SETTRG 1u /* set `@target' */
77 #define TVBF_SETMASK (TVBF_SETTRG)) /* mask of @TVBF_SET...@ */
78 void *subctx; /* subordinate environment context */
79 };
80
81 /* --- Environment implementation --- *
82 *
83 * The following special variables are supported.
84 *
85 * * %|@target|% is the (approximate) number of seconds to run the
86 * benchmark.
87 *
88 * Unrecognized variables are passed to the subordinate environment, if there
89 * is one. Other events are passed through to the subordinate environment.
90 */
91
92 extern tvec_envsetupfn tvec_benchsetup;
93 extern tvec_envfindvarfn tvec_benchfindvar;
94 extern tvec_envbeforefn tvec_benchbefore;
95 extern tvec_envrunfn tvec_benchrun;
96 extern tvec_envafterfn tvec_benchafter;
97 extern tvec_envteardownfn tvec_benchteardown;
98
99 #define TVEC_BENCHENV \
100 { sizeof(struct tvec_benchctx), \
101 tvec_benchsetup, \
102 tvec_benchfindvar, \
103 tvec_benchbefore, \
104 tvec_benchrun, \
105 tvec_benchafter, \
106 tvec_benchteardown }
107 #define TVEC_BENCHINIT TVEC_BENCHENV, &tvec_benchstate
108
109 /*----- Benchmark output extension ----------------------------------------*/
110
111 #define TVEC_BENCHOUTEXT "tvec-bench"
112
113 struct tvec_benchoutops {
114 /* Output extension for benchmarking. The name for this extension is
115 * %|tvec-bench|%.
116 */
117
118 void (*bbench)(struct tvec_output */*o*/,
119 const char */*desc*/, unsigned /*unit*/);
120 /* Begin a benchmark. If the description @desc@ is null -- which it will
121 * be unless we're doing adhoc testing, then the output driver should
122 * label its benchmark output, e.g., by dumping the values of the input
123 * registers marked @TVRF_ID@. The @unit@ is one of the @BTU_...@
124 * constants explaining what sort of thing is being measured.
125 */
126
127 void (*ebench)(struct tvec_output */*o*/,
128 const char */*desc*/, unsigned /*unit*/,
129 const struct bench_timing */*t*/);
130 /* End a benchmark. The @unit@ argument is as for @bbench@. If @tm@ is
131 * zero then the measurement failed; otherwise @tm->n@ counts total
132 * number of things (operations or bytes, as indicated by @unit@)
133 * processed in the indicated time.
134 */
135 };
136
137 extern const struct tvec_benchoutops tvec_benchoutputfallback;
138 /* Fallback operations for benchmark output. The @o@ argument is a pointer
139 * to a @struct tvec_fallbackoutput@.
140 */
141
142 /*----- Global variables --------------------------------------------------*/
143
144 extern struct bench_state *tvec_benchstate; /* default benchmark state */
145
146 /*----- Functions provided ------------------------------------------------*/
147
148 /* --- @TVEC_BENCHMARK@, @TVEC_BENCHMARK_TAG@ --- *
149 *
150 * Arguments: @const char *desc@ = a description of the benchmark
151 * @struct bench_state **bst_inout@ = benchmark state (updated)
152 * @unsigned unit@ = unit being measured (@BTU_...@ code)
153 * @double base@ = number of units per external iteration
154 *
155 * Returns: ---
156 *
157 * Use:
158 */
159
160 #define TVEC_BENCHMARK_DECLS \
161 struct tvec_state *_tvbench_tv; \
162 struct tvec_fallbackoutput _tvbench_fo; \
163 const struct tvec_benchoutops *_tvbench_bo; \
164 struct tvec_output *_tvbench_o; \
165 const char *_tvbench_desc; \
166 unsigned _tvbench_unit; \
167 struct bench_timing _tvbench_tm; \
168 int _tvbench_rc; \
169 BENCH_MEASURE_DECLS
170
171 #define TVEC_BENCHMARK_TAG(tag, desc, tv, bst, unit, base) \
172 MC_BEFORE(tag##__tvbench_setup, { \
173 _tvbench_tv = (tv); \
174 _tvbench_bo = tvec_outputext(_tvbench_tv, &_tvbench_o, &_tvbench_fo, \
175 TVEC_BENCHOUTEXT, \
176 &tvec_benchoutputfallback); \
177 _tvbench_desc = (desc); _tvbench_unit = (unit); \
178 TVEC_BEGINTEST(_tvbench_tv); \
179 _tvbench_bo->bbench(_tvbench_o, _tvbench_desc, _tvbench_unit); \
180 }) \
181 MC_AFTER(tag##__tvbench_report, { \
182 _tvbench_bo->ebench(_tvbench_o, _tvbench_desc, _tvbench_unit, \
183 _tvbench_rc ? 0 : &_tvbench_tm); \
184 tvec_endtest(_tvbench_tv); \
185 }) \
186 BENCH_MEASURE_TAG(tag##__tvbench_measure, (bst), \
187 _tvbench_rc, &_tvbench_tm, (base))
188
189 #define TVEC_BENCHMARK(desc, tv, bst, unit, base) \
190 TVEC_BENCHMARK_TAG(tvec_bench, desc, tv, bst, unit, base)
191
192 /* --- @tvec_benchprep@ --- *
193 *
194 * Arguments: @struct tvec_state *tv@ = test vector state
195 * @struct bench_state **bst_inout@ = benchmark state (updated)
196 * @unsigned f@ = calibration flags
197 *
198 * Returns: Zero on success, %$-1$% on failure.
199 *
200 * Use: If @*bst_inout@ is null then allocate and initialize a fresh
201 * benchmark state with a default timer, and @*bst_inout@ is
202 * updated to point to the fresh state. The storage for the
203 * state was allocated using the test vector state's arena.
204 *
205 * If the benchmark state hasn't been calibrated, then this is
206 * done, passing @f@ to @bench_calibrate@.
207 *
208 * On failure, the test group is skipped, reporting a suitable
209 * message, and %$-1$% is returned. If a fresh benchmark state
210 * was allocated, but calibration failed, the state is
211 * %%\emph{not}%% released.
212 */
213
214 extern int tvec_benchprep(struct tvec_state */*tv*/,
215 struct bench_state **/*bst_inout*/,
216 unsigned /*f*/);
217
218 /* --- @tvec_benchreport@ --- *
219 *
220 * Arguments: @const struct gprintf_ops *gops@ = print operations
221 * @void *go@ = print destination
222 * @unsigned unit@ = the unit being measured (@BTU_...@)
223 * @unsigned style@ = output style (@TVSF_...@)
224 * @const struct bench_timing *t@ = the benchmark result
225 *
226 * Returns: ---
227 *
228 * Use: Formats a report about the benchmark performance. This
229 * function is intended to be called on by an output @ebench@
230 * function.
231 */
232
233 extern void tvec_benchreport
234 (const struct gprintf_ops */*gops*/, void */*go*/,
235 unsigned /*unit*/, unsigned /*style*/, const struct bench_timing */*tm*/);
236
237 /*----- That's all, folks -------------------------------------------------*/
238
239 #ifdef __cplusplus
240 }
241 #endif
242
243 #endif