5#include "testing/testing.h"
32static void print_mem_saved(
const char *
id,
const BArrayStore *bs)
36 const double percent = size_expand ? ((size_real / size_expand) * 100.0) : -1.0;
37 printf(
"%s: %.8f%%\n",
id, percent);
64 memcpy(data_copy,
data, data_len);
80static char *testchunk_as_data(
ListBase *lb,
size_t *r_data_len)
84 data_len += tc->data_len;
89 memcpy(&
data[
i], tc->data, tc->data_len);
90 data_len += tc->data_len;
103 for (
int tc_index = 0; tc_index < tc_array_len; tc_index++) {
104 data_len += tc_array[tc_index]->
data_len;
108 for (
int tc_index = 0; tc_index < tc_array_len; tc_index++) {
145 memcpy(data_copy,
data, data_len);
160 const size_t data_len,
167 const size_t data_stride_len = data_len * stride;
170 for (
size_t i = 0, i_stride = 0;
i < data_len;
i += 1, i_stride += stride) {
171 memset(&data_stride[i_stride],
data[
i], stride);
178#define testbuffer_list_state_from_string_array(lb, data_array) \
182 while ((data = data_array[i_++])) { \
183 testbuffer_list_state_from_data(lb, data, strlen(data)); \
190#define TESTBUFFER_STRINGS_CREATE(lb, ...) \
192 BLI_listbase_clear(lb); \
193 const char *data_array[] = {__VA_ARGS__ nullptr}; \
194 testbuffer_list_state_from_string_array((lb), data_array); \
199#define TESTBUFFER_STRINGS(stride, chunk_count, ...) \
202 TESTBUFFER_STRINGS_CREATE(&lb, __VA_ARGS__); \
204 testbuffer_run_tests_simple(&lb, stride, chunk_count); \
206 testbuffer_list_free(&lb); \
212 size_t data_state_len;
215 if (tb->
data_len != data_state_len) {
218 else if (memcmp(data_state, tb->
data, data_state_len) != 0) {
246 tb_prev = tb, tb = tb->next)
249 bs, tb->data, tb->data_len, (tb_prev ? tb_prev->state :
nullptr));
277 print_mem_saved(
"data", bs);
324 const char data_src[] =
"test";
325 const char *data_dst;
329 EXPECT_STREQ(data_src, data_dst);
330 EXPECT_EQ(data_dst_len,
sizeof(data_src));
338 const char data_src[] =
"test";
339 const char *data_dst;
350 EXPECT_STREQ(data_src, data_dst);
354 EXPECT_STREQ(data_src, data_dst);
357 EXPECT_EQ(data_dst_len,
sizeof(data_src));
364 const char data_src_a[] =
"test";
365 const char data_src_b[] =
"####";
366 const char *data_dst;
376 EXPECT_STREQ(data_src_a, data_dst);
380 EXPECT_STREQ(data_src_b, data_dst);
396TEST(array_store, TextDupeIncreaseDecrease)
436 const char word_delim,
438 const int chunk_count,
439 const int random_seed)
445 for (
int i = 0, i_prev = 0;
i < words_len;
i++) {
446 if (
ELEM(words[
i], word_delim,
'\0')) {
464#define WORDS words10k, sizeof(words10k)
465TEST(array_store, TextSentences_Chunk1)
469TEST(array_store, TextSentences_Chunk2)
473TEST(array_store, TextSentences_Chunk8)
477TEST(array_store, TextSentences_Chunk32)
481TEST(array_store, TextSentences_Chunk128)
485TEST(array_store, TextSentences_Chunk1024)
490TEST(array_store, TextSentences_Chunk3)
494TEST(array_store, TextSentences_Chunk13)
498TEST(array_store, TextSentences_Chunk131)
504TEST(array_store, TextWords_Chunk1)
508TEST(array_store, TextWords_Chunk2)
512TEST(array_store, TextWords_Chunk8)
516TEST(array_store, TextWords_Chunk32)
520TEST(array_store, TextWords_Chunk128)
524TEST(array_store, TextWords_Chunk1024)
529TEST(array_store, TextWords_Chunk3)
533TEST(array_store, TextWords_Chunk13)
537TEST(array_store, TextWords_Chunk131)
543TEST(array_store, TextSentencesRandom_Stride3_Chunk3)
547TEST(array_store, TextSentencesRandom_Stride8_Chunk8)
551TEST(array_store, TextSentencesRandom_Stride32_Chunk1)
555TEST(array_store, TextSentencesRandom_Stride12_Chunk512)
559TEST(array_store, TextSentencesRandom_Stride128_Chunk6)
579 return min_i + value;
584 const size_t data_min_len,
585 const size_t data_max_len,
590 size_t data_len =
rand_range_i(rng, data_min_len, data_max_len + stride, stride);
593 if (lb->
last ==
nullptr) {
598 if (tb_last->
data_len >= data_len) {
599 memcpy(
data, tb_last->
data, data_len);
607 for (
int i = 0;
i < mutate;
i++) {
623 if (data_len < data_max_len) {
626 memmove(&
data[offset + stride], &
data[offset], data_len - (offset + stride));
631 case MUTATE_REMOVE: {
633 if (data_len > data_min_len) {
634 memmove(&
data[offset], &
data[offset + stride], data_len - (offset + stride));
639 case MUTATE_ROTATE: {
640 int items = data_len / stride;
646 case MUTATE_RANDOMIZE: {
663 const int items_size_max,
664 const int items_total,
666 const int chunk_count,
667 const int random_seed,
674 const size_t data_min_len = items_size_min * stride;
675 const size_t data_max_len = items_size_max * stride;
679 for (
int i = 0;
i < items_total;
i++) {
690TEST(array_store, TestData_Stride1_Chunk32_Mutate2)
694TEST(array_store, TestData_Stride8_Chunk512_Mutate2)
698TEST(array_store, TestData_Stride12_Chunk48_Mutate2)
702TEST(array_store, TestData_Stride32_Chunk64_Mutate1)
706TEST(array_store, TestData_Stride32_Chunk64_Mutate8)
715 const int chunks_per_buffer,
717 const int chunk_count,
718 const int random_seed)
721 const size_t chunk_size_bytes = stride * chunk_count;
722 for (
int i = 0;
i < chunks_per_buffer;
i++) {
734 const int items_total,
736 const int chunk_count,
737 const int random_seed)
747 for (
int i = 0;
i < chunks_per_buffer;
i++, tc = tc->
next) {
748 chunks_array[
i] = tc;
758 for (
int i = 0;
i < items_total;
i++) {
762 BLI_assert(data_len == chunks_per_buffer * chunk_count * stride);
774 size_t expected_size = chunks_per_buffer * chunk_count * stride;
782TEST(array_store, TestChunk_Rand8_Stride1_Chunk64)
786TEST(array_store, TestChunk_Rand32_Stride1_Chunk64)
790TEST(array_store, TestChunk_Rand64_Stride8_Chunk32)
794TEST(array_store, TestChunk_Rand31_Stride11_Chunk21)
805 size_t *r_data_enc_len)
829 const bool eq = memcmp(data_dec, data_dec_copy, data_dec_len) == 0;
831 if (r_data_enc_len) {
832 *r_data_enc_len = data_enc_len;
841 const size_t span_size,
842 const int permitations)
850 for (
int i = 0;
i < data_size;
i++) {
851 data_pattern[
i] =
i % 2;
855 const size_t data_enc_no_rle_len = [&data_pattern, &data_size]() ->
size_t {
861 for (
int mutaiton = 0; mutaiton < permitations; mutaiton++) {
862 memcpy(
data, data_pattern, data_size);
869 else if (mutaiton == 1) {
870 index = int(data_size) - span_size;
877 memset(
data + index, 0, span_size);
883 const size_t data_enc_len_expected_max = (data_enc_no_rle_len - span_size) +
884 (
sizeof(
size_t[2]) * 2);
885 EXPECT_LE(data_enc_len, data_enc_len_expected_max);
894 const size_t data_ratio_size,
895 const int permitations)
900 for (
int mutaiton = 0; mutaiton < permitations; mutaiton++) {
901 memset(
data, 1, data_ratio_size);
902 memset(
data + data_ratio_size, 0, data_size - data_ratio_size);
923 const uint8_t
data[] = {0};
927 const uint8_t
data[] = {0};
931 const uint8_t
data[] = {1};
938 const uint8_t data_uniform[64] = {0};
939 uint8_t data_pattern[64] = {0};
940 for (
int i = 0;
i <
sizeof(data_pattern);
i += 2) {
944 size_t data_uniform_enc_len = 0;
945 size_t data_pattern_enc_len = 0;
953 EXPECT_EQ(data_uniform_enc_len,
sizeof(
size_t) +
sizeof(uint8_t) +
sizeof(
size_t[2]));
954 EXPECT_EQ(data_pattern_enc_len,
sizeof(data_uniform) +
sizeof(
size_t[4]));
957TEST(array_store, RLE_Alignment)
961 const size_t data_len_max =
sizeof(
void *) * 8;
963 for (
size_t i = 0;
i < data_len_max;
i += 2) {
971 for (
int data_len = 1; data_len < data_len_max; data_len += 1) {
972 uint8_t *
data =
static_cast<uint8_t *
>(malloc(data_len));
973 for (
size_t offset = 0; offset <
sizeof(
void *); offset += 1) {
974 uint8_t *data_offset =
data + offset;
975 if (data_len <= offset) {
978 const size_t data_offset_len = data_len - offset;
979 memset(
data, 0, data_offset_len);
985 memcpy(data_offset, data_pattern, data_offset_len);
993TEST(array_store, RLE_RandomSpan)
996 const bool do_stress_test =
false;
998 const int permutations = do_stress_test ? 256 : 8;
1012 if (do_stress_test) {
1013 const int data_size_max = 256;
1014 const int margin =
sizeof(
size_t[2]);
1015 for (
int data_size = margin; data_size < data_size_max; data_size++) {
1016 for (
int span_size = 1; span_size < data_size - margin; span_size++) {
1026 const bool do_stress_test =
false;
1028 const int permutations = do_stress_test ? 256 : 8;
1040 if (do_stress_test) {
1041 const int data_size_max = 256;
1042 const int margin =
sizeof(
size_t[2]);
1043 for (
int data_size = margin; data_size < data_size_max; data_size++) {
1044 for (
int data_ratio_size = 1; data_ratio_size < data_size - 1; data_ratio_size++) {
1050 if (do_stress_test) {
1052 const size_t data_len_large = 32000000;
1068static void *file_read_binary_as_mem(
const char *filepath,
size_t pad_bytes,
size_t *r_size)
1070 FILE *fp = fopen(filepath,
"rb");
1071 void *mem =
nullptr;
1074 long int filelen_read;
1075 fseek(fp, 0
L, SEEK_END);
1076 const long int filelen = ftell(fp);
1077 if (filelen == -1) {
1080 fseek(fp, 0
L, SEEK_SET);
1083 if (mem ==
nullptr) {
1087 filelen_read = fread(mem, 1, filelen, fp);
1088 if ((filelen_read != filelen) || ferror(fp)) {
1094 *r_size = filelen_read;
1103TEST(array_store, PlainTextFiles)
1109 for (
int i = 0;
i < 629;
i++) {
1116 data = file_read_binary_as_mem(
str, 0, &data_len);
1126 print_mem_saved(
"source code forward", bs);
1137 print_mem_saved(
"source code backwards", bs);
Efficient in-memory storage of multiple similar arrays.
BArrayState * BLI_array_store_state_add(BArrayStore *bs, const void *data, size_t data_len, const BArrayState *state_reference)
void BLI_array_store_state_remove(BArrayStore *bs, BArrayState *state)
size_t BLI_array_store_calc_size_expanded_get(const BArrayStore *bs)
void * BLI_array_store_state_data_get_alloc(const BArrayState *state, size_t *r_data_len)
bool BLI_array_store_is_valid(BArrayStore *bs)
void BLI_array_store_rle_decode(const uint8_t *data_enc, const size_t data_enc_len, void *data_dec_v, const size_t data_dec_len)
size_t BLI_array_store_state_size_get(const BArrayState *state)
void BLI_array_store_destroy(BArrayStore *bs)
size_t BLI_array_store_calc_size_compacted_get(const BArrayStore *bs)
uint8_t * BLI_array_store_rle_encode(const uint8_t *data_dec, size_t data_dec_len, size_t data_enc_extra_size, size_t *r_data_enc_len)
BArrayStore * BLI_array_store_create(unsigned int stride, unsigned int chunk_count)
static void random_data_mutate_helper(const int items_size_min, const int items_size_max, const int items_total, const int stride, const int chunk_count, const int random_seed, const int mutate)
#define TESTBUFFER_STRINGS(stride, chunk_count,...)
static void testbuffer_list_state_from_data__stride_expand(ListBase *lb, const char *data, const size_t data_len, const size_t stride)
static bool rle_encode_decode_test(const uint8_t *data_dec, size_t data_dec_len, size_t *r_data_enc_len)
#define TESTBUFFER_STRINGS_CREATE(lb,...)
static TestChunk * testchunk_list_add(ListBase *lb, const void *data, size_t data_len)
static void testbuffer_list_state_random_data(ListBase *lb, const size_t stride, const size_t data_min_len, const size_t data_max_len, const uint mutate, RNG *rng)
static void testbuffer_list_store_populate(BArrayStore *bs, ListBase *lb)
static void testbuffer_list_store_clear(BArrayStore *bs, ListBase *lb)
static bool testbuffer_item_validate(TestBuffer *tb)
static void testbuffer_list_data_randomize(ListBase *lb, uint random_seed)
static void array_store_test_random_span_rle_encode(const size_t data_size, const size_t span_size, const int permitations)
static TestBuffer * testbuffer_list_add_copydata(ListBase *lb, const void *data, size_t data_len)
static void random_chunk_mutate_helper(const int chunks_per_buffer, const int items_total, const int stride, const int chunk_count, const int random_seed)
static void testbuffer_run_tests(BArrayStore *bs, ListBase *lb)
static void testchunk_list_free(ListBase *lb)
static void testbuffer_run_tests_single(BArrayStore *bs, ListBase *lb)
static bool testbuffer_list_validate(const ListBase *lb)
static void array_store_test_random_data_rle_encode(const size_t data_size, const size_t data_ratio_size, const int permitations)
static void random_chunk_generate(ListBase *lb, const int chunks_per_buffer, const int stride, const int chunk_count, const int random_seed)
static TestBuffer * testbuffer_list_add(ListBase *lb, const void *data, size_t data_len)
static char * testchunk_as_data_array(TestChunk **tc_array, int tc_array_len, size_t *r_data_len)
static void testbuffer_list_state_from_data(ListBase *lb, const char *data, const size_t data_len)
static void plain_text_helper(const char *words, int words_len, const char word_delim, const int stride, const int chunk_count, const int random_seed)
static void testbuffer_run_tests_simple(ListBase *lb, const int stride, const int chunk_count)
static void testbuffer_list_free(ListBase *lb)
static uint rand_range_i(RNG *rng, uint min_i, uint max_i, uint step)
Generic array manipulation API.
void _bli_array_wrap(void *arr_v, uint arr_len, size_t arr_stride, int dir)
#define BLI_assert_unreachable()
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
void BLI_kdtree_nd_ free(KDTree *tree)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void void void void void void void BLI_listbase_reverse(ListBase *lb) ATTR_NONNULL(1)
void int BLI_rng_get_int(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_rng_shuffle_array(struct RNG *rng, void *data, unsigned int elem_size_i, unsigned int elem_num) ATTR_NONNULL(1
struct RNG * BLI_rng_new(unsigned int seed)
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
unsigned int BLI_rng_get_uint(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_rng_get_char_n(RNG *rng, char *bytes, size_t bytes_len) ATTR_NONNULL(1
void BLI_array_randomize(void *data, unsigned int elem_size, unsigned int elem_num, unsigned int seed)
size_t BLI_snprintf(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
Platform independent time functions.
Utility defines for timing/benchmarks.
#define TIMEIT_START(var)
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
BMesh const char void * data
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
void * MEM_mallocN(size_t len, const char *str)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)