Commit | Line | Data |
---|---|---|
02378956 | 1 | ;;;; benchmark-suite/lib.scm --- generic support for benchmarking |
7e822b32 | 2 | ;;;; Copyright (C) 2002, 2006, 2011, 2012 Free Software Foundation, Inc. |
02378956 | 3 | ;;;; |
53befeb7 NJ |
4 | ;;;; This program is free software; you can redistribute it and/or |
5 | ;;;; modify it under the terms of the GNU Lesser General Public | |
6 | ;;;; License as published by the Free Software Foundation; either | |
7 | ;;;; version 3, or (at your option) any later version. | |
02378956 DH |
8 | ;;;; |
9 | ;;;; This program is distributed in the hope that it will be useful, | |
10 | ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
53befeb7 | 12 | ;;;; GNU Lesser General Public License for more details. |
02378956 | 13 | ;;;; |
53befeb7 NJ |
14 | ;;;; You should have received a copy of the GNU Lesser General Public |
15 | ;;;; License along with this software; see the file COPYING.LESSER. | |
16 | ;;;; If not, write to the Free Software Foundation, Inc., 51 Franklin | |
17 | ;;;; Street, Fifth Floor, Boston, MA 02110-1301 USA | |
02378956 DH |
18 | |
19 | (define-module (benchmark-suite lib) | |
7e822b32 AW |
20 | #:use-module (srfi srfi-9) |
21 | #:export (;; Controlling the execution. | |
22 | iteration-factor | |
23 | scale-iterations | |
24 | ||
25 | ;; Running benchmarks. | |
26 | run-benchmark | |
27 | benchmark | |
28 | ||
29 | ;; Naming groups of benchmarks in a regular fashion. | |
30 | with-benchmark-prefix with-benchmark-prefix* | |
31 | current-benchmark-prefix format-benchmark-name | |
32 | ||
33 | ;; <benchmark-result> accessors | |
34 | benchmark-result:name | |
35 | benchmark-result:iterations | |
36 | benchmark-result:real-time | |
37 | benchmark-result:run-time | |
38 | benchmark-result:gc-time | |
39 | benchmark-result:core-time | |
40 | ||
41 | ;; Reporting results in various ways. | |
42 | report current-reporter | |
43 | register-reporter unregister-reporter reporter-registered? | |
44 | make-log-reporter | |
45 | full-reporter | |
46 | user-reporter)) | |
02378956 | 47 | |
bde9d30b DH |
48 | |
49 | ;;;; If you're using Emacs's Scheme mode: | |
50 | ;;;; (put 'with-benchmark-prefix 'scheme-indent-function 1) | |
51 | ;;;; (put 'benchmark 'scheme-indent-function 1) | |
52 | ||
53 | \f | |
54 | ;;;; CORE FUNCTIONS | |
55 | ;;;; | |
56 | ;;;; The function (run-benchmark name iterations thunk) is the heart of the | |
57 | ;;;; benchmarking environment. The first parameter NAME is a unique name for | |
58 | ;;;; the benchmark to be executed (for an explanation of this parameter see | |
59 | ;;;; below under ;;;; NAMES. The second parameter ITERATIONS is a positive | |
60 | ;;;; integer value that indicates how often the thunk shall be executed (for | |
61 | ;;;; an explanation of how iteration counts should be used, see below under | |
62 | ;;;; ;;;; ITERATION COUNTS). For example: | |
63 | ;;;; | |
64 | ;;;; (run-benchmark "small integer addition" 100000 (lambda () (+ 1 1))) | |
65 | ;;;; | |
66 | ;;;; This will run the function (lambda () (+ 1 1)) a 100000 times (the | |
67 | ;;;; iteration count can, however be scaled. See below for details). Some | |
68 | ;;;; different time data for running the thunk for the given number of | |
69 | ;;;; iterations is measured and reported. | |
70 | ;;;; | |
71 | ;;;; Convenience macro | |
72 | ;;;; | |
73 | ;;;; * (benchmark name iterations body) is a short form for | |
74 | ;;;; (run-benchmark name iterations (lambda () body)) | |
75 | ||
76 | \f | |
77 | ;;;; NAMES | |
78 | ;;;; | |
79 | ;;;; Every benchmark in the benchmark suite has a unique name to be able to | |
80 | ;;;; compare the results of individual benchmarks across several runs of the | |
81 | ;;;; benchmark suite. | |
82 | ;;;; | |
83 | ;;;; A benchmark name is a list of printable objects. For example: | |
84 | ;;;; ("ports.scm" "file" "read and write back list of strings") | |
85 | ;;;; ("ports.scm" "pipe" "read") | |
86 | ;;;; | |
87 | ;;;; Benchmark names may contain arbitrary objects, but they always have | |
88 | ;;;; the following properties: | |
89 | ;;;; - Benchmark names can be compared with EQUAL?. | |
90 | ;;;; - Benchmark names can be reliably stored and retrieved with the standard | |
91 | ;;;; WRITE and READ procedures; doing so preserves their identity. | |
92 | ;;;; | |
93 | ;;;; For example: | |
94 | ;;;; | |
95 | ;;;; (benchmark "simple addition" 100000 (+ 2 2)) | |
96 | ;;;; | |
97 | ;;;; In that case, the benchmark name is the list ("simple addition"). | |
98 | ;;;; | |
99 | ;;;; The WITH-BENCHMARK-PREFIX syntax and WITH-BENCHMARK-PREFIX* procedure | |
100 | ;;;; establish a prefix for the names of all benchmarks whose results are | |
101 | ;;;; reported within their dynamic scope. For example: | |
102 | ;;;; | |
103 | ;;;; (begin | |
104 | ;;;; (with-benchmark-prefix "basic arithmetic" | |
105 | ;;;; (benchmark "addition" 100000 (+ 2 2)) | |
106 | ;;;; (benchmark "subtraction" 100000 (- 4 2))) | |
107 | ;;;; (benchmark "multiplication" 100000 (* 2 2)))) | |
108 | ;;;; | |
109 | ;;;; In that example, the three benchmark names are: | |
110 | ;;;; ("basic arithmetic" "addition"), | |
111 | ;;;; ("basic arithmetic" "subtraction"), and | |
112 | ;;;; ("multiplication"). | |
113 | ;;;; | |
114 | ;;;; WITH-BENCHMARK-PREFIX can be nested. Each WITH-BENCHMARK-PREFIX | |
679cceed | 115 | ;;;; appends a new element to the current prefix: |
bde9d30b DH |
116 | ;;;; |
117 | ;;;; (with-benchmark-prefix "arithmetic" | |
118 | ;;;; (with-benchmark-prefix "addition" | |
119 | ;;;; (benchmark "integer" 100000 (+ 2 2)) | |
120 | ;;;; (benchmark "complex" 100000 (+ 2+3i 4+5i))) | |
121 | ;;;; (with-benchmark-prefix "subtraction" | |
122 | ;;;; (benchmark "integer" 100000 (- 2 2)) | |
123 | ;;;; (benchmark "complex" 100000 (- 2+3i 1+2i)))) | |
124 | ;;;; | |
125 | ;;;; The four benchmark names here are: | |
126 | ;;;; ("arithmetic" "addition" "integer") | |
127 | ;;;; ("arithmetic" "addition" "complex") | |
128 | ;;;; ("arithmetic" "subtraction" "integer") | |
129 | ;;;; ("arithmetic" "subtraction" "complex") | |
130 | ;;;; | |
131 | ;;;; To print a name for a human reader, we DISPLAY its elements, | |
132 | ;;;; separated by ": ". So, the last set of benchmark names would be | |
133 | ;;;; reported as: | |
134 | ;;;; | |
135 | ;;;; arithmetic: addition: integer | |
136 | ;;;; arithmetic: addition: complex | |
137 | ;;;; arithmetic: subtraction: integer | |
138 | ;;;; arithmetic: subtraction: complex | |
139 | ;;;; | |
140 | ;;;; The Guile benchmarks use with-benchmark-prefix to include the name of | |
141 | ;;;; the source file containing the benchmark in the benchmark name, to | |
142 | ;;;; provide each file with its own namespace. | |
143 | ||
144 | \f | |
145 | ;;;; ITERATION COUNTS | |
146 | ;;;; | |
147 | ;;;; Every benchmark has to be given an iteration count that indicates how | |
148 | ;;;; often it should be executed. The reason is, that in most cases a single | |
149 | ;;;; execution of the benchmark code would not deliver usable timing results: | |
150 | ;;;; The resolution of the system time is not arbitrarily fine. Thus, some | |
151 | ;;;; benchmarks would be executed too quickly to be measured at all. A rule | |
42ad901d | 152 | ;;;; of thumb is, that the longer a benchmark runs, the more exact is the |
bde9d30b DH |
153 | ;;;; information about the execution time. |
154 | ;;;; | |
155 | ;;;; However, execution time depends on several influences: First, the | |
156 | ;;;; machine you are running the benchmark on. Second, the compiler you use. | |
157 | ;;;; Third, which compiler options you use. Fourth, which version of guile | |
158 | ;;;; you are using. Fifth, which guile options you are using (for example if | |
159 | ;;;; you are using the debugging evaluator or not). There are even more | |
160 | ;;;; influences. | |
161 | ;;;; | |
162 | ;;;; For this reason, the same number of iterations for a single benchmark may | |
163 | ;;;; lead to completely different execution times in different | |
164 | ;;;; constellations. For someone working on a slow machine, the default | |
165 | ;;;; execution counts may lead to an inacceptable execution time of the | |
166 | ;;;; benchmark suite. For someone on a very fast machine, however, it may be | |
167 | ;;;; desireable to increase the number of iterations in order to increase the | |
168 | ;;;; accuracy of the time data. | |
169 | ;;;; | |
170 | ;;;; For this reason, the benchmark suite allows to scale the number of | |
171 | ;;;; executions by a global factor, stored in the exported variable | |
172 | ;;;; iteration-factor. The default for iteration-factor is 1. A number of 2 | |
173 | ;;;; means, that all benchmarks are executed twice as often, which will also | |
174 | ;;;; roughly double the execution time for the benchmark suite. Similarly, if | |
175 | ;;;; iteration-factor holds a value of 0.5, only about half the execution time | |
176 | ;;;; will be required. | |
177 | ;;;; | |
178 | ;;;; It is probably a good idea to choose the iteration count for each | |
179 | ;;;; benchmark such that all benchmarks will take about the same time, for | |
180 | ;;;; example one second. To achieve this, the benchmark suite holds an empty | |
181 | ;;;; benchmark in the file 0-reference.bm named "reference benchmark for | |
182 | ;;;; iteration counts". It's iteration count is calibrated to make the | |
183 | ;;;; benchmark run about one second on Dirk's laptop :-) If you are adding | |
184 | ;;;; benchmarks to the suite, it would be nice if you could calibrate the | |
185 | ;;;; number of iterations such that each of your added benchmarks takes about | |
186 | ;;;; as long to run as the reference benchmark. But: Don't be too accurate | |
187 | ;;;; to figure out the correct iteration count. | |
188 | ||
189 | \f | |
190 | ;;;; REPORTERS | |
191 | ;;;; | |
192 | ;;;; A reporter is a function which we apply to each benchmark outcome. | |
193 | ;;;; Reporters can log results, print interesting results to the standard | |
194 | ;;;; output, collect statistics, etc. | |
195 | ;;;; | |
196 | ;;;; A reporter function takes the following arguments: NAME ITERATIONS | |
197 | ;;;; BEFORE AFTER GC-TIME. The argument NAME holds the name of the benchmark, | |
198 | ;;;; ITERATIONS holds the actual number of iterations that were performed. | |
199 | ;;;; BEFORE holds the result of the function (times) at the very beginning of | |
200 | ;;;; the excution of the benchmark, AFTER holds the result of the function | |
201 | ;;;; (times) after the execution of the benchmark. GC-TIME, finally, holds | |
202 | ;;;; the difference of calls to (gc-run-time) before and after the execution | |
203 | ;;;; of the benchmark. | |
204 | ;;;; | |
205 | ;;;; This library provides some standard reporters for logging results | |
206 | ;;;; to a file, reporting interesting results to the user, (FIXME: and | |
207 | ;;;; collecting totals). | |
208 | ;;;; | |
209 | ;;;; You can use the REGISTER-REPORTER function and friends to add whatever | |
210 | ;;;; reporting functions you like. See under ;;;; TIMING DATA to see how the | |
211 | ;;;; library helps you to extract relevant timing information from the values | |
212 | ;;;; ITERATIONS, BEFORE, AFTER and GC-TIME. If you don't register any | |
213 | ;;;; reporters, the library uses USER-REPORTER, which writes the most | |
214 | ;;;; interesting results to the standard output. | |
215 | ||
216 | \f | |
217 | ;;;; TIME CALCULATION | |
218 | ;;;; | |
7e822b32 AW |
219 | ;;;; The library uses the guile functions `get-internal-run-time', |
220 | ;;;; `get-internal-real-time', and `gc-run-time' to determine the | |
221 | ;;;; execution time for a single benchmark. Based on these functions, | |
222 | ;;;; Guile makes a <benchmark-result>, a record containing the elapsed | |
223 | ;;;; run time, real time, gc time, and possibly other metrics. These | |
224 | ;;;; times include the time needed to executed the benchmark code | |
225 | ;;;; itself, but also the surrounding code that implements the loop to | |
226 | ;;;; run the benchmark code for the given number of times. This is | |
227 | ;;;; undesirable, since one would prefer to only get the timing data for | |
228 | ;;;; the benchmarking code. | |
bde9d30b DH |
229 | ;;;; |
230 | ;;;; To cope with this, the benchmarking framework uses a trick: During | |
7e822b32 AW |
231 | ;;;; initialization of the library, the time for executing an empty |
232 | ;;;; benchmark is measured and stored. This is an estimate for the time | |
233 | ;;;; needed by the benchmarking framework itself. For later benchmarks, | |
234 | ;;;; this time can then be subtracted from the measured execution times. | |
235 | ;;;; Note that for very short benchmarks, this may result in a negative | |
236 | ;;;; number. | |
237 | ;;;; | |
238 | ;;;; The benchmarking framework provides the following accessors for | |
239 | ;;;; <benchmark-result> values. Note that all time values are in | |
240 | ;;;; internal time units; divide by internal-time-units-per-second to | |
241 | ;;;; get seconds. | |
242 | ;;;; | |
243 | ;;;; benchmark-result:name : Return the name of the benchmark. | |
244 | ;;;; | |
245 | ;;;; benchmark-result:iterations : Return the number of iterations that | |
246 | ;;;; this benchmark ran for. | |
247 | ;;;; | |
248 | ;;;; benchmark-result:real-time : Return the clock time elapsed while | |
249 | ;;;; this benchmark executed. | |
250 | ;;;; | |
251 | ;;;; benchmark-result:run-time : Return the CPU time elapsed while this | |
252 | ;;;; benchmark executed, both in user and kernel space. | |
253 | ;;;; | |
254 | ;;;; benchmark-result:gc-time : Return the approximate amount of time | |
255 | ;;;; spent in garbage collection while this benchmark executed, both | |
256 | ;;;; in user and kernel space. | |
257 | ;;;; | |
258 | ;;;; benchmark-result:core-time : Like benchmark-result:run-time, but | |
259 | ;;;; also estimates the time spent by the framework for the number | |
260 | ;;;; of iterations, and subtracts off that time from the result. | |
261 | ;;;; | |
262 | ||
263 | ;;;; This module is used when benchmarking different Guiles, and so it | |
264 | ;;;; should run on all the Guiles of interest. Currently this set | |
265 | ;;;; includes Guile 1.8, so be careful with introducing features that | |
266 | ;;;; only Guile 2.0 supports. | |
bde9d30b DH |
267 | |
268 | \f | |
02378956 DH |
269 | ;;;; MISCELLANEOUS |
270 | ;;;; | |
271 | ||
7e822b32 AW |
272 | (define-record-type <benchmark-result> |
273 | (make-benchmark-result name iterations real-time run-time gc-time) | |
274 | benchmark-result? | |
275 | (name benchmark-result:name) | |
276 | (iterations benchmark-result:iterations) | |
277 | (real-time benchmark-result:real-time) | |
278 | (run-time benchmark-result:run-time) | |
279 | (gc-time benchmark-result:gc-time)) | |
280 | ||
36ffdf0a | 281 | ;;; Perform a division and convert the result to inexact. |
7e822b32 AW |
282 | (define (->seconds time) |
283 | (/ time 1.0 internal-time-units-per-second)) | |
36ffdf0a | 284 | |
02378956 DH |
285 | ;;; Scale the number of iterations according to the given scaling factor. |
286 | (define iteration-factor 1) | |
287 | (define (scale-iterations iterations) | |
288 | (let* ((i (inexact->exact (round (* iterations iteration-factor))))) | |
289 | (if (< i 1) 1 i))) | |
290 | ||
7e822b32 AW |
291 | ;;; Parameters. |
292 | (cond-expand | |
293 | (srfi-39 #t) | |
294 | (else (use-modules (srfi srfi-39)))) | |
36ffdf0a | 295 | |
02378956 DH |
296 | ;;;; CORE FUNCTIONS |
297 | ;;;; | |
298 | ||
299 | ;;; The central routine for executing benchmarks. | |
300 | ;;; The idea is taken from Greg, the GNUstep regression test environment. | |
7e822b32 AW |
301 | (define benchmark-running? (make-parameter #f)) |
302 | (define (run-benchmark name iterations thunk) | |
303 | (if (benchmark-running?) | |
304 | (error "Nested calls to run-benchmark are not permitted.")) | |
305 | (if (not (and (integer? iterations) (exact? iterations))) | |
306 | (error "Expected exact integral number of iterations")) | |
307 | (parameterize ((benchmark-running? #t)) | |
308 | ;; Warm up the benchmark first. This will resolve any toplevel-ref | |
309 | ;; forms. | |
310 | (thunk) | |
311 | (gc) | |
312 | (let* ((before-gc-time (gc-run-time)) | |
313 | (before-real-time (get-internal-real-time)) | |
314 | (before-run-time (get-internal-run-time))) | |
315 | (do ((i iterations (1- i))) | |
316 | ((zero? i)) | |
317 | (thunk)) | |
318 | (let ((after-run-time (get-internal-run-time)) | |
319 | (after-real-time (get-internal-real-time)) | |
320 | (after-gc-time (gc-run-time))) | |
321 | (report (make-benchmark-result (full-name name) iterations | |
322 | (- after-real-time before-real-time) | |
323 | (- after-run-time before-run-time) | |
324 | (- after-gc-time before-gc-time))))))) | |
02378956 DH |
325 | |
326 | ;;; A short form for benchmarks. | |
7e822b32 AW |
327 | (cond-expand |
328 | (guile-2 | |
329 | (define-syntax-rule (benchmark name iterations body body* ...) | |
330 | (run-benchmark name iterations (lambda () body body* ...)))) | |
331 | (else | |
332 | (defmacro benchmark (name iterations body . rest) | |
333 | `(run-benchmark ,name ,iterations (lambda () ,body ,@rest))))) | |
02378956 DH |
334 | |
335 | \f | |
336 | ;;;; BENCHMARK NAMES | |
337 | ;;;; | |
338 | ||
339 | ;;;; Turn a benchmark name into a nice human-readable string. | |
340 | (define (format-benchmark-name name) | |
7e822b32 | 341 | (string-join name ": ")) |
02378956 DH |
342 | |
343 | ;;;; For a given benchmark-name, deliver the full name including all prefixes. | |
344 | (define (full-name name) | |
345 | (append (current-benchmark-prefix) (list name))) | |
346 | ||
7e822b32 AW |
347 | ;;; A parameter containing the current benchmark prefix, as a list. |
348 | (define current-benchmark-prefix | |
349 | (make-parameter '())) | |
02378956 DH |
350 | |
351 | ;;; Postpend PREFIX to the current name prefix while evaluting THUNK. | |
352 | ;;; The name prefix is only changed within the dynamic scope of the | |
353 | ;;; call to with-benchmark-prefix*. Return the value returned by THUNK. | |
354 | (define (with-benchmark-prefix* prefix thunk) | |
7e822b32 | 355 | (parameterize ((current-benchmark-prefix (full-name prefix))) |
02378956 DH |
356 | (thunk))) |
357 | ||
358 | ;;; (with-benchmark-prefix PREFIX BODY ...) | |
359 | ;;; Postpend PREFIX to the current name prefix while evaluating BODY ... | |
360 | ;;; The name prefix is only changed within the dynamic scope of the | |
361 | ;;; with-benchmark-prefix expression. Return the value returned by the last | |
362 | ;;; BODY expression. | |
7e822b32 AW |
363 | (cond-expand |
364 | (guile-2 | |
365 | (define-syntax-rule (with-benchmark-prefix prefix body body* ...) | |
366 | (with-benchmark-prefix* prefix (lambda () body body* ...)))) | |
367 | (else | |
368 | (defmacro with-benchmark-prefix (prefix . body) | |
369 | `(with-benchmark-prefix* ,prefix (lambda () ,@body))))) | |
02378956 DH |
370 | |
371 | \f | |
7e822b32 | 372 | ;;;; Benchmark results |
02378956 DH |
373 | ;;;; |
374 | ||
7e822b32 | 375 | (define *calibration-result* |
02378956 DH |
376 | "<will be set during initialization>") |
377 | ||
7e822b32 AW |
378 | (define (benchmark-overhead iterations accessor) |
379 | (* (/ iterations 1.0 (benchmark-result:iterations *calibration-result*)) | |
380 | (accessor *calibration-result*))) | |
02378956 | 381 | |
7e822b32 AW |
382 | (define (benchmark-result:core-time result) |
383 | (- (benchmark-result:run-time result) | |
384 | (benchmark-overhead (benchmark-result:iterations result) | |
385 | benchmark-result:run-time))) | |
02378956 DH |
386 | |
387 | \f | |
388 | ;;;; REPORTERS | |
389 | ;;;; | |
390 | ||
7e822b32 AW |
391 | ;;; The global set of reporters. |
392 | (define report-hook (make-hook 1)) | |
393 | ||
394 | (define (default-reporter result) | |
395 | (if (hook-empty? report-hook) | |
396 | (user-reporter result) | |
397 | (run-hook report-hook result))) | |
02378956 | 398 | |
7e822b32 AW |
399 | (define current-reporter |
400 | (make-parameter default-reporter)) | |
02378956 | 401 | |
02378956 | 402 | (define (register-reporter reporter) |
7e822b32 | 403 | (add-hook! report-hook reporter)) |
02378956 | 404 | |
02378956 | 405 | (define (unregister-reporter reporter) |
7e822b32 | 406 | (remove-hook! report-hook reporter)) |
02378956 DH |
407 | |
408 | ;;; Return true iff REPORTER is in the current set of reporter functions. | |
409 | (define (reporter-registered? reporter) | |
7e822b32 | 410 | (if (memq reporter (hook->list report-hook)) #t #f)) |
02378956 DH |
411 | |
412 | ;;; Send RESULT to all currently registered reporter functions. | |
7e822b32 AW |
413 | (define (report result) |
414 | ((current-reporter) result)) | |
02378956 DH |
415 | |
416 | \f | |
417 | ;;;; Some useful standard reporters: | |
8f28ea31 | 418 | ;;;; Log reporters write all benchmark results to a given log file. |
02378956 DH |
419 | ;;;; Full reporters write all benchmark results to the standard output. |
420 | ;;;; User reporters write some interesting results to the standard output. | |
421 | ||
422 | ;;; Display a single benchmark result to the given port | |
7e822b32 AW |
423 | (define (print-result port result) |
424 | (let ((name (format-benchmark-name (benchmark-result:name result))) | |
425 | (iterations (benchmark-result:iterations result)) | |
426 | (real-time (benchmark-result:real-time result)) | |
427 | (run-time (benchmark-result:run-time result)) | |
428 | (gc-time (benchmark-result:gc-time result)) | |
429 | (core-time (benchmark-result:core-time result))) | |
02378956 | 430 | (write (list name iterations |
7e822b32 AW |
431 | 'total (->seconds real-time) |
432 | 'user (->seconds run-time) | |
433 | 'system 0 | |
434 | 'frame (->seconds (- run-time core-time)) | |
435 | 'benchmark (->seconds core-time) | |
436 | 'user/interp (->seconds (- run-time gc-time)) | |
437 | 'bench/interp (->seconds (- core-time gc-time)) | |
438 | 'gc (->seconds gc-time)) | |
02378956 DH |
439 | port) |
440 | (newline port))) | |
441 | ||
442 | ;;; Return a reporter procedure which prints all results to the file | |
443 | ;;; FILE, in human-readable form. FILE may be a filename, or a port. | |
444 | (define (make-log-reporter file) | |
445 | (let ((port (if (output-port? file) file | |
446 | (open-output-file file)))) | |
7e822b32 AW |
447 | (lambda (result) |
448 | (print-result port result) | |
02378956 DH |
449 | (force-output port)))) |
450 | ||
451 | ;;; A reporter that reports all results to the user. | |
7e822b32 AW |
452 | (define (full-reporter result) |
453 | (print-result (current-output-port) result)) | |
02378956 DH |
454 | |
455 | ;;; Display interesting results of a single benchmark to the given port | |
7e822b32 AW |
456 | (define (print-user-result port result) |
457 | (let ((name (format-benchmark-name (benchmark-result:name result))) | |
458 | (iterations (benchmark-result:iterations result)) | |
459 | (real-time (benchmark-result:real-time result)) | |
460 | (run-time (benchmark-result:run-time result)) | |
461 | (gc-time (benchmark-result:gc-time result)) | |
462 | (core-time (benchmark-result:core-time result))) | |
463 | (write (list name iterations | |
464 | 'real (->seconds real-time) | |
465 | 'real/iteration (->seconds (/ real-time iterations)) | |
466 | 'run/iteration (->seconds (/ run-time iterations)) | |
467 | 'core/iteration (->seconds (/ core-time iterations)) | |
468 | 'gc (->seconds gc-time)) | |
02378956 DH |
469 | port) |
470 | (newline port))) | |
471 | ||
472 | ;;; A reporter that reports interesting results to the user. | |
7e822b32 AW |
473 | (define (user-reporter result) |
474 | (print-user-result (current-output-port) result)) | |
02378956 DH |
475 | |
476 | \f | |
477 | ;;;; Initialize the benchmarking system: | |
478 | ;;;; | |
479 | ||
7e822b32 AW |
480 | (define (calibrate-benchmark-framework) |
481 | (display ";; running guile version ") | |
482 | (display (version)) | |
483 | (newline) | |
484 | (display ";; calibrating the benchmarking framework...") | |
485 | (newline) | |
486 | (parameterize ((current-reporter | |
487 | (lambda (result) | |
488 | (set! *calibration-result* result) | |
489 | (display ";; calibration: ") | |
490 | (print-user-result (current-output-port) result)))) | |
491 | (benchmark "empty initialization benchmark" 10000000 #t))) | |
492 | ||
493 | (calibrate-benchmark-framework) |