Reduce calls to malloc in multimap (#102)

Reduce the number of malloc calls in multimap. Improves efficiency by 40%.
This commit is contained in:
Bailey Thompson
2020-08-16 11:22:09 -04:00
committed by GitHub
parent fd3d3fc8b8
commit 5c4752c198
4 changed files with 431 additions and 344 deletions

View File

@@ -144,22 +144,21 @@ unordered_multiset unordered_multiset_destroy(unordered_multiset me);
typedef struct internal_multimap *multimap;
/* Starting */
multimap multimap_init(size_t key_size,
size_t value_size,
multimap multimap_init(size_t key_size, size_t value_size,
int (*key_comparator)(const void *const one,
const void *const two),
int (*value_comparator)(const void *const one,
const void *const two));
/* Capacity */
int multimap_size(multimap me);
size_t multimap_size(multimap me);
int multimap_is_empty(multimap me);
/* Accessing */
int multimap_put(multimap me, void *key, void *value);
void multimap_get_start(multimap me, void *key);
int multimap_get_next(void *value, multimap me);
int multimap_count(multimap me, void *key);
size_t multimap_count(multimap me, void *key);
int multimap_contains(multimap me, void *key);
int multimap_remove(multimap me, void *key, void *value);
int multimap_remove_all(multimap me, void *key);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2019 Bailey Thompson
* Copyright (c) 2017-2020 Bailey Thompson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -32,22 +32,21 @@
typedef struct internal_multimap *multimap;
/* Starting */
multimap multimap_init(size_t key_size,
size_t value_size,
multimap multimap_init(size_t key_size, size_t value_size,
int (*key_comparator)(const void *const one,
const void *const two),
int (*value_comparator)(const void *const one,
const void *const two));
/* Capacity */
int multimap_size(multimap me);
size_t multimap_size(multimap me);
int multimap_is_empty(multimap me);
/* Accessing */
int multimap_put(multimap me, void *key, void *value);
void multimap_get_start(multimap me, void *key);
int multimap_get_next(void *value, multimap me);
int multimap_count(multimap me, void *key);
size_t multimap_count(multimap me, void *key);
int multimap_contains(multimap me, void *key);
int multimap_remove(multimap me, void *key, void *value);
int multimap_remove_all(multimap me, void *key);

File diff suppressed because it is too large Load Diff

View File

@@ -1,72 +1,86 @@
#include <memory.h>
#include "test.h"
#include "../src/include/multimap.h"
/*
* Include this struct to verify the tree.
* Include this to verify the tree.
*/
struct internal_multimap {
size_t size;
size_t key_size;
size_t value_size;
int (*key_comparator)(const void *const one, const void *const two);
int (*value_comparator)(const void *const one, const void *const two);
int size;
struct node *root;
struct value_node *iterate_get;
char *root;
char *iterate_get;
};
/*
* Include this struct to verify the tree.
* Include this to verify the tree.
*/
struct node {
struct node *parent;
int balance;
void *key;
int value_count;
struct value_node *head;
struct node *left;
struct node *right;
};
static const size_t ptr_size = sizeof(char *);
/* static const size_t count_size = sizeof(size_t); */
/* Node balance is always the first byte (at index 0). */
/* static const size_t node_value_count_offset = sizeof(signed char); */
/* static const size_t node_value_head_offset = 1 + sizeof(size_t); */
static const size_t node_parent_offset = 1 + sizeof(size_t) + sizeof(char *);
static const size_t node_left_child_offset =
1 + sizeof(size_t) + 2 * sizeof(char *);
static const size_t node_right_child_offset =
1 + sizeof(size_t) + 3 * sizeof(char *);
static const size_t node_key_offset = 1 + sizeof(size_t) + 4 * sizeof(char *);
/*
* Verifies that the AVL tree rules are followed. The balance factor of an item
* must be the right height minus the left height. Also, the left key must be
* less than the right key.
*/
static int multimap_verify_recursive(struct node *const item)
static int multimap_verify_recursive(char *const item)
{
int left;
int right;
int max;
char *item_left;
char *item_right;
if (!item) {
return 0;
}
left = multimap_verify_recursive(item->left);
right = multimap_verify_recursive(item->right);
memcpy(&item_left, item + node_left_child_offset, ptr_size);
memcpy(&item_right, item + node_right_child_offset, ptr_size);
left = multimap_verify_recursive(item_left);
right = multimap_verify_recursive(item_right);
max = left > right ? left : right;
assert(right - left == item->balance);
if (item->left && item->right) {
const int left_val = *(int *) item->left->key;
const int right_val = *(int *) item->right->key;
assert(right - left == item[0]);
if (item_left && item_right) {
const int left_val = *(int *) (item_left + node_key_offset);
const int right_val = *(int *) (item_right + node_key_offset);
assert(left_val < right_val);
}
if (item->left) {
assert(item->left->parent == item);
assert(item->left->parent->key == item->key);
if (item_left) {
char *item_left_parent;
memcpy(&item_left_parent, item_left + node_parent_offset, ptr_size);
assert(item_left_parent == item);
assert(item_left_parent + node_key_offset == item + node_key_offset);
}
if (item->right) {
assert(item->right->parent == item);
assert(item->right->parent->key == item->key);
if (item_right) {
char *item_right_parent;
memcpy(&item_right_parent, item_right + node_parent_offset, ptr_size);
assert(item_right_parent == item);
assert(item_right_parent + node_key_offset == item + node_key_offset);
}
return max + 1;
}
static int multimap_compute_size(struct node *const item)
static size_t multimap_compute_size(char *const item)
{
char *left;
char *right;
if (!item) {
return 0;
}
return 1 + multimap_compute_size(item->left) +
multimap_compute_size(item->right);
memcpy(&left, item + node_left_child_offset, ptr_size);
memcpy(&right, item + node_right_child_offset, ptr_size);
return 1 + multimap_compute_size(left) + multimap_compute_size(right);
}
static void multimap_verify(multimap me)
@@ -93,7 +107,7 @@ static void test_invalid_init(void)
static void mutation_order(multimap me, const int *const arr, const int size)
{
int i;
int actual_size = 0;
size_t actual_size = 0;
assert(multimap_is_empty(me));
for (i = 0; i < size; i++) {
int num = arr[i];
@@ -385,7 +399,7 @@ static void test_contains(void)
static void test_stress_add(void)
{
int count = 0;
size_t count = 0;
int flip = 0;
int i;
multimap me = multimap_init(sizeof(int), sizeof(int), compare_int,
@@ -561,12 +575,6 @@ static void test_put_root_out_of_memory(multimap me)
fail_malloc = 1;
delay_fail_malloc = 1;
assert(multimap_put(me, &key, &key) == -ENOMEM);
fail_malloc = 1;
delay_fail_malloc = 2;
assert(multimap_put(me, &key, &key) == -ENOMEM);
fail_malloc = 1;
delay_fail_malloc = 3;
assert(multimap_put(me, &key, &key) == -ENOMEM);
}
#endif
@@ -579,12 +587,6 @@ static void test_put_on_left_out_of_memory(multimap me)
fail_malloc = 1;
delay_fail_malloc = 1;
assert(multimap_put(me, &key, &key) == -ENOMEM);
fail_malloc = 1;
delay_fail_malloc = 2;
assert(multimap_put(me, &key, &key) == -ENOMEM);
fail_malloc = 1;
delay_fail_malloc = 3;
assert(multimap_put(me, &key, &key) == -ENOMEM);
}
#endif
@@ -597,12 +599,6 @@ static void test_put_on_right_out_of_memory(multimap me)
fail_malloc = 1;
delay_fail_malloc = 1;
assert(multimap_put(me, &key, &key) == -ENOMEM);
fail_malloc = 1;
delay_fail_malloc = 2;
assert(multimap_put(me, &key, &key) == -ENOMEM);
fail_malloc = 1;
delay_fail_malloc = 3;
assert(multimap_put(me, &key, &key) == -ENOMEM);
}
#endif