75 lines
2.3 KiB
C
75 lines
2.3 KiB
C
/*
|
|
* Benchmark harness for vlibc (musts/BENCHMARKING.md).
|
|
*
|
|
* Every vlibc component is benchmarked against the software it replaces.
|
|
* This stub times vlibc_version() and is the skeleton that per-component
|
|
* benchmarks build on. Reconfigure with --with-libc=musl or --with-libc=glibc
|
|
* to link the same harness against a reference libc for comparison.
|
|
*
|
|
* This TU is deliberately a HOST-headers-only translation unit: it includes
|
|
* no vlibc header, because vlibc's self-contained
|
|
* <stdarg.h>/<stddef.h>/<limits.h>/<float.h> shadow GCC's internal headers
|
|
* and mixing them with the system <stdio.h>/<time.h> hard-errors. The
|
|
* function under test is reached through the adapter TU
|
|
* bench_vlibc_under.c, which is compiled with vlibc's headers and exposes
|
|
* the call through its own declaration here.
|
|
*/
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
|
|
/* Adapter entry (bench_vlibc_under.c); declared here rather than including
|
|
* <vlibc.h>, which this host-header TU must not do. The adapter also drops
|
|
* vlibc_version()'s __attribute__((const)), so the timed loop really
|
|
* executes the call. */
|
|
const char *
|
|
bench_vlibc_version(void);
|
|
|
|
#define ITERATIONS 100000000ULL
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
volatile const char *version = NULL;
|
|
struct timespec start;
|
|
struct timespec end;
|
|
double whole;
|
|
double frac;
|
|
double seconds;
|
|
|
|
if (clock_gettime(CLOCK_MONOTONIC, &start) != 0)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
for (unsigned long long i = 0; i < ITERATIONS; i++)
|
|
{
|
|
version = bench_vlibc_version();
|
|
}
|
|
|
|
if (clock_gettime(CLOCK_MONOTONIC, &end) != 0)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
whole = (double)(end.tv_sec - start.tv_sec);
|
|
frac = (double)(end.tv_nsec - start.tv_nsec) / 1000000000.0;
|
|
seconds = whole + frac;
|
|
|
|
printf("vlibc_version() x %llu: %.3f s (%.2f ns/call), version=%s\n", ITERATIONS, seconds,
|
|
seconds * 1000000000.0 / ITERATIONS, (const char *)version);
|
|
|
|
/*
|
|
* Explicit flush: this harness is a host program, but its DT_NEEDED order
|
|
* puts libvlibc.so before libc.so.6, so the exit() that runs at process
|
|
* end is vlibc's — which does not flush stdio yet (that hook lands with
|
|
* the stdio todo). Without the flush the buffered result above is lost.
|
|
*/
|
|
fflush(stdout);
|
|
|
|
return 0;
|
|
}
|