Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikwidlund committed Jan 20, 2017
1 parent 623160f commit da20a08
Show file tree
Hide file tree
Showing 9 changed files with 248 additions and 133 deletions.
7 changes: 5 additions & 2 deletions benchmark/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ vector_CXXFLAGS = -I../src -g -O3 -flto -fuse-linker-plugin
vector_LDADD = ../libdynamic.la

map_SOURCES = \
map.c map_custom.c map_subclass.c map_dynamic.c map_unordered.cpp \
map.h map_custom.h map_subclass.h map_dynamic.h map_unordered.h \
map.c map_std_unordered.cpp map_custom.c map_dynamic.c \
map.h map_std_unordered.h map_custom.h map_dynamic.h \
map.R
#map.c map_custom.c map_subclass.c map_dynamic.c map_unordered.cpp \
#map.h map_custom.h map_subclass.h map_dynamic.h map_unordered.h \
#map.R
map_CFLAGS = -std=gnu11 -I../src -g -O3 -flto -fuse-linker-plugin
map_CXXFLAGS = -I../src -g -O3 -flto -fuse-linker-plugin
map_LDADD = ../libdynamic.la
Expand Down
14 changes: 7 additions & 7 deletions benchmark/map.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,33 @@ g1 <- ggplot(legend = TRUE) +
theme(plot.title = element_text(size = 10),
axis.title.x = element_text(size = 8), axis.title.y = element_text(size = 8),
axis.text.x = element_text(size = 8), axis.text.y = element_text(size = 8)) +
geom_smooth(method = "loess", span = 0.1, data = data.map, aes(x = size, y = insert, colour = name)) +
geom_smooth(method = "loess", span = 0.2, se = FALSE, data = data.map, aes(x = size, y = insert, colour = name)) +
scale_y_continuous(labels = comma) +
expand_limits(y = 0) +
scale_x_continuous(trans = log_trans(), breaks = 10^(0:10), labels = comma)
g1$labels$colour <- "Implementation"
g1$labels$colour <- "Library"

g2 <- ggplot(legend = TRUE) +
labs(list(title = "Lookup", x = "Map size", y = "Time/Operation (ns)")) +
theme(plot.title = element_text(size = 10),
axis.title.x = element_text(size = 8), axis.title.y = element_text(size = 8),
axis.text.x = element_text(size = 8), axis.text.y = element_text(size = 8)) +
geom_smooth(method = "loess", span = 0.1, data = data.map, aes(x = size, y = at, colour = name)) +
geom_smooth(method = "loess", span = 0.2, se = FALSE, data = data.map, aes(x = size, y = lookup, colour = name)) +
scale_y_continuous(labels = comma) +
expand_limits(y = 0) +
scale_x_continuous(trans = log_trans(), breaks = 10^(0:10), labels = comma)
g2$labels$colour <- "Implementation"
g2$labels$colour <- "Library"

g3 <- ggplot(legend = TRUE) +
labs(list(title = "Delete", x = "Map size", y = "Time/Operation (ns)")) +
theme(plot.title = element_text(size = 10),
axis.title.x = element_text(size = 8), axis.title.y = element_text(size = 8),
axis.text.x = element_text(size = 8), axis.text.y = element_text(size = 8)) +
geom_smooth(method = "loess", span = 0.1, data = data.map, aes(x = size, y = erase, colour = name)) +
geom_smooth(method = "loess", span = 0.2, se = FALSE, data = data.map, aes(x = size, y = delete, colour = name)) +
scale_y_continuous(labels = comma) +
expand_limits(y = 0) +
scale_x_continuous(trans = log_trans(), breaks = 10^(0:10), labels = comma)
g3$labels$colour <- "Implementation"
g3$labels$colour <- "Library"

pdf("map.pdf", width = 10, height = 10)
grid.arrange(g1, g2, g3, ncol=1, top = "libdynamic map benchmark")
grid.arrange(g1, g2, g3, ncol=1, top = "Hash map benchmark (random integer keys)")
183 changes: 140 additions & 43 deletions benchmark/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,47 @@
#include <time.h>
#include "dynamic.h"

#include "map.h"
//#include "map.h"
//#include "map_subclass.h"
#include "map_std_unordered.h"
#include "map_custom.h"
#include "map_subclass.h"
#include "map_unordered.h"
#include "map_dynamic.h"
//#include "map_dynamic.h"

static map_metric metrics[] = {
{.name = "std::map_unordered", .measure = map_unordered},
{.name = "custom open addressing", .measure = map_custom},
{.name = "libdynamic", .measure = map_dynamic},
{.name = "libdynamic (subclass)", .measure = map_subclass}
typedef struct library library;
struct library
{
char *name;
void (*measure)(int *, int *, int *, size_t, size_t, double *, double *, double *, uint64_t *);
};

typedef struct metric metric;
struct metric
{
char *name;
size_t size;
double insert;
double lookup;
double delete;
uint64_t sum;
};

struct result
typedef struct input input;
struct input
{
char *name;
size_t size;
double insert;
double at;
double erase;
int *keys;
int *keys_shuffled;
int *values;
};

static library libraries[] = {
{.name = "std::map_unordered", .measure = map_std_unordered},
{.name = "custom open addressing", .measure = map_custom},
{.name = "libdynamic", .measure = map_libdynamic},
//{.name = "libdynamic map (subclass)", .measure = map_libdynamic_subclass}
};
static const size_t libraries_len = sizeof libraries / sizeof libraries[0];

uint64_t ntime(void)
{
struct timespec ts;
Expand All @@ -36,46 +55,124 @@ uint64_t ntime(void)
return ((uint64_t) ts.tv_sec * 1000000000) + ((uint64_t) ts.tv_nsec);
}

static void shuffle(int *array, size_t n)
{
size_t i, j;
int t;

if (n <= 1)
return;

for (i = 0; i < n - 1; i ++)
{
j = i + rand() / (RAND_MAX / (n - i) + 1);
t = array[j];
array[j] = array[i];
array[i] = t;
}
}

static void input_construct(input *input, size_t size)
{
input->size = 0;
input->keys = malloc(size * sizeof input->keys[0]);
input->keys_shuffled = malloc(size * sizeof input->keys_shuffled[0]);
input->values = malloc(size * sizeof input->values[0]);

while (input->size < size)
{
input->keys[input->size] = random();
input->keys_shuffled[input->size] = input->keys[input->size];
input->values[input->size] = random();
input->size ++;
}

shuffle(input->keys_shuffled, input->size);
}

static void input_destruct(input *input)
{
free(input->keys);
free(input->keys_shuffled);
free(input->values);
}

static void metric_aggregate(metric *ma, metric *mi)
{
if (!ma->insert || ma->insert > mi->insert)
ma->insert = mi->insert;
if (!ma->lookup || ma->lookup > mi->lookup)
ma->lookup = mi->lookup;
if (!ma->delete || ma->delete > mi->delete)
ma->delete = mi->delete;
ma->sum = mi->sum;
}

int main()
{
size_t i, n, n_min = 10, n_max = 1000000, round, rounds = 5;
double k = 1.1;
uint32_t *a;
map_metric *m;
vector results;
struct result result, *r;

vector_construct(&results, sizeof result);
for (n = n_min; n < n_max; n = ceil(k * n))
size_t size, size_min, size_max, rounds, lookups, r, i;
double size_factor;
vector metrics;
input input;
metric metric, mr, *mp;

/* benchmark settings */
size_min = 10;
size_max = 1000000;
size_factor = 1.1;
rounds = 5;
lookups = 100000;

vector_construct(&metrics, sizeof metric);

/* iterate through libraries */
for (size = size_min; size < size_max; size = ceil(size_factor * size))
{
a = calloc(n, sizeof *a);
for (i = 0; i < n; i ++)
a[i] = rand();
input_construct(&input, size);

for (m = metrics; m < &metrics[sizeof metrics / sizeof metrics[0]]; m ++)
for (i = 0; i < libraries_len; i ++)
{
result = (struct result) {.name = m->name, .size = n};
for (round = 0; round < rounds; round ++)
metric = (struct metric) {.name = libraries[i].name, .size = input.size};
for (r = 0; r < rounds; r ++)
{
m->measure(m, a, n);
if (!result.insert || m->insert < result.insert)
result.insert = m->insert;
if (!result.at || m->at < result.at)
result.at = m->at;
if (!result.erase || m->erase < result.erase)
result.erase = m->erase;
libraries[i].measure(input.keys, input.keys_shuffled, input.values, input.size, lookups,
&mr.insert, &mr.lookup, &mr.delete, &mr.sum);
metric_aggregate(&metric, &mr);
}
vector_push_back(&results, &result);
vector_push_back(&metrics, &metric);
}
free(a);

input_destruct(&input);
}

(void) fprintf(stdout, "name,size,insert,at,erase\n");
for (i = 0; i < vector_size(&results); i ++)
/* output resulting metrics */
(void) fprintf(stdout, "name,size,insert,lookup,delete\n");
for (i = 0; i < vector_size(&metrics); i ++)
{
r = vector_at(&results, i);
(void) fprintf(stdout, "%s,%lu,%f,%f,%f\n", r->name, r->size, r->insert, r->at, r->erase);
mp = vector_at(&metrics, i);
(void) fprintf(stdout, "%s,%lu,%f,%f,%f\n", mp->name, mp->size, mp->insert, mp->lookup, mp->delete);
}

vector_destruct(&metrics);
}

/*
{
metric = (struct metric) {.name = m->name, .size = n};
for (round = 0; round < rounds; round ++)
{
m->measure(m, a, n, 6);
if (!metric.insert || m->insert < metric.insert)
metric.insert = m->insert;
if (!metric.at || m->at < metric.at)
metric.at = m->at;
if (!metric.erase || m->erase < metric.erase)
metric.erase = m->erase;
}
vector_push_back(&metrics, &metric);
}
free(a);
}
vector_destruct(&results);
}
*/

0 comments on commit da20a08

Please sign in to comment.