Skip to content

Commit

Permalink
Finish map benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikwidlund committed Jan 14, 2017
1 parent e9ab2f6 commit b75ddf5
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 23 deletions.
12 changes: 6 additions & 6 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ maintainer-clean-local:; rm -rf autotools m4 libdynamic-?.?.?

CHECK_CFLAGS = -std=gnu11 -O0 -g -ftest-coverage -fprofile-arcs
CHECK_LDADD = -L. -ldynamic_test -lcmocka
CHECK_LDFLAGS_EXTRA = -Wl,--wrap=malloc -Wl,--wrap=calloc -Wl,--wrap=realloc -Wl,--wrap=aligned_alloc
CHECK_LDFLAGS_EXTRA = -Wl,--wrap=malloc -Wl,--wrap=calloc -Wl,--wrap=realloc -Wl,--wrap=aligned_alloc -Wl,--wrap=abort

check_LIBRARIES = libdynamic_test.a
libdynamic_test_a_CFLAGS = $(CHECK_CFLAGS)
Expand All @@ -48,31 +48,31 @@ check_PROGRAMS = test/buffer
test_buffer_CFLAGS = $(CHECK_CFLAGS)
test_buffer_LDADD = $(CHECK_LDADD)
test_buffer_LDFLAGS = $(CHECK_LDFLAGS_EXTRA)
test_buffer_SOURCES = test/buffer.c test/memory.c
test_buffer_SOURCES = test/buffer.c test/mock.c

check_PROGRAMS += test/vector
test_vector_CFLAGS = $(CHECK_CFLAGS)
test_vector_LDADD = $(CHECK_LDADD)
test_vector_LDFLAGS = $(CHECK_LDFLAGS_EXTRA)
test_vector_SOURCES = test/vector.c test/memory.c
test_vector_SOURCES = test/vector.c test/mock.c

check_PROGRAMS += test/string
test_string_CFLAGS = $(CHECK_CFLAGS)
test_string_LDADD = $(CHECK_LDADD)
test_string_LDFLAGS = $(CHECK_LDFLAGS_EXTRA)
test_string_SOURCES = test/string.c test/memory.c
test_string_SOURCES = test/string.c test/mock.c

check_PROGRAMS += test/hash
test_hash_CFLAGS = $(CHECK_CFLAGS)
test_hash_LDADD = $(CHECK_LDADD)
test_hash_LDFLAGS = $(CHECK_LDFLAGS_EXTRA)
test_hash_SOURCES = test/hash.c test/memory.c
test_hash_SOURCES = test/hash.c test/mock.c

check_PROGRAMS += test/map
test_map_CFLAGS = $(CHECK_CFLAGS)
test_map_LDADD = $(CHECK_LDADD)
test_map_LDFLAGS = $(CHECK_LDFLAGS_EXTRA)
test_map_SOURCES = test/map.c test/memory.c
test_map_SOURCES = test/map.c test/mock.c

dist_noinst_SCRIPTS = test/valgrind.sh test/coverage.sh

Expand Down
2 changes: 1 addition & 1 deletion benchmark/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ 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

benchmarks: map.pdf
benchmark: map.pdf

map.pdf: map.dat map.R
./map.R
Expand Down
6 changes: 3 additions & 3 deletions benchmark/README
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
To build the benchmarks, invole
make benchmarks
To build the benchmark, invole
make benchmark

The benchmarks require R and the ggplot2, scales and sitools libraries.
The benchmark require R, and the ggplot2, scales and sitools libraries.
37 changes: 31 additions & 6 deletions benchmark/map.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,39 @@ library(scales)
library(sitools)

data.map <- read.csv("map.dat", head=TRUE, sep=",")
sets <- unique(data.map$name)

graph <- ggplot(legend = TRUE) +
labs(list(x = "Elements", y = "Time/Operation (ns)")) +
theme(plot.title = element_text(size = 10),
labs(list(title = "Insert", 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)) +
axis.text.x = element_text(size = 8), axis.text.y = element_text(size = 8)) +
geom_smooth(method = "loess", span = 0.5, 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^(2:10), labels = comma)
ggsave(graph, file = "map.pdf", width = 10, height = 5)
scale_x_continuous(trans = log_trans(), breaks = 10^(0:10), labels = comma)
graph$labels$colour <- "Implementation"
ggsave(graph, file = "map_insert.pdf", width = 10, height = 5)

graph <- 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.5, data = data.map, aes(x = size, y = at, colour = name)) +
scale_y_continuous(labels = comma) +
expand_limits(y = 0) +
scale_x_continuous(trans = log_trans(), breaks = 10^(0:10), labels = comma)
graph$labels$colour <- "Implementation"
ggsave(graph, file = "map_lookup.pdf", width = 10, height = 5)

graph <- 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.5, data = data.map, aes(x = size, y = erase, colour = name)) +
scale_y_continuous(labels = comma) +
expand_limits(y = 0) +
scale_x_continuous(trans = log_trans(), breaks = 10^(0:10), labels = comma)
graph$labels$colour <- "Implementation"
ggsave(graph, file = "map_delete.pdf", width = 10, height = 5)
15 changes: 8 additions & 7 deletions benchmark/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include "dynamic.h"

Expand All @@ -12,10 +13,10 @@
#include "map_dynamic.h"

static map_metric metrics[] = {
{.name = "custom", .measure = map_custom},
{.name = "custom open addressing", .measure = map_custom},
{.name = "libdynamic", .measure = map_dynamic},
{.name = "subclass", .measure = map_subclass},
{.name = "std::map_unordered", .measure = map_unordered}
{.name = "std::map_unordered", .measure = map_unordered},
{.name = "libdynamic (subclass)", .measure = map_subclass}
};

uint64_t ntime(void)
Expand All @@ -28,13 +29,13 @@ uint64_t ntime(void)

int main()
{
size_t i, n, n_min = 100, n_max = 1000000;
size_t i, n, n_min = 10, n_max = 1000000;
double k = 1.1;
uint32_t *a;
map_metric *m;

(void) fprintf(stdout, "name,size,insert,at\n");
for (n = n_min; n < n_max; n *= k)
(void) fprintf(stdout, "name,size,insert,at,erase\n");
for (n = n_min; n < n_max; n = ceil(k * n))
{
a = calloc(n, sizeof *a);
for (i = 0; i < n; i ++)
Expand All @@ -43,7 +44,7 @@ int main()
for (m = metrics; m < &metrics[sizeof metrics / sizeof metrics[0]]; m ++)
{
m->measure(m, a, n);
(void) fprintf(stdout, "%s,%lu,%f,%f\n", m->name, n, m->insert, m->at);
(void) fprintf(stdout, "%s,%lu,%f,%f,%f\n", m->name, n, m->insert, m->at, m->erase);
}

free(a);
Expand Down
1 change: 1 addition & 0 deletions benchmark/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ struct map_metric
void (*measure)(map_metric *, uint32_t *, size_t);
double insert;
double at;
double erase;
};

uint64_t ntime(void);
Expand Down
40 changes: 40 additions & 0 deletions benchmark/map_custom.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,38 @@ static void map_insert(map *m, uint32_t key, uint32_t value)
}
}

static void map_erase(map *m, uint32_t key)
{
map_element *e;
size_t i, j, k;

e = map_at(m, key);
if (e->key == (uint32_t) -1)
return;

m->elements_count --;

i = ((char *) e - (char *) m->elements) / sizeof *e;
j = i;
while (1)
{
j = (j + 1) & (m->elements_capacity - 1);
if (m->elements[j].key == (uint32_t) -1)
break;

k = m->elements[j].key & (m->elements_capacity - 1);
if ((i < j && (k <= i || k > j)) ||
(i > j && (k <= i && k > j)))
{
m->elements[i].key = m->elements[j].key;
m->elements[i].value = m->elements[j].value;
i = j;
}
}

m->elements[i].key = (uint32_t) -1;
}

static void map_rehash(map *m, size_t size)
{
map new;
Expand Down Expand Up @@ -131,5 +163,13 @@ void map_custom(map_metric *metric, uint32_t *a, size_t n)
t2 = ntime();
metric->at = (double) (t2 - t1) / n;

t1 = ntime();
for (i = 0; i < n; i ++)
map_erase(&m, a[i]);
t2 = ntime();
if (m.elements_count)
errx(1, "inconsistency");
metric->erase = (double) (t2 - t1) / n;

map_destruct(&m);
}
9 changes: 9 additions & 0 deletions benchmark/map_dynamic.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <err.h>
#include <time.h>

#include "dynamic.h"
Expand Down Expand Up @@ -45,5 +46,13 @@ void map_dynamic(map_metric *metric, uint32_t *a, size_t n)
t2 = ntime();
metric->at = (double) (t2 - t1) / n;

t1 = ntime();
for (i = 0; i < n; i ++)
map_erase(&m, (map_element[]){{.key = a[i]}}, hash, equal, NULL);
t2 = ntime();
if (map_size(&m))
errx(1, "inconsistency");
metric->erase = (double) (t2 - t1) / n;

map_destruct(&m, NULL, NULL);
}
19 changes: 19 additions & 0 deletions benchmark/map_subclass.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ static void map_int_pair_insert(map_int_pair *m, uint32_t key, uint32_t value)
map_insert(m,(map_int_pair_element[]){{.key = key, .value = value}}, hash, equal, NULL);
}

static void map_int_pair_erase(map_int_pair *m, uint32_t key)
{
map_erase(m,(map_int_pair_element[]){{.key = key}}, hash, equal, NULL);
}

static size_t map_int_pair_size(map_int_pair *m)
{
return map_size(m);
}

void map_subclass(map_metric *metric, uint32_t *a, size_t n)
{
map_int_pair m;
Expand All @@ -68,5 +78,14 @@ void map_subclass(map_metric *metric, uint32_t *a, size_t n)
t2 = ntime();
metric->at = (double) (t2 - t1) / n;

t1 = ntime();
for (i = 0; i < n; i ++)
map_int_pair_erase(&m, a[i]);
t2 = ntime();
if (map_int_pair_size(&m))
errx(1, "inconsistency");
metric->erase = (double) (t2 - t1) / n;


map_int_pair_destruct(&m);
}
13 changes: 13 additions & 0 deletions benchmark/map_unordered.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ void map_unordered(map_metric *, uint32_t *, size_t);
void map_unordered(map_metric *metric, uint32_t *a, size_t n)
{
std::unordered_map<uint32_t, uint32_t> m;
std::unordered_map<uint32_t, uint32_t>::iterator iter;
size_t i;
uint64_t t1, t2;

Expand All @@ -32,5 +33,17 @@ void map_unordered(map_metric *metric, uint32_t *a, size_t n)
t2 = ntime();
metric->at = (double) (t2 - t1) / n;

t1 = ntime();
for (i = 0; i < n; i ++)
{
iter = m.find(a[i]);
if (iter != m.end())
m.erase(iter);
}
if (m.size())
errx(1, "inconsistency");
t2 = ntime();
metric->erase = (double) (t2 - t1) / n;

m.clear();
}

0 comments on commit b75ddf5

Please sign in to comment.