performance of span
This commit is contained in:
parent
feb3e12581
commit
5460ef87b7
10
Makefile
10
Makefile
|
@ -6,10 +6,10 @@ SHARED_LIB = libsparsemap.so
|
|||
#CFLAGS = -Wall -Wextra -Wpedantic -Of -std=c11 -Iinclude/ -fPIC
|
||||
#CFLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC
|
||||
CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DSPARSEMAP_ASSERT -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC
|
||||
#CFLAGS = -Wall -Wextra -Wpedantic -Og -g -fsanitize=address,leak,object-size,pointer-compare,pointer-subtract,null,return,bounds,pointer-overflow,undefined -fsanitize-address-use-after-scope -std=c99 -Iinclude/ -fPIC
|
||||
#CFLAGS = -Wall -Wextra -Wpedantic -Og -g -fsanitize=all -fhardened -std=c99 -Iinclude/ -fPIC
|
||||
#CFLAGS = -Wall -Wextra -Wpedantic -Og -g -fsanitize=address,leak,object-size,pointer-compare,pointer-subtract,null,return,bounds,pointer-overflow,undefined -fsanitize-address-use-after-scope -std=c11 -Iinclude/ -fPIC
|
||||
#CFLAGS = -Wall -Wextra -Wpedantic -Og -g -fsanitize=all -fhardened -std=c11 -Iinclude/ -fPIC
|
||||
|
||||
TEST_FLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c99 -Iinclude/ -Itests/ -fPIC
|
||||
TEST_FLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -Itests/ -fPIC
|
||||
|
||||
TESTS = tests/test
|
||||
TEST_OBJS = tests/test.o tests/munit.o tests/common.o
|
||||
|
@ -49,7 +49,7 @@ clean:
|
|||
rm -f $(EXAMPLES) examples/*.o
|
||||
|
||||
format:
|
||||
clang-format -i src/sparsemap.c include/sparsemap.h examples/ex_*.c tests/test.c tests/common.c
|
||||
clang-format -i src/sparsemap.c include/sparsemap.h examples/ex_*.c tests/test.c tests/common.c tests/common.h
|
||||
# clang-format -i include/*.h src/*.c tests/*.c tests/*.h examples/*.c
|
||||
|
||||
%.o: src/%.c
|
||||
|
@ -76,4 +76,4 @@ examples/ex_3: examples/common.o examples/ex_3.o $(STATIC_LIB)
|
|||
examples/ex_4: examples/common.o examples/ex_4.o $(STATIC_LIB)
|
||||
$(CC) $^ -o $@ $(CFLAGS) $(TEST_FLAGS)
|
||||
|
||||
# cp src/sparsemap.c /tmp && clang-tidy src/sparsemap.c -fix -fix-errors -checks="readability-braces-around-statements" -- -DDEBUG -DSPARSEMAP_DIAGNOSTIC -DSPARSEMAP_ASSERT -Wall -Wextra -Wpedantic -Og -g -std=c99 -Iinclude/ -fPIC
|
||||
# cp src/sparsemap.c /tmp && clang-tidy src/sparsemap.c -fix -fix-errors -checks="readability-braces-around-statements" -- -DDEBUG -DSPARSEMAP_DIAGNOSTIC -DSPARSEMAP_ASSERT -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
} while (0)
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
|
||||
/* !!! Duplicated here for testing purposes. Keep in sync, or suffer. !!! */
|
||||
struct sparsemap {
|
||||
uint8_t *m_data;
|
||||
|
@ -20,7 +19,6 @@ struct sparsemap {
|
|||
size_t m_data_used;
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
|
|
|
@ -87,12 +87,10 @@
|
|||
* Usually this is an uint64_t.
|
||||
*/
|
||||
|
||||
|
||||
typedef struct sparsemap sparsemap_t;
|
||||
typedef uint32_t sm_idx_t;
|
||||
typedef uint64_t sm_bitvec_t;
|
||||
|
||||
|
||||
/* Allocate on a sparsemap_t on the heap and initialize it. */
|
||||
sparsemap_t *sparsemap(uint8_t *data, size_t size);
|
||||
|
||||
|
|
|
@ -20,13 +20,12 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <popcount.h>
|
||||
#include <sparsemap.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <popcount.h>
|
||||
#include <sparsemap.h>
|
||||
|
||||
#ifdef SPARSEMAP_DIAGNOSTIC
|
||||
#pragma GCC diagnostic push
|
||||
|
@ -99,18 +98,16 @@ enum __SM_CHUNK_INFO {
|
|||
|
||||
#define SM_CHUNK_GET_FLAGS(from, at) (((from)) & ((sm_bitvec_t)SM_FLAG_MASK << ((at) * 2))) >> ((at) * 2)
|
||||
|
||||
|
||||
typedef struct {
|
||||
sm_bitvec_t *m_data;
|
||||
} __sm_chunk_t;
|
||||
|
||||
struct sparsemap {
|
||||
uint8_t *m_data; /* The serialized bitmap data */
|
||||
size_t m_capacity; /* The total size of m_data */
|
||||
size_t m_data_used; /* The used size of m_data */
|
||||
uint8_t *m_data; /* The serialized bitmap data */
|
||||
size_t m_capacity; /* The total size of m_data */
|
||||
size_t m_data_used; /* The used size of m_data */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the number of sm_bitvec_ts required by a single byte with flags
|
||||
* (in m_data[0]).
|
||||
|
@ -799,7 +796,8 @@ sparsemap_set_data_size(sparsemap_t *map, size_t data_size)
|
|||
* indicate full.
|
||||
*/
|
||||
double
|
||||
sparsemap_capacity_remaining(sparsemap_t *map) {
|
||||
sparsemap_capacity_remaining(sparsemap_t *map)
|
||||
{
|
||||
if (map->m_data_used > map->m_capacity) {
|
||||
return 0;
|
||||
}
|
||||
|
|
159
tests/common.c
159
tests/common.c
|
@ -2,12 +2,12 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <sparsemap.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../include/sparsemap.h"
|
||||
#include "common.h"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
|
@ -19,6 +19,87 @@
|
|||
} while (0)
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
uint64_t
|
||||
tsc(void)
|
||||
{
|
||||
uint32_t low, high;
|
||||
__asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
|
||||
return ((uint64_t)high << 32) | low;
|
||||
}
|
||||
|
||||
static
|
||||
uint64_t get_tsc_frequency() {
|
||||
uint32_t high, low;
|
||||
__asm__ volatile("rdtsc" : "=a" (low), "=d" (high));
|
||||
__asm__ volatile("rdtsc");
|
||||
return ((uint64_t)high << 32) | low;
|
||||
}
|
||||
|
||||
double
|
||||
tsc_ticks_to_ns(uint64_t tsc_ticks) {
|
||||
static uint64_t tsc_freq = 0;
|
||||
if (tsc_freq == 0) {
|
||||
tsc_freq = get_tsc_frequency();
|
||||
}
|
||||
return (double)tsc_ticks / (double)tsc_freq * 1e9;
|
||||
}
|
||||
|
||||
void
|
||||
est_sift_up(uint64_t *heap, int child_index)
|
||||
{
|
||||
while (child_index > 0) {
|
||||
int parent_index = (child_index - 1) / 2;
|
||||
if (heap[parent_index] > heap[child_index]) {
|
||||
// Swap parent and child
|
||||
uint64_t temp = heap[parent_index];
|
||||
heap[parent_index] = heap[child_index];
|
||||
heap[child_index] = temp;
|
||||
child_index = parent_index;
|
||||
} else {
|
||||
break; // Heap property satisfied
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
est_sift_down(uint64_t *heap, int heap_size, int parent_index)
|
||||
{
|
||||
int child_index = 2 * parent_index + 1; // Left child
|
||||
while (child_index < heap_size) {
|
||||
// Right child exists and is smaller than left child
|
||||
if (child_index + 1 < heap_size && heap[child_index + 1] < heap[child_index]) {
|
||||
child_index++;
|
||||
}
|
||||
// If the smallest child is smaller than the parent, swap them
|
||||
if (heap[child_index] < heap[parent_index]) {
|
||||
uint64_t temp = heap[child_index];
|
||||
heap[child_index] = heap[parent_index];
|
||||
heap[parent_index] = temp;
|
||||
parent_index = child_index;
|
||||
child_index = 2 * parent_index + 1;
|
||||
} else {
|
||||
break; // Heap property satisfied
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
est_insert_value(uint64_t *heap, int heap_max_size, int *heap_size, uint64_t value)
|
||||
{
|
||||
if (*heap_size < heap_max_size) { // Heap not full, insert value
|
||||
heap[*heap_size] = value;
|
||||
est_sift_up(heap, *heap_size);
|
||||
(*heap_size)++;
|
||||
} else {
|
||||
// Heap is full, replace root with new value with a certain probability
|
||||
// This is a very naive approach to maintain a sample of the input
|
||||
if (rand() % 2) {
|
||||
heap[0] = value;
|
||||
est_sift_down(heap, heap_max_size, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int __xorshift32_state = 0;
|
||||
|
||||
// Xorshift algorithm for PRNG
|
||||
|
@ -120,7 +201,11 @@ int
|
|||
create_sequential_set_in_empty_map(sparsemap_t *map, int s, int r)
|
||||
{
|
||||
int placed_at;
|
||||
placed_at = random_uint32() % (s - r - 1);
|
||||
if (s >= r + 1) {
|
||||
placed_at = 0;
|
||||
} else {
|
||||
placed_at = random_uint32() % (s - r - 1);
|
||||
}
|
||||
for (int i = placed_at; i < placed_at + r; i++) {
|
||||
sparsemap_set(map, i, true);
|
||||
}
|
||||
|
@ -269,60 +354,62 @@ setup_test_array(int a[], int l, int max_value)
|
|||
}
|
||||
|
||||
void
|
||||
bitmap_from_uint32(sparsemap_t *map, uint32_t number) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
bool bit = number & (1 << i);
|
||||
sparsemap_set(map, i, bit);
|
||||
}
|
||||
bitmap_from_uint32(sparsemap_t *map, uint32_t number)
|
||||
{
|
||||
for (int i = 0; i < 32; i++) {
|
||||
bool bit = number & (1 << i);
|
||||
sparsemap_set(map, i, bit);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bitmap_from_uint64(sparsemap_t *map, uint64_t number) {
|
||||
for (int i = 0; i < 64; i++) {
|
||||
bool bit = number & (1 << i);
|
||||
sparsemap_set(map, i, bit);
|
||||
}
|
||||
bitmap_from_uint64(sparsemap_t *map, uint64_t number)
|
||||
{
|
||||
for (int i = 0; i < 64; i++) {
|
||||
bool bit = number & (1 << i);
|
||||
sparsemap_set(map, i, bit);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rank_uint64(uint64_t number, int n, int p)
|
||||
{
|
||||
if (p < n || p > 63) {
|
||||
return 0;
|
||||
}
|
||||
if (p < n || p > 63) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create a mask for the range between n and p.
|
||||
This works by shifting 1 to the left (p+1) times, subtracting 1 to have
|
||||
a sequence of p 1's, then shifting n times to the left to position it
|
||||
starting at n. Finally, subtracting (1 << n) - 1 removes the bits below
|
||||
n from the mask. */
|
||||
uint64_t mask = ((uint64_t)1 << (p + 1)) - 1 - (((uint64_t)1 << n) - 1);
|
||||
/* Create a mask for the range between n and p.
|
||||
This works by shifting 1 to the left (p+1) times, subtracting 1 to have
|
||||
a sequence of p 1's, then shifting n times to the left to position it
|
||||
starting at n. Finally, subtracting (1 << n) - 1 removes the bits below
|
||||
n from the mask. */
|
||||
uint64_t mask = ((uint64_t)1 << (p + 1)) - 1 - (((uint64_t)1 << n) - 1);
|
||||
|
||||
/* Apply the mask and count the set bits in the result. */
|
||||
uint64_t maskedNumber = number & mask;
|
||||
/* Apply the mask and count the set bits in the result. */
|
||||
uint64_t maskedNumber = number & mask;
|
||||
|
||||
/* Count the bits set in maskedNumber. */
|
||||
uint32_t count = 0;
|
||||
while (maskedNumber) {
|
||||
count += maskedNumber & 1;
|
||||
maskedNumber >>= 1;
|
||||
}
|
||||
/* Count the bits set in maskedNumber. */
|
||||
uint32_t count = 0;
|
||||
while (maskedNumber) {
|
||||
count += maskedNumber & 1;
|
||||
maskedNumber >>= 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
return count;
|
||||
}
|
||||
|
||||
int
|
||||
whats_set_uint64(uint64_t number, int pos[64])
|
||||
{
|
||||
int length = 0;
|
||||
int length = 0;
|
||||
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if (number & ((uint64_t)1 << i)) {
|
||||
pos[length++] = i;
|
||||
}
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if (number & ((uint64_t)1 << i)) {
|
||||
pos[length++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
return length;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -23,6 +23,21 @@
|
|||
#define XORSHIFT_SEED_VALUE ((unsigned int)time(NULL) ^ getpid())
|
||||
#endif
|
||||
|
||||
#define EST_MEDIAN_DECL(decl, size) \
|
||||
uint64_t heap_##decl[size] = { 0 }; \
|
||||
int heap_##decl##_max_size = size; \
|
||||
int heap_##decl##_size = 0;
|
||||
|
||||
#define EST_MEDIAN_ADD(decl, value) est_insert_value(heap_##decl, heap_##decl##_max_size, &heap_##decl##_size, (value));
|
||||
|
||||
#define EST_MEDIAN_GET(decl) heap_##decl[0]
|
||||
|
||||
uint64_t tsc(void);
|
||||
double tsc_ticks_to_ns(uint64_t tsc_ticks);
|
||||
void est_sift_up(uint64_t *heap, int child_index);
|
||||
void est_sift_down(uint64_t *heap, int heap_size, int parent_index);
|
||||
void est_insert_value(uint64_t *heap, int heap_max_size, int *heap_size, uint64_t value);
|
||||
|
||||
void xorshift32_seed();
|
||||
uint32_t xorshift32();
|
||||
|
||||
|
|
226
tests/test.c
226
tests/test.c
|
@ -21,7 +21,6 @@
|
|||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
|
||||
/* !!! Duplicated here for testing purposes. Keep in sync, or suffer. !!! */
|
||||
struct sparsemap {
|
||||
uint8_t *m_data;
|
||||
|
@ -39,7 +38,7 @@ populate_map(sparsemap_t *map, int size, int max_value)
|
|||
int array[size];
|
||||
|
||||
setup_test_array(array, size, max_value);
|
||||
//TODO ensure_sequential_set(array, size, 10);
|
||||
// TODO ensure_sequential_set(array, size, 10);
|
||||
shuffle(array, size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
sparsemap_set(map, array[i], true);
|
||||
|
@ -70,7 +69,7 @@ static MunitResult
|
|||
test_api_static_init(const MunitParameter params[], void *data)
|
||||
{
|
||||
sparsemap_t a_map, *map = &a_map;
|
||||
uint8_t buf[1024] = {0};
|
||||
uint8_t buf[1024] = { 0 };
|
||||
|
||||
(void)params;
|
||||
(void)data;
|
||||
|
@ -215,7 +214,7 @@ test_api_remaining_capacity(const MunitParameter params[], void *data)
|
|||
sparsemap_set(map, i++, true);
|
||||
cap = sparsemap_capacity_remaining(map);
|
||||
} while (cap > 1.0);
|
||||
//assert_true(i == 169985); when seed is 8675309
|
||||
// assert_true(i == 169985); when seed is 8675309
|
||||
assert_true(cap <= 1.0);
|
||||
|
||||
sparsemap_clear(map);
|
||||
|
@ -226,7 +225,7 @@ test_api_remaining_capacity(const MunitParameter params[], void *data)
|
|||
i++;
|
||||
cap = sparsemap_capacity_remaining(map);
|
||||
} while (cap > 2.0);
|
||||
//assert_true(i == 64); when seed is 8675309
|
||||
// assert_true(i == 64); when seed is 8675309
|
||||
assert_true(cap <= 2.0);
|
||||
|
||||
return MUNIT_OK;
|
||||
|
@ -422,7 +421,8 @@ test_api_scan_tear_down(void *fixture)
|
|||
test_api_tear_down(fixture);
|
||||
}
|
||||
void
|
||||
scan_for_0xfeedfacebadcoffee(sm_idx_t v[], size_t n) {
|
||||
scan_for_0xfeedfacebadcoffee(sm_idx_t v[], size_t n)
|
||||
{
|
||||
/* Called multiple times */
|
||||
((void)v);
|
||||
((void)n);
|
||||
|
@ -449,7 +449,7 @@ test_api_split_setup(const MunitParameter params[], void *user_data)
|
|||
sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data);
|
||||
|
||||
sparsemap_init(map, buf, 1024);
|
||||
for(int i = 0; i < 1024; i ++) {
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
sparsemap_set(map, i, true);
|
||||
}
|
||||
return (void *)map;
|
||||
|
@ -465,7 +465,7 @@ static MunitResult
|
|||
test_api_split(const MunitParameter params[], void *data)
|
||||
{
|
||||
sparsemap_t *map = (sparsemap_t *)data;
|
||||
uint8_t buf[1024] = {0};
|
||||
uint8_t buf[1024] = { 0 };
|
||||
sparsemap_t portion;
|
||||
(void)params;
|
||||
|
||||
|
@ -600,58 +600,174 @@ test_api_span(const MunitParameter params[], void *data)
|
|||
|
||||
assert_ptr_not_null(map);
|
||||
|
||||
int located_at, placed_at, amt = 5000;
|
||||
for (int i = 1; i < amt; i++) {
|
||||
for (int j = 1; j < amt / 10; j++) {
|
||||
sparsemap_clear(map);
|
||||
placed_at = create_sequential_set_in_empty_map(map, amt, j);
|
||||
//logf("i = %d, j = %d\tplaced_at %d\n", i, j, placed_at);
|
||||
//whats_set(map, 5000);
|
||||
located_at = sparsemap_span(map, 0, j);
|
||||
if (placed_at != located_at)
|
||||
logf("a: i = %d, j = %d\tplaced_at %d located_at %d\n", i, j, placed_at, located_at);
|
||||
assert_true(located_at == placed_at);
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (int i = 1; i < amt; i++) {
|
||||
for (int j = 1; j < amt / 10; j++) {
|
||||
sparsemap_clear(map);
|
||||
populate_map(map, 1024, 3 * 1024);
|
||||
placed_at = create_sequential_set_in_empty_map(map, amt, j);
|
||||
located_at = sparsemap_span(map, 0, j);
|
||||
if (located_at >= placed_at)
|
||||
logf("b: i = %d, j = %d\tplaced_at %d located_at %d\n", i, j, placed_at, located_at);
|
||||
//assert_true(located_at >= placed_at);
|
||||
located_at = sparsemap_span(map, (placed_at < j ? 0 : placed_at / 2), i);
|
||||
assert_true(placed_at == located_at);
|
||||
}
|
||||
}
|
||||
*/
|
||||
int located_at, placed_at, amt = 10000;
|
||||
|
||||
return MUNIT_OK;
|
||||
placed_at = create_sequential_set_in_empty_map(map, amt, 1);
|
||||
located_at = sparsemap_span(map, 0, 1);
|
||||
assert_true(located_at == placed_at);
|
||||
|
||||
sparsemap_clear(map);
|
||||
|
||||
placed_at = create_sequential_set_in_empty_map(map, amt, 50);
|
||||
located_at = sparsemap_span(map, 0, 50);
|
||||
assert_true(located_at == placed_at);
|
||||
|
||||
sparsemap_clear(map);
|
||||
|
||||
placed_at = create_sequential_set_in_empty_map(map, amt, 50);
|
||||
located_at = sparsemap_span(map, placed_at / 2, 50);
|
||||
assert_true(located_at == placed_at);
|
||||
|
||||
/* TODO
|
||||
sparsemap_clear(map);
|
||||
|
||||
placed_at = create_sequential_set_in_empty_map(map, amt, amt - 1);
|
||||
located_at = sparsemap_span(map, 0, amt - 1);
|
||||
assert_true(located_at == placed_at);
|
||||
*/
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitTest api_test_suite[] = { { (char *)"/api/static_init", test_api_static_init, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/clear", test_api_clear, test_api_clear_setup, test_api_clear_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/open", test_api_open, test_api_open_setup, test_api_open_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/set_data_size", test_api_set_data_size, test_api_set_data_size_setup, test_api_set_data_size_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/remaining_capacity", test_api_remaining_capacity, test_api_remaining_capacity_setup, test_api_remaining_capacity_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/get_range_size", test_api_get_range_size, test_api_get_range_size_setup, test_api_get_range_size_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/is_set", test_api_is_set, test_api_is_set_setup, test_api_is_set_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/set", test_api_set, test_api_set_setup, test_api_set_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/get_start_offset", test_api_get_start_offset, test_api_get_start_offset_setup, test_api_get_start_offset_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/get_size", test_api_get_size, test_api_get_size_setup, test_api_get_size_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/scan", test_api_scan, test_api_scan_setup, test_api_scan_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/split", test_api_split, test_api_split_setup, test_api_split_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/select", test_api_select, test_api_select_setup, test_api_select_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/rank", test_api_rank, test_api_rank_setup, test_api_rank_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/api/span", test_api_span, test_api_span_setup, test_api_span_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
// clang-format off
|
||||
static MunitTest api_test_suite[] = {
|
||||
{ (char *)"/static_init", test_api_static_init, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/clear", test_api_clear, test_api_clear_setup, test_api_clear_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/open", test_api_open, test_api_open_setup, test_api_open_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/set_data_size", test_api_set_data_size, test_api_set_data_size_setup, test_api_set_data_size_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/remaining_capacity", test_api_remaining_capacity, test_api_remaining_capacity_setup, test_api_remaining_capacity_tear_down,
|
||||
MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/get_range_size", test_api_get_range_size, test_api_get_range_size_setup, test_api_get_range_size_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/is_set", test_api_is_set, test_api_is_set_setup, test_api_is_set_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/set", test_api_set, test_api_set_setup, test_api_set_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/get_start_offset", test_api_get_start_offset, test_api_get_start_offset_setup, test_api_get_start_offset_tear_down, MUNIT_TEST_OPTION_NONE,
|
||||
NULL },
|
||||
{ (char *)"/get_size", test_api_get_size, test_api_get_size_setup, test_api_get_size_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/scan", test_api_scan, test_api_scan_setup, test_api_scan_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/split", test_api_split, test_api_split_setup, test_api_split_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/select", test_api_select, test_api_select_setup, test_api_select_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/rank", test_api_rank, test_api_rank_setup, test_api_rank_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/span", test_api_span, test_api_span_setup, test_api_span_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static void *
|
||||
test_perf_span_solo_setup(const MunitParameter params[], void *user_data)
|
||||
{
|
||||
uint8_t *buf = munit_calloc(1024 * 3, sizeof(uint8_t));
|
||||
sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data);
|
||||
|
||||
sparsemap_init(map, buf, 3 * 1024);
|
||||
|
||||
return (void *)map;
|
||||
}
|
||||
static void
|
||||
test_perf_span_solo_tear_down(void *fixture)
|
||||
{
|
||||
sparsemap_t *map = (sparsemap_t *)fixture;
|
||||
free(map->m_data);
|
||||
test_api_tear_down(fixture);
|
||||
}
|
||||
EST_MEDIAN_DECL(solo, 10000)
|
||||
static MunitResult
|
||||
test_perf_span_solo(const MunitParameter params[], void *data)
|
||||
{
|
||||
sparsemap_t *map = (sparsemap_t *)data;
|
||||
uint64_t stop, start;
|
||||
(void)params;
|
||||
int located_at, placed_at, amt = 1000;
|
||||
|
||||
assert_ptr_not_null(map);
|
||||
|
||||
for (int i = 1; i < amt; i++) {
|
||||
for (int j = 1; j < amt / 10; j++) {
|
||||
sparsemap_clear(map);
|
||||
placed_at = create_sequential_set_in_empty_map(map, amt, j);
|
||||
// logf("i = %d, j = %d\tplaced_at %d\n", i, j, placed_at);
|
||||
// whats_set(map, 5000);
|
||||
start = tsc();
|
||||
located_at = sparsemap_span(map, 0, j);
|
||||
stop = tsc();
|
||||
// fprintf(stdout, "%ll - %ll = %ll\n", stop, start, stop - start);
|
||||
EST_MEDIAN_ADD(solo, stop - start);
|
||||
if (placed_at != located_at)
|
||||
logf("a: i = %d, j = %d\tplaced_at %d located_at %d\n", i, j, placed_at, located_at);
|
||||
}
|
||||
}
|
||||
uint64_t est = EST_MEDIAN_GET(solo);
|
||||
fprintf(stdout, "median time %zu or %f ns\n", est, tsc_ticks_to_ns(est)); // measured 228
|
||||
assert_true(EST_MEDIAN_GET(solo) < 500);
|
||||
fflush(stdout);
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static void *
|
||||
test_perf_span_tainted_setup(const MunitParameter params[], void *user_data)
|
||||
{
|
||||
uint8_t *buf = munit_calloc(1024 * 3, sizeof(uint8_t));
|
||||
sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data);
|
||||
|
||||
sparsemap_init(map, buf, 3 * 1024);
|
||||
|
||||
return (void *)map;
|
||||
}
|
||||
static void
|
||||
test_perf_span_tainted_tear_down(void *fixture)
|
||||
{
|
||||
sparsemap_t *map = (sparsemap_t *)fixture;
|
||||
free(map->m_data);
|
||||
test_api_tear_down(fixture);
|
||||
}
|
||||
EST_MEDIAN_DECL(tainted, 10000)
|
||||
static MunitResult
|
||||
test_perf_span_tainted(const MunitParameter params[], void *data)
|
||||
{
|
||||
sparsemap_t *map = (sparsemap_t *)data;
|
||||
uint64_t stop, start;
|
||||
(void)params;
|
||||
|
||||
assert_ptr_not_null(map);
|
||||
|
||||
int located_at, placed_at, amt = 1000;
|
||||
for (int i = 1; i < amt; i++) {
|
||||
for (int j = 1; j < amt / 10; j++) {
|
||||
sparsemap_clear(map);
|
||||
populate_map(map, 1024, 1 * 1024);
|
||||
placed_at = create_sequential_set_in_empty_map(map, amt, j);
|
||||
start = tsc();
|
||||
located_at = sparsemap_span(map, 0, j);
|
||||
stop = tsc();
|
||||
EST_MEDIAN_ADD(tainted, stop - start);
|
||||
if (located_at >= placed_at)
|
||||
logf("b: i = %d, j = %d\tplaced_at %d located_at %d\n", i, j, placed_at, located_at);
|
||||
// assert_true(located_at >= placed_at);
|
||||
//start = tsc();
|
||||
//located_at = sparsemap_span(map, (placed_at < j ? 0 : placed_at / 2), i);
|
||||
//stop = tsc();
|
||||
//EST_MEDIAN_ADD(solo, stop - start);
|
||||
// assert_true(placed_at == located_at);
|
||||
}
|
||||
}
|
||||
uint64_t est = EST_MEDIAN_GET(tainted);
|
||||
fprintf(stdout, "median time %zu or %f ns\n", est, tsc_ticks_to_ns(est)); // measured 228
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
static MunitTest performance_test_suite[] = {
|
||||
{ (char *)"/span/solo", test_perf_span_solo, test_perf_span_solo_setup, test_perf_span_solo_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char *)"/span/tainted", test_perf_span_tainted, test_perf_span_tainted_setup, test_perf_span_tainted_tear_down, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } };
|
||||
// clang-format on
|
||||
|
||||
static MunitTest scale_tests[] = { { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } };
|
||||
|
||||
static MunitSuite other_test_suite[] = { { "/scale", scale_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE }, { NULL, NULL, NULL, 0, MUNIT_SUITE_OPTION_NONE } };
|
||||
// clang-format off
|
||||
static MunitSuite other_test_suite[] = {
|
||||
{ "/performance", performance_test_suite, NULL, 1, MUNIT_SUITE_OPTION_NONE },
|
||||
{ NULL, NULL, NULL, 0, MUNIT_SUITE_OPTION_NONE } };
|
||||
// clang-format on
|
||||
|
||||
static const MunitSuite main_test_suite = { (char *)"/api", api_test_suite, other_test_suite, 1, MUNIT_SUITE_OPTION_NONE };
|
||||
|
||||
|
|
Loading…
Reference in a new issue