Объясню.
Во-первых, в данном примере всё было сделано так, чтобы возникли все необходимые факторы для того, чтобы получился именно такой результат, который получился.
И самая главная глупость — многократное изменение размера массива на всего-лишь один элемент. Артур2,
Step 100 не изменяет этого факта.
Так вот, грубый ReDim (т.е. оный без Preserve) должен "занулять" все элемента массива.
Мягкий ReDim (т.е. ReDim Preserve) должен "занулять" только добавленные элементы.
Пример jangla показывает только одно: произвести N занулений будет быстрее, чем произвести (N
2 + N)/2 занулений. Это очевидно и без примера.
Во-вторых, jangle обвинял тут всех, кто высказались "против него", в незнании механизмов управления памятью в Win32. Как я показал выше, разница в результатах обусловлена исключительно разным количеством занулений. Механизмы управления памятью тут непричём.
Есть и другой момент. Этот пример — сферический конь в вакууме.
При ReDim-инге массива для его размещения нужен блок памяти. Положим, что память для массивов выделяется в обычной виндовой куче обычными кучными функциями. Тогда каждый акт редиминга инициирует вызов HeapReAlloc.
Тут есть два принципиально разных вариантов развития событий:
- В куче после текущего блока памяти окажется достаточно свободного места, чтобы можно было засчёт него расширить текущий блок. Тогда блок просто расширяется.
- В куче после текущего блока идёт другой блок, причём так близко к текущему, что расширить текущий блок до нужных размеров так, чтобы он не перекрыл другие блоки — невозможно. Тогда текущий блок переезжает в другое место кучной памяти.
В последнем случае
тратится больше ресурсов (да, jangle!), потому что одновременно в памяти должны существовать два блока памяти: блок старого массива старого размера и блок нового массива нового размера — чтобы скопировать данные из старого массива в новый. Так что если мы превращаем 490мб-массив в 500-мб массив, то в некоторый момент у нас будет занято 990 метров кучной памяти.
Экономия ресурсов, да?
Но здесь мы имеем особую атмосферу проведения эксперимента:
1) В проекте один лишь эксперимент, он совершается в самом начале работы программы, а значит куча изначально не фрагментирована.
2) Постоянные редимы делаются в цикле. Между редимами никаких иных действий не совершается, а значит в процессе работы никто не сможет фрагментировать кучу.
Таким образом, я с 95% вероятностью могу утверждать, что все ReDim-ы в примере jangle-а идут по первому варианту развития событий, без реаллокации (в прямом смысле), а значит очень быстро.
Плюс к этому у jangle-а используется психологический эффект: структура имеет кучу полей. На самом деле все поля байтовые и их 8. Элемент массива занимает всего-лишь 8 байтов. Учитывай, что Heap(Re)Alloc может прихватывать справа ещё и чуть-чуть памяти, то даже в случае очень сильной фрагментации достаточно большое кол-во редимов пройдёт без необходимости релокации блока.Всё то же самое, будь оно внутри реальной программы, в которой по своим законам создаются и уничтожаются объекты, а значит, в которой постоянно фрагментируется куча, в которой массив расширяется не по одному элементу, а достаточно большими блоками — результат был бы обратным.