Skip to content

Instantly share code, notes, and snippets.

@ncruces
Created July 1, 2025 15:42
Show Gist options
  • Save ncruces/24849719d73ed521fa2dbd510932ecd8 to your computer and use it in GitHub Desktop.
Save ncruces/24849719d73ed521fa2dbd510932ecd8 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define DoNotOptimize(value) \
({ \
typeof(value) v = value; \
asm volatile("" : "+r,m"(v) : : "memory"); \
value; \
})
#define NANOS (int64_t)(1e9)
#define MEGABYTE (1024 * 1024)
static int64_t timespec_to_nsec(const struct timespec a) {
return (int64_t)a.tv_sec * NANOS + a.tv_nsec;
}
void bench_strlen() {
char *buffer = malloc(MEGABYTE);
memset(buffer, 5, MEGABYTE);
buffer[MEGABYTE - 1] = 0;
// Test various lengths.
for (size_t i = 1; i < MEGABYTE; i = i * 3 - 1) {
buffer[i] = 0;
}
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
for (size_t i = 0; i < MEGABYTE;) {
i += 1 + DoNotOptimize(strlen(buffer + i));
}
clock_gettime(CLOCK_MONOTONIC, &end);
int64_t delta = timespec_to_nsec(end) - timespec_to_nsec(start);
printf("strlen: %f MB/s\n", (float)NANOS / (float)delta);
free(buffer);
}
void bench_memchr() {
char *buffer = malloc(MEGABYTE);
memset(buffer, 5, MEGABYTE);
// Test various lengths.
for (size_t i = 1; i < MEGABYTE; i = i * 3 - 1) {
buffer[i] = 7;
}
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
for (char *ptr = buffer; ptr < buffer + MEGABYTE; ptr++) {
ptrdiff_t avail = (buffer + MEGABYTE) - ptr;
ptr = DoNotOptimize(memchr(ptr, 7, avail));
if (ptr == NULL) break;
}
clock_gettime(CLOCK_MONOTONIC, &end);
int64_t delta = timespec_to_nsec(end) - timespec_to_nsec(start);
printf("memchr: %f MB/s\n", (float)NANOS / (float)delta);
free(buffer);
}
int main(void) {
for (int i = 0; i < 10; i++) {
bench_strlen();
bench_memchr();
}
return 0;
}
@abrown
Copy link

abrown commented Jul 7, 2025

So I can replicate: what commands do you use to compile and run this?

@ncruces
Copy link
Author

ncruces commented Jul 8, 2025

I just dropped it next to the unit tests in test/src/misc/.

Given the infra, just printing some output fails the test, but that was good enough “for now”. Then go look at the failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment