Skip to content

Instantly share code, notes, and snippets.

@emmiegit
Last active March 31, 2017 21:28
Show Gist options
  • Select an option

  • Save emmiegit/fdd91dfa3e6a9f15d86d31aa9ee6980e to your computer and use it in GitHub Desktop.

Select an option

Save emmiegit/fdd91dfa3e6a9f15d86d31aa9ee6980e to your computer and use it in GitHub Desktop.
Helium garbage generator
#define _XOPEN_SOURCE 500
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <he.h>
#define DEFAULT_URL "he://.//mnt/nvme/he"
#define DATASTORE_NAME "gc"
#define THREADS 64
struct thread_data {
he_t he;
unsigned int thread;
unsigned int seed;
};
static void *
_stats_(void *arg)
{
struct timespec ts;
struct he_stats stats;
he_t he;
he = arg;
ts.tv_sec = 30;
ts.tv_nsec = 0;
for (;;) {
if (he_stats(he, &stats)) {
he_perror("he_stats");
break;
}
printf("---------------------------\n"
"Valid / Deleted: %" PRIu64 ", %" PRIu64 "\n"
"Utilized / Capacity: %" PRIu64 ", %" PRIu64 "\n"
"GC rounds: %" PRIu64 "\n",
stats.valid_items,
stats.deleted_items,
stats.utilized,
stats.capacity,
stats.auto_cleans);
if (nanosleep(&ts, NULL)) {
perror("nanosleep");
break;
}
}
return NULL;
}
static void *
_worker_(void *arg)
{
struct thread_data *data;
struct he_item item;
char key[32], val[16];
unsigned long i;
data = arg;
item.key = key;
item.val = val;
printf("Starting thread %u...\n", data->thread);
for (i = 1; i != 0; i++) {
item.key_len = snprintf(key, sizeof(key),
"%03d_%u",
rand_r(&data->seed) % 1000,
rand_r(&data->seed));
item.val_len = snprintf(val, sizeof(val),
"%lu_%d",
i,
rand_r(&data->seed));
if (he_update(data->he, &item)) {
he_perror("he_update");
break;
}
/* 2/3 chance of deletion */
if ((rand_r(&data->seed) % 3) < 2) {
if (he_delete(data->he, &item)) {
he_perror("he_delete");
break;
}
}
}
return NULL;
}
int
main(int argc, const char *argv[])
{
struct he_env env;
he_t he;
const char *url;
pthread_t stat_thrd;
struct worker {
pthread_t thrd;
struct thread_data dat;
} workers[THREADS];
unsigned int i;
if (argc == 1)
url = DEFAULT_URL;
else
url = argv[1];
memset(&env, 0, sizeof(struct he_env));
env.clean_dirty_pct = 2;
he = he_open(url,
DATASTORE_NAME,
HE_O_CREATE | HE_O_VOLUME_CREATE | HE_O_VOLUME_TRUNCATE,
&env);
if (!he) {
he_perror("he_open");
return -1;
}
srand(time(NULL));
for (i = 0; i < THREADS; i++) {
struct worker *wrk;
wrk = &workers[i];
wrk->dat.he = he;
wrk->dat.thread = i;
wrk->dat.seed = rand() + 1;
if (pthread_create(&wrk->thrd, NULL, _worker_, &wrk->dat)) {
perror("pthread_create");
return -1;
}
}
if (pthread_create(&stat_thrd, NULL, _stats_, he)) {
perror("pthread_create");
return -1;
}
for (i = 0; i < THREADS; i++) {
struct worker *wrk;
wrk = &workers[i];
if (pthread_join(wrk->thrd, NULL)) {
perror("pthread_join");
return -1;
}
}
if (pthread_join(stat_thrd, NULL)) {
perror("pthread_join");
return -1;
}
if (he_close(he)) {
he_perror("he_open");
return -1;
}
return 0;
}
@emmiegit
Copy link
Author

This program spins up 64 threads and has them spamming a datastore with items, deleting 2/3s of them. This way the datastore fills up with garbage. I then have another thread print gc statistics every 30 seconds. By inspecting the output, I was able to determine that the new gc metric for helium directories is working correctly, and garbage is being collected. I set "clean_util_pct" to 2%.

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