chiark / gitweb /
@@@ bench wip
[mLib] / test / bench.h
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 #ifndef MLIB_DSTR_H
42 #  include "dstr.h"
43 #endif
44
45 /*----- Data structures ---------------------------------------------------*/
46
47 struct bench_time {
48   unsigned f;                           /* flags */
49 #define BTF_TIMEOK 1u                   /*   @s@ ad @ns@ slots are value */
50 #define BTF_CYOK 2u                     /*   @cy@ slot is valid */
51 #define BTF_ANY (BTF_TIMEOK | BTF_CYOK) /*   some part is useful */
52   kludge64 s; uint32 ns;                /* real time, seconds and nanos */
53   kludge64 cy;                          /* count of CPU cycles */
54 };
55
56 struct bench_timing {
57   unsigned f;                           /* flags (@BTF_...@) */
58   double n, t, cy;                      /* count, time, and cycles */
59 };
60
61 struct bench_timer { const struct bench_timerops *ops; };
62
63 struct bench_timerops {
64   void (*describe)(struct bench_timer */*bt*/, dstr */*d*/);
65     /* Write a description of the timer to @d@. */
66
67   void (*now)(struct bench_timer */*bt*/, struct bench_time */*t_out*/);
68     /* Fill in @*t_out@ with the current time. v*/
69
70   void (*destroy)(struct bench_timer */*bt*/);
71     /* Release the timer and any resources it holds. */
72 };
73
74 struct bench_state {
75   struct bench_timer *tm;               /* a timer */
76   double target_s;                      /* target time to run benchmarks */
77   unsigned f;                           /* calibration flags (@BTF_...@) */
78 #define BTF_CLB 0x0100                  /*   tried calibrating */
79   struct { double m, c; } clk, cy;      /* calculated overheads */
80 };
81
82 typedef void bench_fn(unsigned long /*n*/, void */*ctx*/);
83   /* Run the benchmark @n@ times, given a context pointer @ctx@. */
84
85 /*----- Functions provided ------------------------------------------------*/
86
87 /* --- @bench_createtimer@ --- *
88  *
89  * Arguments:   @const char *config@ = user-supplied configuration string
90  *
91  * Returns:     A freshly constructed standard timer object, or null on
92  *              failure.
93  *
94  * Use:         Allocate a timer.  Dispose of it by calling
95  *              @tm->ops->destroy(tm)@ when you're done.
96  *
97  *              Applications should not set configuration strings except as
98  *              established by user action, e.g., from a command-line option,
99  *              environment variable, or configuration file.
100  */
101
102 extern struct bench_timer *bench_createtimer(const char *config);
103
104 /* --- @bench_init@ --- *
105  *
106  * Arguments:   @struct bench_state *b@ = bench state to initialize
107  *              @struct bench_timer *tm@ = timer to attach, or null
108  *
109  * Returns:     Zero on success, %$-1$% on failure.
110  *
111  * Use:         Initialize the benchmark state.  On success, the timer state
112  *              still needs to be calibrated (use @bench_calibrate@) before
113  *              it can be used, but this will be done automatically by
114  *              @bench_measure@ if it's not done by hand earlier.  The timer
115  *              is now owned by the benchmark state and will be destroyed by
116  *              @bench_destroy@.
117  *
118  *              The only reason for failure is if @tm@ was null on entry,
119  *              and automatic construction of a timer failed.  The state is
120  *              safe to discard, but calling @bench_destroy@ is safe too.
121  */
122
123 extern int bench_init(struct bench_state */*b*/, struct bench_timer */*tm*/);
124
125 /* --- @bench_destroy@ --- *
126  *
127  * Arguments:   @struct bench_state *b@ = bench state
128  *
129  * Returns:     ---
130  *
131  * Use:         Destroy the benchmark state, releasing the resources that it
132  *              holds.
133  */
134
135 extern void bench_destroy(struct bench_state */*b*/);
136
137 /* --- @bench_calibrate@ --- *
138  *
139  * Arguments:   @struct bench_state *b@ = bench state
140  *
141  * Returns:     Zero on success, %$-1$% if calibration failed.
142  *
143  * Use:         Calibrate the benchmark state, so that it can be used to
144  *              measure performance reasonably accurately.
145  */
146
147 extern int bench_calibrate(struct bench_state */*b*/);
148
149 /* --- @bench_measure@ --- *
150  *
151  * Arguments:   @struct bench_timing *t_out@ = where to leave the timing
152  *              @struct bench_state *b@ = benchmark state
153  *              @double base@ = number of internal units per call
154  *              @bench_fn *fn@, @void *ctx@ = benchmark function to run
155  *
156  * Returns:     Zero on success, %$-1$% if timing failed.
157  *
158  * Use:         Measure a function.  The function @fn@ is called adaptively
159  *              with an iteration count @n@ set so as to run for
160  *              approximately @b->target_s@ seconds.
161  *
162  *              The result is left in @*t_out@, with @t_out->n@ counting the
163  *              final product of the iteration count and @base@ (which might,
164  *              e.g., reflect the number of inner iterations the function
165  *              performs, or the number of bytes it processes per iteration).
166  */
167
168 extern int bench_measure(struct bench_timing */*t_out*/,
169                          struct bench_state */*b*/,
170                          double /*base*/, bench_fn */*fn*/, void */*ctx*/);
171
172 /*----- That's all, folks -------------------------------------------------*/
173
174 #ifdef __cplusplus
175   }
176 #endif
177
178 #endif