diff options
author | Jean Cyr <jcyr@dillobits.com> | 2014-05-13 19:59:44 -0400 |
---|---|---|
committer | Jean Cyr <jcyr@dillobits.com> | 2014-05-13 19:59:44 -0400 |
commit | 8d3fed09443faa6a3c79b68b7800ed3472877a1c (patch) | |
tree | 68df28fda657261eb21215941fcfbca2965284a6 /src/modules/dataman | |
parent | 178a3e8567b3e721771fffcb8f32df140ad1038b (diff) | |
download | px4-firmware-8d3fed09443faa6a3c79b68b7800ed3472877a1c.tar.gz px4-firmware-8d3fed09443faa6a3c79b68b7800ed3472877a1c.tar.bz2 px4-firmware-8d3fed09443faa6a3c79b68b7800ed3472877a1c.zip |
Reduce potential dataman memory fragmentation
The data manager dynamically allocates relatively small work item blocks
on an as needed basis. It never frees these, instead maintaining then in
a list of available block for reuse when needed. Even if these blocks
are small, the are required at non-deterministic times and can end up
scattered in memory thus causing memory fragmentation. In order to
mitigate this problems work item blocks are allocated in groups of 8 in
contiguous memory to reduce the number of scattered memory allocations.
In reality, based on current usage, rarely will more than one group of 8
be allocated.
Diffstat (limited to 'src/modules/dataman')
-rw-r--r-- | src/modules/dataman/dataman.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/src/modules/dataman/dataman.c b/src/modules/dataman/dataman.c index 7505ba358..cbd9b2d7c 100644 --- a/src/modules/dataman/dataman.c +++ b/src/modules/dataman/dataman.c @@ -100,6 +100,8 @@ typedef struct { }; } work_q_item_t; +const size_t k_work_item_allocation_chunk_size = 8; + /* Usage statistics */ static unsigned g_func_counts[dm_number_of_funcs]; @@ -177,9 +179,20 @@ create_work_item(void) unlock_queue(&g_free_q); - /* If we there weren't any free items then obtain memory for a new one */ - if (item == NULL) - item = (work_q_item_t *)malloc(sizeof(work_q_item_t)); + /* If we there weren't any free items then obtain memory for a new ones */ + if (item == NULL) { + item = (work_q_item_t *)malloc(k_work_item_allocation_chunk_size * sizeof(work_q_item_t)); + if (item) { + lock_queue(&g_free_q); + for (int i = 1; i < k_work_item_allocation_chunk_size; i++) + sq_addfirst(&(item + i)->link, &(g_free_q.q)); + /* Update the queue size and potentially the maximum queue size */ + g_free_q.size += k_work_item_allocation_chunk_size - 1; + if (g_free_q.size > g_free_q.max_size) + g_free_q.max_size = g_free_q.size; + unlock_queue(&g_free_q); + } + } /* If we got one then lock the item*/ if (item) |