I use C struct to build a prefix tree, i.e. Trie. I want to use it to store a lot of number lists to get the next possible number in a given path. (For example, I have [10, 15, 17] and [10, 15, 18], then the next possible number of [10,15] is 17,18.) The problem I met is about the memory use, my each struct Trie node takes only 12 bytes(I used sizeof() to check it), and have 0.83 billion nodes in total, which should take 0.83 billion * 12 bytes = 10G memory use, but actually I used 20G memory, and I want to reduce the memory use into 10G.
I use an unsigned short to store the data for each node, unsignedn short n_child to store how many children does this node have, a pointer to his children list beginning location, and realloc a 12 bytes bigger memory space for a new node.
#pragma pack(2)
typedef struct trie_node{
unsigned short data;
unsigned short n_child;
struct trie_node * children;
} Trie;
When I have to add a new child, I use:
this_node->n_child = this_node->n_child + 1;
this_node->children = (Trie *)realloc(this_node->children, this_node->n_child * sizeof(Trie));
I want to know why the memory use is bigger than calculated and cound I reduce the memory use.
this_node->children = (Trie *)realloc(this_node->children, this_node->n_child * sizeof(Trie));. Ifrealloc()fails, you will overwrite your previous pointer withNULL, losing the only reference to the previous data.malloc(). For example, on a Mac running macOS 10.14.5 Mojave, allocating blocks of 12 (or 14, or 16) bytes generates addresses that are 16 bytes apart. Any overhead is not visible — but I'm confident it's there.