Во-первых, я думаю, вы пренебрегаете стоимостью размещения QueueItems.Таким образом, затраты на распределение между вашими двумя подходами одинаковы.(Кто-то более осведомленный о распределении памяти, пожалуйста, говорите, если я ошибаюсь.)
Вы можете сделать это, чтобы уменьшить потерянное пространство для извлеченных / незаполненных элементов в массиве.Сделайте гибрид из списка и массива.Пусть каждый узел списка содержит массив размером K.
struct QueueItem
{
QueueItem* next;
void (*data)[K];
}
struct Queue
{
QueueItem* head;
QueueItem* tail;
size_t head;
size_t end;
}
Теперь ваша производительность определяется размером, выбранным для массива.Чем оно меньше, тем меньше у вас потраченного пространства.Чем оно больше, тем меньше издержек QueueItem стоит вам в процентах от общего пространства.Если вы знали, скажем, что ваша очередь обычно будет иметь размер N, то вы можете выбрать K, чтобы быть N / 10.В этом случае общая стоимость памяти равна N / K + 4 + N. Максимальный объем пространства, которое вы можете тратить в массивах на неиспользуемые элементы, составляет 2 * K - 2.
Шаблоны использования будут определять фактическую производительность.,Но если вы можете предвидеть ваш шаблон использования, вы можете выбрать K, который работает хорошо.Может даже существовать способ адаптивно выбирать K по-разному для каждого узла, чтобы получить еще лучшую производительность, но я думаю, что сейчас это за мной.