chiark / gitweb /
@@@ fltfmt wip
[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