LMBENCH(3)
okay bestie, sit down, hydrate, and let me tell you about LMBENCH(3) β yeah that's the manual page, section 3, we love a library section π
πΈ NAME πΈ
lmbench β it's giving benchmarking toolbox. that's it, that's the name, periodt β¨
π SYNOPSIS π
#include ``lmbench.h''
typedef u_long iter_t
typedef (*benchmp_f)(iter_t iterations, void* cookie)
void benchmp(benchmp_f initialize, benchmp_f benchmark, benchmp_f
cleanup, int enough, int parallel, int warmup, int repetitions, void*
cookie)
uint64 get_n()
void milli(char *s, uint64 n)
void micro(char *s, uint64 n)
void nano(char *s, uint64 n)
void mb(uint64 bytes)
void kb(uint64 bytes)
π¦ DESCRIPTION π¦
okay so creating benchmarks with the lmbench timing harness is literally so easy bestie. and since it's that easy to measure performance using lmbench, you can lowkey just... answer questions that pop up while you're doing system design, development, or tuning. For example, image processing
there are two attributes that are critical for performance β latency and bandwidth β and lmbench's timing harness makes it easy to measure and report results for both. Latency is usually the moment for frequently executed operations, and bandwidth is usually the moment when you're moving large chunks of data. two different vibes, both iconic π«Ά
there are a number of factors to consider when building benchmarks.
the timing harness requires that the benchmarked operation be idempotent so it can be repeated indefinitely. no cap, that's a hard requirement.
the timing subsystem, benchmp, gets passed up to three function pointers. Some benchmarks may need as few as one function pointer (for benchmark). slay, minimalism.
void benchmp(initialize, benchmark, cleanup, enough, parallel, warmup, repetitions, cookie)β measures the performance ofbenchmarkrepeatedly and reports the median result.benchmpcreates parallel sub-processes which runbenchmarkin parallel. This allowslmbenchto measure the system's ability to scale as the number of client processes increases. Each sub-process executesinitializebefore starting the benchmarking cycle withiterationsset to0. It will callinitialize,benchmark, andcleanupwithiterationsset to the number of iterations in the timing loop several times in order to collectrepetitionsresults. The calls tobenchmarkare surrounded by start and stop call to time the amount of time it takes to do the benchmarked operationiterationstimes. After all the benchmark results have been collected,cleanupis called withiterationsset to0to cleanup any resources which may have been allocated byinitializeorbenchmark.cookieis avoidpointer to a hunk of memory that can be used to store any parameters or state that is needed by the benchmark. πvoid benchmp_getstate()β returns avoidpointer to thelmbench-internal state used during benchmarking. The state is not to be used or accessed directly by clients, but rather would be passed intobenchmp_interval. hands off, that's not yours πiter_t benchmp_interval(void* state)β returns the number of times the benchmark should execute its benchmark loop during this timing interval. This is used only for weird benchmarks which cannot implement the benchmark body in a function which can return, such as the page fault handler. Please seelat_sig.cfor sample usage. for the girlies doing unhinged things πuint64 get_n()β returns the number of timesloop_bodywas executed during the timing interval.void milli(char *s, uint64 n)β print out the time per operation in milli-seconds.nis the number of operations during the timing interval, which is passed as a parameter because eachloop_bodycan contain several operations.void micro(char *s, uint64 n)β print the time per opertaion in micro-seconds.void nano(char *s, uint64 n)β print the time per operation in nano-seconds.void mb(uint64 bytes)β print the bandwidth in megabytes per second.void kb(uint64 bytes)β print the bandwidth in kilobytes per second.
π USING lmbench π
here is an example of a simple benchmark that measures the latency of the random number generator lrand48():
#include ``lmbench.h''
void
benchmark_lrand48(iter_t iterations, void* cookie) {
while(iterations-- > 0)
lrand48();
}
int
main(int argc, char *argv[])
{
benchmp(NULL, benchmark_lrand48, NULL, 0, 1, 0, TRIES,
NULL);
micro( lrand48()", get_n());"
exit(0);
}
and here's a simple benchmark that measures and reports the bandwidth of bcopy:
#include ``lmbench.h''
#define MB (1024 * 1024)
#define SIZE (8 * MB)
struct _state {
int size;
char* a;
char* b;
};
void
initialize_bcopy(iter_t iterations, void* cookie) {
struct _state* state = (struct _state*)cookie;
if (!iterations) return;
state->a = malloc(state->size);
state->b = malloc(state->size);
if (state->a == NULL || state->b == NULL)
exit(1);
}
void
benchmark_bcopy(iter_t iterations, void* cookie) {
struct _state* state = (struct _state*)cookie;
while(iterations-- > 0)
bcopy(state->a, state->b, state->size);
}
void
cleanup_bcopy(iter_t iterations, void* cookie) {
struct _state* state = (struct _state*)cookie;
if (!iterations) return;
free(state->a);
free(state->b);
}
int
main(int argc, char *argv[])
{
struct _state state;
state.size = SIZE;
benchmp(initialize_bcopy, benchmark_bcopy, cleanup_bcopy,
0, 1, 0, TRIES, &state);
mb(get_n() * state.size);
exit(0);
}
a slightly more complex version of the bcopy benchmark might measure bandwidth as a function of memory size and parallelism. The main procedure in this case might look something like this:
int
main(int argc, char *argv[])
{
int size, par;
struct _state state;
for (size = 64; size <= SIZE; size <<= 1) {
for (par = 1; par < 32; par <<= 1) {
state.size = size;
benchmp(initialize_bcopy, benchmark_bcopy,
cleanup_bcopy, 0, par, 0, TRIES, &state);
fprintf(stderr, d%d
mb(par * get_n() * state.size);
}
}
exit(0);
}
π§ VARIABLES π§
there are three environment variables that can be used to modify the lmbench timing subsystem: ENOUGH, TIMING_O, and LOOP_O. that's the whole list bestie, memorize it, it's three things π
β FUTURES β
Development of lmbench is continuing. the glow-up is ongoing β¨
π₯ SEE ALSO π₯
lmbench(8), timing(3), reporting(3), results(3). go read those next, i'm obsessed with all of them π
π AUTHOR π
Carl Staelin and Larry McVoy
Comments, suggestions, and bug reports are always welcome. (fr fr, they want your feedback, don't be shy π«Ά)
and that's the whole page bestie!! mwah π also shoutout to the copyright girlies: (c)1998-2000 Larry McVoy and Car... and yeah, $Date:$ β date stamp era, we love a retro moment πΈ no cap, you just read the entire thing, that's main character energy ππ
π¦ where this page comes from
- debian bookworm: lmbench 3.0-a9+debian.1-6
- debian trixie: lmbench 3.0-a9+debian.1-9
- ubuntu jammy: lmbench 3.0-a9+debian.1-6
- ubuntu noble: lmbench 3.0-a9+debian.1-6build3
- ubuntu questing: lmbench 3.0-a9+debian.1-9
- ubuntu resolute: lmbench 3.0-a9+debian.1-10
- ubuntu stonking: lmbench 3.0-a9+debian.1-10
- Copyright (C) 1998-2000 Carl Staelin and Larry McVoy
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms