Так что название несколько вводит в заблуждение ... Я буду упрощать: я сравниваю эти две структуры данных:
- Массив, в котором он начинается с размера 1, и для каждого последующего добавления существует вызов realloc () для расширения памяти, а затем добавление нового (malloced) элемента в позицию n-1.
- Связанный список, по которому я отслеживаю голову, хвост и размер. Кроме того, добавление включает в себя неправильный поиск нового элемента и обновление указателя и размера хвоста.
Не беспокойтесь ни о каких других деталях этих структур данных. Это единственная функция, которая мне нужна для этого тестирования.
Теоретически, LL должен работать лучше. Тем не менее, они практически идентичны по времени испытаний с участием 10, 100, 1000 ... до 5 000 000 элементов.
Мое ощущение, что куча большая. Я думаю, что сегмент данных по умолчанию 10 МБ на Redhat? Я могу ошибаться. В любом случае, realloc () сначала проверяет, доступно ли пространство в конце уже выделенного непрерывного расположения памяти (0- [n-1]). Если n-я позиция доступна, перемещение элементов не производится. Вместо этого realloc () просто резервирует старый пробел + непосредственно следующий пробел. Мне трудно найти доказательства этого, и мне все труднее доказать, что этот массив на практике должен работать хуже, чем LL.
Вот некоторый дальнейший анализ после прочтения постов ниже:
[Обновление № 1]
Я изменил код, чтобы иметь отдельный список, который распределяет память каждую 50-ю итерацию как для LL, так и для массива. На 1 миллион дополнений в массиве почти всегда есть 18 ходов. Там нет концепции переезда для LL. Я сделал сравнение времени, они все еще почти идентичны. Вот некоторые результаты для 10 миллионов дополнений:
(Array)
time ./a.out a 10,000,000
real 0m31.266s
user 0m4.482s
sys 0m1.493s
(LL)
time ./a.out l 10,000,000
real 0m31.057s
user 0m4.696s
sys 0m1.297s
Я бы ожидал, что время будет резко отличаться от 18 ходов. Для добавления массива требуется еще 1 присваивание и еще 1 сравнение, чтобы получить и проверить возвращаемое значение realloc, чтобы убедиться, что произошло перемещение.
[Обновление № 2]
Я запустил ltrace для тестирования, которое я опубликовал выше, и я думаю, что это интересный результат ... Похоже, что realloc (или некоторый менеджер памяти) превентивно перемещает массив в более крупные смежные местоположения на основе текущего размера.
Для 500 итераций перемещение памяти было запущено на итерациях:
1, 2, 4, 7, 11, 18, 28, 43, 66, 101, 154, 235, 358
Что довольно близко к последовательности суммирования. Я нахожу это довольно интересным - думал, что я отправлю это.