During work collecting regressions statistics for #78852 I did some profiling on performance tests included in native EventPipe tests, https://github.com/dotnet/runtime/blob/main/src/mono/mono/eventpipe/test. This commit implements a couple of optimizations in the EventPipe native container classes as well as Mono's EventPipe implementation improving performance in low level native EventPipe performance tests.
Commit also includes a number of new native EventPipe tests covering optimizations done in dn_vector_ptr_t.
ep_rt_valloc0 (size_t buffer_size)
{
uint8_t *buffer = (uint8_t *)mono_valloc (NULL, buffer_size, MONO_MMAP_READ | MONO_MMAP_WRITE, MONO_MEM_ACCOUNT_PROFILER);
-
- if (buffer)
- memset (buffer, 0, buffer_size);
+#ifdef EP_CHECKED_BUILD
+ for (size_t i = 0; i < buffer_size; i++)
+ EP_ASSERT (buffer [i] == 0);
+#endif
return buffer;
}
NULL
};
+static void *test_vector_ptr_last_disposed_value = 0;
+static int32_t test_vector_ptr_dispose_call_count = 0;
+
+static
+void
+DN_CALLBACK_CALLTYPE
+test_vector_ptr_dispose_call_func(void *data)
+{
+ test_vector_ptr_last_disposed_value = *((void **)data);
+ test_vector_ptr_dispose_call_count++;
+}
+
static int32_t test_vector_ptr_foreach_iterate_index = 0;
static char *test_vector_ptr_foreach_iterate_error = NULL;
static
dn_vector_ptr_t *
-vector_ptr_alloc_and_fill (uint32_t *item_count)
+vector_ptr_alloc_and_fill (dn_vector_ptr_t *vector, uint32_t *item_count)
{
- dn_vector_ptr_t *vector = dn_vector_ptr_alloc ();
int32_t i;
+ if (!vector)
+ vector = dn_vector_ptr_alloc ();
for(i = 0; test_vector_ptr_items [i] != NULL; i++) {
dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [i]);
dn_vector_ptr_t *vector;
uint32_t i;
- vector = vector_ptr_alloc_and_fill (&i);
+ vector = vector_ptr_alloc_and_fill (NULL, &i);
if (dn_vector_ptr_capacity (vector) != vector_ptr_guess_capacity (vector->size)) {
return FAILED ("capacity should be %d, but it is %d",
RESULT
test_vector_ptr_for_iterate (void)
{
- dn_vector_ptr_t *vector = vector_ptr_alloc_and_fill (NULL);
+ dn_vector_ptr_t *vector = vector_ptr_alloc_and_fill (NULL, NULL);
uint32_t i = 0;
DN_VECTOR_PTR_FOREACH_BEGIN (char *, item, vector) {
RESULT
test_vector_ptr_foreach_iterate (void)
{
- dn_vector_ptr_t *vector = vector_ptr_alloc_and_fill (NULL);
+ dn_vector_ptr_t *vector = vector_ptr_alloc_and_fill (NULL, NULL);
test_vector_ptr_foreach_iterate_index = 0;
test_vector_ptr_foreach_iterate_error = NULL;
test_vector_ptr_resize (void)
{
dn_vector_ptr_t *vector= dn_vector_ptr_alloc ();
+ uint32_t grow_length = 50;
+
+ dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [0]);
+ dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [1]);
+ dn_vector_ptr_resize (vector, grow_length);
+
+ if (vector->size != grow_length) {
+ return FAILED ("vector size should be 50, it is %d", vector->size);
+ } else if (*dn_vector_ptr_index (vector, 0) != test_vector_ptr_items [0]) {
+ return FAILED ("item 0 was overwritten, should be %s", test_vector_ptr_items [0]);
+ } else if (*dn_vector_ptr_index (vector, 1) != test_vector_ptr_items [1]) {
+ return FAILED ("item 1 was overwritten, should be %s", test_vector_ptr_items [1]);
+ }
+
+ dn_vector_ptr_free (vector);
+
+ return OK;
+}
+
+static
+RESULT
+test_vector_ptr_resize_2 (void)
+{
+ dn_vector_ptr_custom_alloc_params_t params = {0,};
+ params.attributes = DN_VECTOR_ATTRIBUTE_MEMORY_INIT;
+
+ dn_vector_ptr_t *vector= dn_vector_ptr_custom_alloc (¶ms);
uint32_t i, grow_length = 50;
dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [0]);
static
RESULT
-test_vector_ptr_erase (void)
+test_vector_ptr_push_back (void)
{
- dn_vector_ptr_t *vector;
- uint32_t i;
+ int32_t v;
+ dn_vector_ptr_t *vector = dn_vector_ptr_alloc ();
+ if (vector->size != 0)
+ return FAILED ("vector size didn't match");
+
+ v = 27;
+
+ dn_vector_ptr_push_back (vector, INT32_TO_POINTER (v));
+
+ if (1 != vector->size)
+ return FAILED ("vector push_back failed");
+
+ if (v != POINTER_TO_INT32 (*dn_vector_ptr_index (vector, 0)))
+ return FAILED ("dn_vector_index failed");
+
+ dn_vector_ptr_free (vector);
+
+ return OK;
+}
+
+static
+RESULT
+test_vector_ptr_push_back_2 (void)
+{
+ dn_vector_ptr_t *vector = dn_vector_ptr_alloc ();
+ if (vector->size != 0)
+ return FAILED ("vector size didn't match");
+
+ for (int32_t i = 0; i < 10; ++i)
+ dn_vector_ptr_push_back (vector, INT32_TO_POINTER (i));
+
+ for (uint32_t i = 0; i < vector->size; ++i) {
+ if (i != POINTER_TO_INT32 (*dn_vector_ptr_index (vector, i)))
+ return FAILED ("vector push_back failed");
+ }
+
+ dn_vector_ptr_free (vector);
+
+ return OK;
+}
+
+static
+RESULT
+test_vector_ptr_pop_back (void)
+{
+ dn_vector_ptr_t *vector = dn_vector_ptr_alloc ();
+ if (vector->size != 0)
+ return FAILED ("vector size didn't match");
+
+ for (int32_t i = 0; i < 10; ++i)
+ dn_vector_ptr_push_back (vector, INT32_TO_POINTER (i));
+
+ if (POINTER_TO_INT32 (*dn_vector_ptr_back (vector)) != 9)
+ return FAILED ("vector back failed");
+
+ dn_vector_ptr_pop_back (vector);
+
+ if (POINTER_TO_INT32 (*dn_vector_ptr_back (vector)) != 8)
+ return FAILED ("vector pop_back failed");
+
+ dn_vector_ptr_pop_back (vector);
+
+ if (POINTER_TO_INT32 (*dn_vector_ptr_back (vector)) != 7)
+ return FAILED ("vector pop_back failed");
+
+ dn_vector_ptr_free (vector);
- vector = vector_ptr_alloc_and_fill (&i);
+ return OK;
+}
+
+static
+RESULT
+test_vector_ptr_pop_back_2 (void)
+{
+ dn_vector_ptr_t *vector = dn_vector_ptr_alloc ();
+ if (vector->size != 0)
+ return FAILED ("vector size didn't match");
+
+ for (int32_t i = 0; i < 10; ++i)
+ dn_vector_ptr_push_back (vector, INT32_TO_POINTER (i));
+
+ if (POINTER_TO_INT32 (*dn_vector_ptr_back (vector)) != 9)
+ return FAILED ("vector back failed");
+
+ test_vector_ptr_last_disposed_value = 0;
+ dn_vector_ptr_custom_pop_back (vector, test_vector_ptr_dispose_call_func);
+ if (POINTER_TO_INT32 (test_vector_ptr_last_disposed_value) != 9)
+ return FAILED ("vector custom_pop_back failed, wrong disposed value #1");
+
+ if (POINTER_TO_INT32 (*dn_vector_ptr_back (vector)) != 8)
+ return FAILED ("vector pop_back failed");
+
+ test_vector_ptr_last_disposed_value = 0;
+ dn_vector_ptr_custom_pop_back (vector, test_vector_ptr_dispose_call_func);
+ if (POINTER_TO_INT32 (test_vector_ptr_last_disposed_value) != 8)
+ return FAILED ("vector custom_pop_back failed, wrong disposed value #2");
+
+ if (POINTER_TO_INT32 (*dn_vector_ptr_back (vector)) != 7)
+ return FAILED ("vector pop_back failed");
+
+ dn_vector_ptr_free (vector);
+
+ return OK;
+}
+
+static
+RESULT
+test_vector_ptr_erase (void)
+{
+ dn_vector_ptr_t * vector = vector_ptr_alloc_and_fill (NULL, NULL);
dn_vector_ptr_erase (dn_vector_ptr_begin (vector));
if (*dn_vector_ptr_index (vector, 0) != test_vector_ptr_items [1]) {
RESULT
test_vector_ptr_erase_fast (void)
{
- dn_vector_ptr_t *vector;
- uint32_t i;
-
- vector = vector_ptr_alloc_and_fill (&i);
+ dn_vector_ptr_t *vector = vector_ptr_alloc_and_fill (NULL, NULL);
dn_vector_ptr_erase_fast (dn_vector_ptr_begin (vector));
if (*dn_vector_ptr_index (vector, 0) != test_vector_ptr_items [vector->size]) {
return OK;
}
+static
+RESULT
+test_vector_ptr_erase_fast_2 (void)
+{
+ dn_vector_ptr_t *vector = vector_ptr_alloc_and_fill (NULL, NULL);
+
+ test_vector_ptr_last_disposed_value = NULL;
+ dn_vector_ptr_custom_erase_fast (dn_vector_ptr_it_next_n (dn_vector_ptr_begin (vector), 3), test_vector_ptr_dispose_call_func);
+ if (test_vector_ptr_last_disposed_value != test_vector_ptr_items [3])
+ return FAILED ("custom erase failed to dispose correct value");
+
+ dn_vector_ptr_free (vector);
+
+ return OK;
+}
+
+static
+RESULT
+test_vector_ptr_erase_fast_3 (void)
+{
+ dn_vector_ptr_t vector;
+ dn_vector_ptr_init (&vector);
+ vector_ptr_alloc_and_fill (&vector, NULL);
+
+ dn_vector_ptr_erase_fast (dn_vector_ptr_begin (&vector));
+
+ if (vector.data [dn_vector_ptr_size (&vector)] == NULL)
+ return FAILED ("erase initialized memory, but shouldn't.");
+
+ dn_vector_ptr_dispose (&vector);
+
+ dn_vector_ptr_custom_alloc_params_t params = {0, };
+ params.attributes = DN_VECTOR_ATTRIBUTE_MEMORY_INIT;
+
+ dn_vector_ptr_custom_init (&vector, ¶ms);
+ vector_ptr_alloc_and_fill (&vector, NULL);
+
+ dn_vector_ptr_erase_fast (dn_vector_ptr_begin (&vector));
+
+ if (vector.data [dn_vector_ptr_size (&vector)] != NULL)
+ return FAILED ("erase didn't initialize memory, but should");
+
+ dn_vector_ptr_dispose (&vector);
+
+ return OK;
+}
+
static
RESULT
test_vector_ptr_capacity (void)
{
uint32_t size;
- dn_vector_ptr_t *vector = vector_ptr_alloc_and_fill (&size);
+ dn_vector_ptr_t *vector = vector_ptr_alloc_and_fill (NULL, &size);
if (dn_vector_ptr_capacity (vector) < size)
return FAILED ("invalid vector capacity #1");
dn_vector_ptr_custom_alloc_params_t params = {0, };
params.allocator = (dn_allocator_t *)&allocator;
- uint32_t init_capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size);
+ uint32_t init_capacity = dn_vector_ptr_default_local_allocator_capacity_size;
dn_vector_ptr_t *vector = dn_vector_ptr_custom_alloc (¶ms);
if (!vector)
return FAILED ("failed vector custom alloc");
dn_allocator_fixed_or_malloc_init (&allocator, buffer, dn_vector_ptr_default_local_allocator_byte_size);
memset (buffer, 0, dn_vector_ptr_default_local_allocator_byte_size);
- uint32_t init_capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size);
-
dn_vector_ptr_custom_alloc_params_t params = {0, };
params.allocator = (dn_allocator_t *)&allocator;
- params.capacity = init_capacity;
+ params.capacity = dn_vector_ptr_default_local_allocator_capacity_size;
dn_vector_ptr_t *vector = dn_vector_ptr_custom_alloc (¶ms);
if (!vector)
dn_allocator_fixed_init (&allocator, buffer, dn_vector_ptr_default_local_allocator_byte_size);
memset (buffer, 0, dn_vector_ptr_default_local_allocator_byte_size);
- uint32_t init_capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size);
-
dn_vector_ptr_custom_alloc_params_t params = {0, };
params.allocator = (dn_allocator_t *)&allocator;
- params.capacity = init_capacity;
+ params.capacity = dn_vector_ptr_default_local_allocator_capacity_size;
dn_vector_ptr_t *vector = dn_vector_ptr_custom_alloc (¶ms);
if (!vector)
dn_allocator_fixed_or_malloc_init (&allocator, buffer, dn_vector_ptr_default_local_allocator_byte_size);
memset (buffer, 0, dn_vector_ptr_default_local_allocator_byte_size);
- uint32_t init_capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size);
-
dn_vector_ptr_custom_alloc_params_t params = {0, };
params.allocator = (dn_allocator_t *)&allocator;
- params.capacity = init_capacity;
+ params.capacity = dn_vector_ptr_default_local_allocator_capacity_size;
dn_vector_ptr_t *vector = dn_vector_ptr_custom_alloc (¶ms);
if (!vector)
if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [0]))
return FAILED ("failed vector push_back using custom alloc #2");
- if (dn_vector_ptr_capacity (vector) <= init_capacity)
+ if (dn_vector_ptr_capacity (vector) <= dn_vector_ptr_default_local_allocator_capacity_size)
return FAILED ("unexpected vector capacity #1");
- init_capacity = dn_vector_ptr_capacity (vector);
+ uint32_t init_capacity = dn_vector_ptr_capacity (vector);
// Make room for on more item.
dn_vector_ptr_pop_back (vector);
dn_allocator_fixed_init (&allocator, buffer, dn_vector_ptr_default_local_allocator_byte_size);
memset (buffer, 0, dn_vector_ptr_default_local_allocator_byte_size);
- uint32_t init_capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size);
-
dn_vector_ptr_custom_alloc_params_t params = {0, };
params.allocator = (dn_allocator_t *)&allocator;
- params.capacity = init_capacity;
+ params.capacity = dn_vector_ptr_default_local_allocator_capacity_size;
dn_vector_ptr_t *vector = dn_vector_ptr_custom_alloc (¶ms);
if (!vector)
dn_allocator_fixed_or_malloc_init (&allocator, buffer, dn_vector_ptr_default_local_allocator_byte_size);
memset (buffer, 0, dn_vector_ptr_default_local_allocator_byte_size);
- uint32_t init_capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size);
-
dn_vector_ptr_custom_alloc_params_t params = {0, };
params.allocator = (dn_allocator_t *)&allocator;
- params.capacity = init_capacity;
+ params.capacity = dn_vector_ptr_default_local_allocator_capacity_size;
dn_vector_ptr_t *vector = dn_vector_ptr_custom_alloc (¶ms);
if (!vector)
{"test_vector_ptr_for_iterate", test_vector_ptr_for_iterate},
{"test_vector_ptr_foreach_iterate", test_vector_ptr_foreach_iterate},
{"test_vector_ptr_resize", test_vector_ptr_resize},
+ {"test_vector_ptr_resize_2", test_vector_ptr_resize_2},
+ {"test_vector_ptr_push_back", test_vector_ptr_push_back},
+ {"test_vector_ptr_push_back_2", test_vector_ptr_push_back_2},
+ {"test_vector_ptr_pop_back", test_vector_ptr_pop_back},
+ {"test_vector_ptr_pop_back_2", test_vector_ptr_pop_back_2},
{"test_vector_ptr_erase", test_vector_ptr_erase},
{"test_vector_ptr_erase_fast", test_vector_ptr_erase_fast},
+ {"test_vector_ptr_erase_fast_2", test_vector_ptr_erase_fast_2},
+ {"test_vector_ptr_erase_fast_3", test_vector_ptr_erase_fast_3},
{"test_vector_ptr_capacity", test_vector_ptr_capacity},
{"test_vector_ptr_custom_free", test_vector_ptr_custom_free},
{"test_vector_ptr_clear", test_vector_ptr_clear},
dn_vector_custom_alloc_params_t params = {0,};
params.capacity = 32;
- params.attributes = DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT;
vector = dn_vector_custom_alloc_t (¶ms, int32_t);
if (vector->size != 0)
dn_vector_t *vector = NULL;
dn_vector_custom_alloc_params_t params = {0, };
+ params.attributes = DN_VECTOR_ATTRIBUTE_MEMORY_INIT;
params.capacity = PREALLOC_SIZE;
vector = dn_vector_custom_alloc_t (¶ms, int32_t);
{
dn_vector_t vector;
dn_vector_custom_init_params_t params = {0, };
+ params.attributes = DN_VECTOR_ATTRIBUTE_MEMORY_INIT;
params.capacity = PREALLOC_SIZE;
if (!dn_vector_custom_init_t (&vector, ¶ms, int32_t))
if (vector->size != 0)
return FAILED ("vector size didn't match");
+ int32_t value = INT32_MAX;
for (int32_t i = 0; i < 10; ++i)
- dn_vector_push_back (vector, i);
+ dn_vector_push_back (vector, value);
dn_vector_erase (dn_vector_begin (vector));
- if (((uint32_t *)vector->data) [9] != 0)
- return FAILED ("erase didn't zero memory.");
+ if (((uint32_t *)vector->data) [9] == 0)
+ return FAILED ("erase initialized memory, but shouldn't.");
dn_vector_free (vector);
dn_vector_custom_alloc_params_t params = {0, };
- params.attributes = DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT;
+ params.attributes = DN_VECTOR_ATTRIBUTE_MEMORY_INIT;
vector = dn_vector_custom_alloc_t (¶ms, int32_t);
for (int32_t i = 0; i < 10; ++i)
- dn_vector_push_back (vector, i);
+ dn_vector_push_back (vector, value);
dn_vector_erase (dn_vector_begin (vector));
- if (((uint32_t *)vector->data) [9] == 0)
- return FAILED ("resize zeroed memory, but shouldn't.");
+ if (((uint32_t *)vector->data) [9] != 0)
+ return FAILED ("erase didn't initialize memory, but should");
dn_vector_free (vector);
if (vector->size != 0)
return FAILED ("vector size didn't match");
+ int32_t value = INT32_MAX;
+
for (int32_t i = 0; i < 10; ++i)
- dn_vector_push_back (vector, i);
+ dn_vector_push_back (vector, value);
dn_vector_erase_fast (dn_vector_begin (vector));
- if (((uint32_t *)vector->data) [9] != 0)
- return FAILED ("erase didn't zero memory.");
+ if (((uint32_t *)vector->data) [9] == 0)
+ return FAILED ("erase initialized memory, but shouldn't.");
dn_vector_free (vector);
dn_vector_custom_alloc_params_t params = {0, };
- params.attributes = DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT;
+ params.attributes = DN_VECTOR_ATTRIBUTE_MEMORY_INIT;
vector = dn_vector_custom_alloc_t (¶ms, int32_t);
for (int32_t i = 0; i < 10; ++i)
- dn_vector_push_back (vector, i);
+ dn_vector_push_back (vector, value);
dn_vector_erase_fast (dn_vector_begin (vector));
- if (((uint32_t *)vector->data) [9] == 0)
- return FAILED ("resize zeroed memory, but shouldn't.");
+ if (((uint32_t *)vector->data) [9] != 0)
+ return FAILED ("erase didn't initialize memory, but should");
dn_vector_free (vector);
if (vector->size != 0)
return FAILED ("vector size didn't match #1");
+ int32_t value = INT32_MAX;
+
for (int32_t i = 0; i < 10; ++i)
- dn_vector_push_back (vector, i);
+ dn_vector_push_back (vector, value);
dn_vector_resize (vector, 5);
for (uint32_t i = 5; i < 10; ++i) {
- if (((uint32_t *)vector->data) [i] != 0)
- return FAILED ("resize didn't zero memory.");
+ if (((uint32_t *)vector->data) [i] == 0)
+ return FAILED ("resize initialized memory, but shouldn't.");
}
dn_vector_free (vector);
dn_vector_custom_alloc_params_t params = {0, };
- params.attributes = DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT;
+ params.attributes = DN_VECTOR_ATTRIBUTE_MEMORY_INIT;
vector = dn_vector_custom_alloc_t (¶ms, int32_t);
for (int32_t i = 0; i < 10; ++i)
- dn_vector_push_back (vector, i);
+ dn_vector_push_back (vector, value);
dn_vector_resize (vector, 5);
for (uint32_t i = 5; i < 10; ++i) {
- if (((uint32_t *)vector->data) [i] != i)
- return FAILED ("resize zeroed memory, but shouldn't.");
+ if (((uint32_t *)vector->data) [i] != 0)
+ return FAILED ("resize didn't initialize memory, but should");
}
dn_vector_free (vector);
if (vector->size != 0)
return FAILED ("vector size didn't match #1");
+ int32_t value = INT32_MAX;
+
for (int32_t i = 0; i < 10; ++i)
- dn_vector_push_back (vector, i);
+ dn_vector_push_back (vector, value);
dn_vector_clear (vector);
for (int32_t i = 0; i < 10; ++i) {
- if (((uint32_t *)vector->data) [i] != 0)
- return FAILED ("clear didn't zero memory.");
+ if (((uint32_t *)vector->data) [i] == 0)
+ return FAILED ("clear initialized memory, but shouldn't.");
}
dn_vector_free (vector);
dn_vector_custom_alloc_params_t params = {0, };
- params.attributes = DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT;
+ params.attributes = DN_VECTOR_ATTRIBUTE_MEMORY_INIT;
vector = dn_vector_custom_alloc_t (¶ms, int32_t);
for (int32_t i = 0; i < 10; ++i)
- dn_vector_push_back (vector, i);
+ dn_vector_push_back (vector, value);
dn_vector_clear (vector);
for (int32_t i = 0; i < 10; ++i) {
- if (((uint32_t *)vector->data) [i] != i)
- return FAILED ("clear zeroed memory, but shouldn't.");
+ if (((uint32_t *)vector->data) [i] != 0)
+ return FAILED ("clear didn't initialize memory, but should.");
}
dn_vector_free (vector);
NULL,
1,
EP_EVENT_LEVEL_LOGALWAYS,
- true);
+ true,
+ 0);
ep_provider_callback_data_queue_enqueue (provider_callback_data_queue, provider_enqueue_callback_data);
ep_provider_callback_data_fini (provider_enqueue_callback_data);
}
int
mono_vfree (void *addr, size_t length, MonoMemAccountType type)
{
+ int res;
MEMORY_BASIC_INFORMATION mbi;
- SIZE_T query_result = VirtualQuery (addr, &mbi, sizeof (mbi));
- BOOL res;
-
- g_assert (query_result);
-
- res = VirtualFree (mbi.AllocationBase, 0, MEM_RELEASE);
-
- g_assert (res);
-
+ res = (VirtualQuery (addr, &mbi, sizeof (mbi)) != 0 && VirtualFree (mbi.AllocationBase, 0, MEM_RELEASE) != 0) ? 0 : -1;
mono_account_mem (type, -(ssize_t)length);
-
- return 0;
+ return res;
}
#if HAVE_API_SUPPORT_WIN32_FILE_MAPPING || HAVE_API_SUPPORT_WIN32_FILE_MAPPING_FROM_APP
for (uint32_t i = 0; i < current_bucket_count; i++){
dn_umap_node_t *node, *next_node;
for (node = buckets [i]; node; node = next_node){
- uint32_t hashcode = map->_internal._hash_func (node->key) % map->_internal._bucket_count;
+ uint32_t hashcode = (map->_internal._hash_func (node->key)) % map->_internal._bucket_count;
next_node = node->next;
node->next = map->_internal._buckets [hashcode];
umap_rehash (dn_umap_t *map)
{
uint32_t diff;
-
if (map->_internal._last_rehash > map->_internal._node_count)
diff = map->_internal._last_rehash - map->_internal._node_count;
else
diff = map->_internal._node_count - map->_internal._last_rehash;
- if (!((double)diff * 0.75 > (double)map->_internal._bucket_count * 2))
+ if (!(diff * 0.75 > map->_internal._bucket_count * 2))
return;
umap_do_rehash (map, umap_spaced_primes_closest (map->_internal._node_count));
umap_sanity_check (map);
}
-static dn_umap_result_t
+static inline void
+umap_insert_set_result (
+ dn_umap_result_t *insert_result,
+ dn_umap_t *map,
+ dn_umap_node_t *node,
+ uint32_t index,
+ bool result)
+{
+ insert_result->it._internal._map = map;
+ insert_result->it._internal._node = node;
+ insert_result->it._internal._index = index;
+ insert_result->result = result;
+ return;
+}
+
+static void
umap_insert (
dn_umap_t *map,
void *key,
void *value,
- bool assign)
+ bool assign,
+ dn_umap_result_t *result)
{
umap_sanity_check (map);
- dn_umap_result_t result = { { map, NULL, 0 }, false };
- dn_umap_equal_func_t equal_func = map->_internal._key_equal_func;
+ if (map->_internal._node_count == dn_umap_max_size (map)) {
+ umap_insert_set_result (result, map, NULL, 0, false);
+ return;
+ }
- if (map->_internal._node_count == dn_umap_max_size (map))
- return result;
+ umap_rehash (map);
- if (map->_internal._node_count >= map->_internal._threshold)
- umap_rehash (map);
+ dn_umap_equal_func_t equal_func = map->_internal._key_equal_func;
+ uint32_t hashcode = (map->_internal._hash_func (key)) % map->_internal._bucket_count;
- uint32_t hashcode = map->_internal._hash_func (key) % map->_internal._bucket_count;
for (dn_umap_node_t *node = map->_internal._buckets [hashcode]; node; node = node->next) {
if (equal_func (node->key, key)) {
- if (!assign) {
- result.it._internal._node = node;
- result.it._internal._index = hashcode;
- return result;
- }
+ if (assign) {
+ if (map->_internal._value_dispose_func)
+ map->_internal._value_dispose_func (node->value);
- if (map->_internal._value_dispose_func)
- map->_internal._value_dispose_func (node->value);
+ node->value = value;
- node->value = value;
+ umap_sanity_check (map);
- umap_sanity_check (map);
-
- result.it._internal._index = hashcode;
- result.it._internal._node = node;
- result.result = true;
-
- return result;
+ umap_insert_set_result (result, map, node, hashcode, true);
+ return;
+ } else {
+ umap_insert_set_result (result, map, node, hashcode, false);
+ return;
+ }
}
}
umap_sanity_check (map);
- result.it._internal._index = hashcode;
- result.it._internal._node = node;
- result.result = true;
+ umap_insert_set_result (result, map, node, hashcode, true);
+ return;
}
- return result;
+ umap_insert_set_result (result, map, NULL, 0, false);
+ return;
}
static bool
{
DN_ASSERT (map);
- dn_umap_it_t it = dn_umap_end (map);
uint32_t index = 0;
while (true) {
if (index >= map->_internal._bucket_count)
- return it;
+ return dn_umap_end (map);
if (map->_internal._buckets [index])
break;
index ++;
}
- it._internal._node = map->_internal._buckets [index];
- it._internal._index = index;
-
+ dn_umap_it_t it = { map, map->_internal._buckets [index], index };
return it;
}
void *value)
{
DN_ASSERT (map);
- return umap_insert (map, key, value, false);
+
+ dn_umap_result_t result;
+ umap_insert (map, key, value, false, &result);
+ return result;
}
dn_umap_result_t
void *value)
{
DN_ASSERT (map);
- return umap_insert (map, key, value, true);
+
+ dn_umap_result_t result;
+ umap_insert (map, key, value, true, &result);
+ return result;
}
dn_umap_it_t
umap_sanity_check (map);
dn_umap_equal_func_t equal_func = map->_internal._key_equal_func;
- uint32_t hashcode = map->_internal._hash_func (key) % map->_internal._bucket_count;
+ uint32_t hashcode = (map->_internal._hash_func (key)) % map->_internal._bucket_count;
dn_umap_node_t *prev_node = NULL;
for (dn_umap_node_t *node = map->_internal._buckets [hashcode]; node; node = node->next){
- if (equal_func (node->key, key)){
+ if (equal_func (node->key, key)) {
umap_erase_node (map, hashcode, node, prev_node);
return 1;
}
DN_ASSERT (map);
dn_umap_equal_func_t equal_func = map->_internal._key_equal_func;
- uint32_t hashcode = map->_internal._hash_func (key) % map->_internal._bucket_count;
+ uint32_t hashcode = (map->_internal._hash_func (key)) % map->_internal._bucket_count;
dn_umap_node_t *prev_node = NULL;
for (dn_umap_node_t *node = map->_internal._buckets [hashcode]; node; node = node->next){
- if (equal_func (node->key, key)){
+ if (equal_func (node->key, key)) {
if (!prev_node)
map->_internal._buckets [hashcode] = node->next;
else
dn_umap_it_t
dn_umap_custom_find (
dn_umap_t *map,
- const void *data,
+ const void *key,
dn_umap_equal_func_t equal_func)
{
DN_ASSERT (map);
- dn_umap_it_t found = dn_umap_end (map);
- equal_func = equal_func ? equal_func : map->_internal._key_equal_func;
+ if (!equal_func)
+ equal_func = map->_internal._key_equal_func;
- for (uint32_t i = 0; i < map->_internal._bucket_count; i++) {
- for (dn_umap_node_t *node = map->_internal._buckets [i]; node; node = node->next)
- if (equal_func (node->key, data)) {
- found._internal._index = i;
- found._internal._node = node;
- return found;
- }
+ uint32_t hashcode = (map->_internal._hash_func (key)) % map->_internal._bucket_count;
+
+ for (dn_umap_node_t *node = map->_internal._buckets [hashcode]; node; node = node->next) {
+ if (equal_func (node->key, key)) {
+ dn_umap_it_t found = { map, node, hashcode };
+ return found;
+ }
}
- return found;
+ return dn_umap_end (map);
}
void
#include "dn-allocator.h"
#include "dn-vector-types.h"
+bool
+_dn_vector_ensure_capacity (
+ dn_vector_t *vector,
+ uint32_t capacity,
+ bool calc_capacity);
+
bool
_dn_vector_insert_range (
dn_vector_it_t *position,
dn_vector_it_t *position,
dn_vector_dispose_func_t dispose_func);
-uint32_t
-_dn_vector_buffer_capacity (
- size_t buffer_size,
- uint32_t element_size);
-
dn_vector_it_t
_dn_vector_custom_find (
dn_vector_t *vector,
static inline DN_DEFINE_VECTOR_RESULT_T_NAME(name) \
DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_erase_fast) (DN_DEFINE_VECTOR_IT_T_NAME(name) position, dn_vector_dispose_func_t dispose_func) \
{ \
- DN_DEFINE_VECTOR_RESULT_T_NAME(name) result; \
- result.result = _dn_vector_erase_fast ((dn_vector_it_t *)&position, dispose_func); \
- result.it = position; \
+ DN_DEFINE_VECTOR_T_NAME(name) *vector = position._internal._vector; \
+ DN_ASSERT (vector && vector->size != 0); \
+ DN_ASSERT (position.it != position._internal._vector->size); \
+ vector->size --; \
+ if (dispose_func) \
+ dispose_func (vector->data + position.it); \
+ vector->data [position.it] = vector->data [vector->size]; \
+ if ((vector->_internal._attributes & (uint32_t)DN_VECTOR_ATTRIBUTE_MEMORY_INIT) == DN_VECTOR_ATTRIBUTE_MEMORY_INIT) \
+ vector->data [vector->size] = 0; \
+ DN_DEFINE_VECTOR_RESULT_T_NAME(name) result = { true, position }; \
return result; \
} \
static inline DN_DEFINE_VECTOR_RESULT_T_NAME(name) \
DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, erase_fast) (DN_DEFINE_VECTOR_IT_T_NAME(name) position) \
{ \
- return DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_erase_fast) (position, NULL); \
+ DN_DEFINE_VECTOR_T_NAME(name) *vector = position._internal._vector; \
+ DN_ASSERT (vector && vector->size != 0); \
+ DN_ASSERT (position.it != position._internal._vector->size); \
+ vector->size --; \
+ vector->data [position.it] = vector->data [vector->size]; \
+ if ((vector->_internal._attributes & (uint32_t)DN_VECTOR_ATTRIBUTE_MEMORY_INIT) == DN_VECTOR_ATTRIBUTE_MEMORY_INIT) \
+ vector->data [vector->size] = 0; \
+ DN_DEFINE_VECTOR_RESULT_T_NAME(name) result = { true, position }; \
+ return result; \
} \
static inline bool \
DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_resize) (DN_DEFINE_VECTOR_T_NAME(name) *vector, uint32_t size, dn_vector_dispose_func_t dispose_func) \
DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, push_back) (DN_DEFINE_VECTOR_T_NAME(name) *vector, type element) \
{ \
DN_ASSERT (vector); \
- return dn_vector_push_back ((dn_vector_t *)vector, element); \
+ uint64_t new_capacity = (uint64_t)vector->size + (uint64_t)1; \
+ if (DN_UNLIKELY (new_capacity > (uint64_t)(vector->_internal._capacity))) { \
+ if (DN_UNLIKELY (!_dn_vector_ensure_capacity ((dn_vector_t *)vector, (uint32_t)new_capacity, true))) \
+ return false; \
+ } \
+ vector->data [vector->size] = element; \
+ vector->size ++; \
+ return true; \
} \
static inline void \
DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_pop_back) (DN_DEFINE_VECTOR_T_NAME(name) *vector, dn_vector_dispose_func_t dispose_func) \
{ \
- dn_vector_custom_pop_back ((dn_vector_t*)vector, dispose_func); \
+ DN_ASSERT (vector && vector->size != 0); \
+ vector->size--; \
+ if (dispose_func) \
+ dispose_func (vector->data + vector->size); \
+ if (((vector->_internal._attributes & (uint32_t)DN_VECTOR_ATTRIBUTE_MEMORY_INIT) == DN_VECTOR_ATTRIBUTE_MEMORY_INIT)) \
+ vector->data [vector->size] = 0; \
} \
static inline void \
DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, pop_back) (DN_DEFINE_VECTOR_T_NAME(name) *vector) \
{ \
- dn_vector_pop_back ((dn_vector_t*)vector); \
-} \
-static inline uint32_t \
-DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, buffer_capacity) (size_t buffer_byte_size) \
-{ \
- return dn_vector_buffer_capacity_t (buffer_byte_size, type); \
+ DN_ASSERT (vector && vector->size != 0); \
+ vector->size --; \
+ if (((vector->_internal._attributes & (uint32_t)DN_VECTOR_ATTRIBUTE_MEMORY_INIT) == DN_VECTOR_ATTRIBUTE_MEMORY_INIT)) \
+ vector->data [vector->size] = 0; \
} \
static inline void \
DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, for_each) (const DN_DEFINE_VECTOR_T_NAME(name) *vector, dn_vector_for_each_func_t for_each_func, void *user_data) \
DN_DEFINE_VECTOR_T_STRUCT (dn_vector, uint8_t);
typedef enum {
- DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT = 0x1
+ DN_VECTOR_ATTRIBUTE_MEMORY_INIT = 0x1
} dn_vector_attribute;
#endif /* __DN_VECTOR_TYPES_H__ */
#include "dn-vector.h"
-#define INITIAL_CAPACITY 16
+#define INITIAL_CAPACITY 64
#define CALC_NEW_CAPACITY(capacity) ((capacity + (capacity >> 1) + 63) & ~63)
#define element_offset(p,i) \
#define check_attribute(vector, value) ((vector->_internal._attributes & (uint32_t)value) == value)
-static bool
-ensure_capacity (
+bool
+_dn_vector_ensure_capacity (
dn_vector_t *vector,
- uint32_t capacity)
+ uint32_t capacity,
+ bool calc_capacity)
{
- uint64_t new_capacity;
-
if (capacity != 0 && capacity <= (uint64_t)(vector->_internal._capacity))
return true;
- new_capacity = CALC_NEW_CAPACITY (capacity);
+ uint64_t new_capacity = calc_capacity ? CALC_NEW_CAPACITY (capacity) : capacity;
if (DN_UNLIKELY (new_capacity > (uint64_t)(UINT32_MAX)))
return false;
vector->data = data;
- if (vector->data && !check_attribute (vector, DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT)) {
+ if (vector->data && check_attribute (vector, DN_VECTOR_ATTRIBUTE_MEMORY_INIT)) {
// Checks already verified that element_offset won't overflow.
// new_capacity > vector capacity, so new_capacity - vector capacity won't underflow.
// dn_safe_size_t_multiply already verified element_length won't overflow.
dn_vector_t *vector = position->_internal._vector;
uint64_t new_capacity = (uint64_t)vector->size + (uint64_t)element_count;
- if (DN_UNLIKELY (new_capacity > (uint64_t)(UINT32_MAX)))
- return false;
-
- if (DN_UNLIKELY (!ensure_capacity (vector, (uint32_t)new_capacity)))
- return false;
+ if (DN_UNLIKELY (new_capacity > (uint64_t)(vector->_internal._capacity))) {
+ if (DN_UNLIKELY (!_dn_vector_ensure_capacity (vector, (uint32_t)new_capacity, true)))
+ return false;
+ }
uint64_t insert_offset = (uint64_t)position->it + (uint64_t)element_count;
uint64_t size_to_move = (uint64_t)vector->size - (uint64_t)position->it;
DN_ASSERT (vector && elements && element_count != 0);
uint64_t new_capacity = (uint64_t)vector->size + (uint64_t)element_count;
- if (DN_UNLIKELY (new_capacity > (uint64_t)(UINT32_MAX)))
- return false;
-
- if (DN_UNLIKELY (!ensure_capacity (vector, (uint32_t)new_capacity)))
- return false;
+ if (DN_UNLIKELY (new_capacity > (uint64_t)(vector->_internal._capacity))) {
+ if (DN_UNLIKELY (!_dn_vector_ensure_capacity (vector, (uint32_t)new_capacity, true)))
+ return false;
+ }
/* ensure_capacity already verified element_offset and element_length won't overflow. */
memmove (element_offset (vector, vector->size), elements, element_length (vector, element_count));
DN_ASSERT (vector && vector->size != 0);
uint64_t insert_offset = (uint64_t)position->it + 1;
- int64_t size_to_move = (int64_t)vector->size - (int64_t)position->it;
+ int64_t size_to_move = (int64_t)vector->size - (int64_t)position->it - 1;
if (DN_UNLIKELY (insert_offset > vector->_internal._capacity || size_to_move < 0))
return false;
vector->size --;
- if (!check_attribute (vector, DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT))
+ if (check_attribute (vector, DN_VECTOR_ATTRIBUTE_MEMORY_INIT))
memset (element_offset(vector, vector->size), 0, element_length (vector, 1));
return true;
if (dispose_func)
dispose_func (element_offset (vector, position->it));
+ vector->size --;
+
/* element_offset won't overflow since position is smaller than current capacity */
/* element_offset won't overflow since vector->size - 1 is smaller than current capacity */
/* vector->size - 1 won't underflow since vector->size > 0 */
- memmove (element_offset (vector, position->it), element_offset (vector, vector->size - 1), element_length (vector, 1));
+ memmove (element_offset (vector, position->it), element_offset (vector, vector->size), element_length (vector, 1));
- vector->size --;
-
- if (!check_attribute (vector, DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT))
+ if (check_attribute (vector, DN_VECTOR_ATTRIBUTE_MEMORY_INIT))
memset (element_offset(vector, vector->size), 0, element_length (vector, 1));
return true;
}
-uint32_t
-_dn_vector_buffer_capacity (
- size_t buffer_byte_size,
- uint32_t element_size)
-{
- // Estimate maximum array capacity for buffer size.
- size_t max_capacity = (buffer_byte_size - DN_ALLOCATOR_ALIGN_SIZE (sizeof (dn_vector_t), DN_ALLOCATOR_MEM_ALIGN8) - 32 /* padding */) / element_size;
- if (DN_UNLIKELY (max_capacity > buffer_byte_size || max_capacity > (size_t)UINT32_MAX))
- return 0;
-
- // Adjust to heuristics in ensure_capacity.
- uint32_t capacity = 1;
- while(CALC_NEW_CAPACITY (capacity) <= (uint32_t)max_capacity)
- capacity <<= 1;
-
- return (uint32_t)(capacity >> 1);
-}
-
dn_vector_it_t
_dn_vector_custom_find (
dn_vector_t *vector,
capacity = params->capacity;
}
- if (DN_UNLIKELY (!ensure_capacity (vector, capacity))) {
+ if (DN_UNLIKELY (!_dn_vector_ensure_capacity (vector, capacity, false))) {
dn_vector_dispose (vector);
return false;
}
uint32_t capacity)
{
DN_ASSERT (vector);
- return ensure_capacity (vector, capacity);
+ return _dn_vector_ensure_capacity (vector, capacity, true);
}
uint32_t
return true;
if (size > vector->_internal._capacity)
- if (DN_UNLIKELY (!ensure_capacity (vector, size)))
+ if (DN_UNLIKELY (!_dn_vector_ensure_capacity (vector, size, true)))
return false;
if (size < vector->size) {
dispose_func (element_offset (vector, i));
}
- if (!check_attribute (vector, DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT))
+ if (check_attribute (vector, DN_VECTOR_ATTRIBUTE_MEMORY_INIT))
memset (element_offset(vector, size), 0, element_length (vector, vector->size - size));
}
if (dispose_func)
dispose_func (element_offset (vector, vector->size));
- if (!check_attribute (vector, DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT))
+ if (check_attribute (vector, DN_VECTOR_ATTRIBUTE_MEMORY_INIT))
memset (element_offset (vector, vector->size), 0, vector->_internal._element_size);
}
dn_vector_custom_pop_back (vector, NULL);
}
-#define dn_vector_buffer_capacity_t(buffer_byte_size, type) \
- _dn_vector_buffer_capacity ((buffer_byte_size), sizeof (type))
-
void
dn_vector_for_each (
const dn_vector_t *vector,
dn_vector_ptr_custom_alloc_params_t params = {0, };
params.allocator = (dn_allocator_t *)&allocator;
- params.capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size);
+ params.capacity = dn_vector_ptr_default_local_allocator_capacity_size;
dn_vector_ptr_t *port_configs = dn_vector_ptr_custom_alloc (¶ms);
dn_vector_ptr_t *port_config_parts = dn_vector_ptr_custom_alloc (¶ms);
dn_vector_ptr_custom_init_params_t params = {0, };
params.allocator = (dn_allocator_t *)&allocator;
- params.capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size);
+ params.capacity = dn_vector_ptr_default_local_allocator_capacity_size;
ep_raise_error_if_nok (dn_vector_ptr_custom_init (&buffer_array, ¶ms));
ep_raise_error_if_nok (dn_vector_ptr_custom_init (&buffer_list_array, ¶ms));
dn_vector_ptr_custom_init_params_t params = {0, };
params.allocator = (dn_allocator_t *)&allocator;
- params.capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size);
+ params.capacity = dn_vector_ptr_default_local_allocator_capacity_size;
dn_vector_ptr_t thread_vector;
ep_raise_error_if_nok (dn_vector_ptr_custom_init (&thread_vector, ¶ms));
dn_vector_ptr_custom_init_params_t params = {0, };
params.allocator = (dn_allocator_t *)&allocator;
- params.capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size);
+ params.capacity = dn_vector_ptr_default_local_allocator_capacity_size;
dn_vector_ptr_t session_states_to_delete;
ep_raise_error_if_nok (dn_vector_ptr_custom_init (&session_states_to_delete, ¶ms));
dn_vector_ptr_custom_init_params_t params = {0, };
params.allocator = (dn_allocator_t *)&allocator;
- params.capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size);
+ params.capacity = dn_vector_ptr_default_local_allocator_capacity_size;
dn_vector_ptr_t thread_session_states_to_remove;
ep_raise_error_if_nok (dn_vector_ptr_custom_init (&thread_session_states_to_remove, ¶ms));
dn_vector_ptr_custom_init_params_t params = {0, };
params.allocator = (dn_allocator_t *)&allocator;
- params.capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size);
+ params.capacity = dn_vector_ptr_default_local_allocator_capacity_size;
dn_vector_ptr_t threads;