Skip to content

Instantly share code, notes, and snippets.

@tlively
Last active February 27, 2023 23:22
Show Gist options
  • Save tlively/fb2f2522bf80a6d73e0eed8cd83337f7 to your computer and use it in GitHub Desktop.
Save tlively/fb2f2522bf80a6d73e0eed8cd83337f7 to your computer and use it in GitHub Desktop.
#include <assert.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#ifdef __EMSCRIPTEN__
#include <emscripten/wasmfs.h>
#endif
#define ITERATIONS 10000
#define WARMUP_RUNS 5
_Atomic int nready = 0;
_Atomic int start = 0;
_Atomic int iterations = 0;
void do_work(int fd) {
#ifndef NULLFS
struct stat stat_buf;
int err = fstat(fd, &stat_buf);
assert(err == 0 && stat_buf.st_size == 0);
#endif
}
void* run_thread(void* arg) {
int id = (int)arg;
char path[3] = {};
int path_len = snprintf(path, sizeof(path), "%d", id);
assert(path_len > 0 && path_len < sizeof(path));
// Open file
int fd = creat(path, 0777);
if (fd < 0) {
abort();
}
nready++;
// Wait for start
while (start == 0) {}
// Go go go!
while (iterations++ < ITERATIONS) {
do_work(fd);
}
// Finish
close(fd);
return NULL;
}
void benchmark(int nthreads, int nruns) {
int64_t cumulative_nanos = 0;
printf("Running %d runs with %d threads\n", nruns, nthreads);
for (int run = 0; run < nruns + WARMUP_RUNS; run++) {
printf("Run %d: ", run - WARMUP_RUNS);
if (run < WARMUP_RUNS) {
printf("\n");
}
pthread_t threads[nthreads];
struct timespec start_time, end_time;
// Start threads
nready = start = iterations = 0;
for (int i = 0; i < nthreads; ++i) {
if (pthread_create(&threads[i], NULL, run_thread, (void*)i) != 0) {
abort();
}
}
// Wait for all threads to be ready.
while (nready < nthreads) {}
// Start
clock_gettime(CLOCK_REALTIME, &start_time);
start = 1;
// End
while (iterations < ITERATIONS) {}
clock_gettime(CLOCK_REALTIME, &end_time);
// Join threads
for (int i = 0; i < nthreads; ++i) {
pthread_join(threads[i], NULL);
}
if (run >= WARMUP_RUNS) {
// Report the time.
int64_t nanos =
(int64_t)(end_time.tv_sec - start_time.tv_sec) * 1000000000ll +
(end_time.tv_nsec - start_time.tv_nsec);
printf("%f ms\n", (double)nanos / 1000000);
cumulative_nanos += nanos;
}
}
printf("%d threads: %f ms\n",
nthreads,
(double)cumulative_nanos / (nruns * 1000000));
}
#ifdef PROXYFS
backend_t make_mem_backend(void* arg) {
return wasmfs_create_memory_backend();
}
#endif
int main() {
#if defined(__EMSCRIPTEN__) && !defined(NULLFS)
#ifdef MEMFS
backend_t backend = wasmfs_get_backend_by_path("/");
#else
#ifdef JSFS
backend_t backend = wasmfs_create_js_file_backend();
#else
#ifdef NODEFS
backend_t backend = wasmfs_create_node_backend(".");
#else
#ifdef OPFS
backend_t backend = wasmfs_create_opfs_backend();
#else
#ifdef PROXYFS
backend_t backend = wasmfs_create_proxied_backend(make_mem_backend, NULL);
#endif
#endif
#endif
#endif
#endif
int err = wasmfs_create_directory("working", 0777, backend);
assert(err == 0);
err = chdir("working");
assert(err == 0);
#endif
// TODO: set up WasmFS backend, etc.
for (int nthreads = 1; nthreads <= 16; nthreads <<= 1) {
benchmark(nthreads, 10);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment