Так что название несколько вводит в заблуждение... Я буду говорить просто: я сравниваю эти две структуры данных:
- Массив, в котором он начинается с размера 1, и для каждого последующего добавления есть вызов realloc() для расширения памяти, а затем добавление нового (распределенного) элемента в позицию 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, что довольно близко к последовательности суммирования. Я нахожу это довольно интересным — решил опубликовать это.
realloc()расширяет блок, а не перемещает его — если указательrealloc()возвращает тот же самый, что и тот, который вы ему передали, то он расширил блок. - person caf   schedule 30.09.2010reallocдолжен копировать данные, просто добавьте код, который сравнивает указатель до и после вызова. Времена, когда они разные, это когда он сделал копию. Складывайте размер массива каждый раз, когда он копируется, и вы увидите, сколько накладных расходов имеет массив. - person Gabe   schedule 30.09.2010