2009-11-23 3 views
4

У меня есть процедура, которая добавляет порядковые элементы («День» или «Ночь» перечислимого типа) в многомерном динамический массив, который объявлен как:Большой динамический массив - медленный написание

TShiftType = (stDay, stNight); 
TScheduleArray = array of array of array [1..DaysPerWeek] of TShiftType; 

Решетка может содержать что-либо между 1 элементом (например, (Day, Day, Day, Day, Day, Night, Night)) и более 20 000 элементов. Каждый элемент может сам иметь подэлементы в зависимости от того, сколько недель обрабатывается.

Так один элемент в две недели массиве может выглядеть следующим образом:

((stDay, stDay, stDay, stDay, stDay, stNight, stNight), (stDay, stDay, stDay, stDay, stDay, stNight, stNight))

Это работает очень быстро и очень хорошо работает, когда число элементов является относительно низким (около менее 1000). Как только количество недель и элементов увеличивается, просто добавление нового элемента в массив (после вызова SetLength для увеличения длины массива на единицу) начинает экспоненциально замедляться.

Иногда я также получаю нарушение доступа. Когда я использую средство «Найти ошибку» в Delphi, он приводит меня к методу @DynArrayAsg в окне CPU. Но я никогда не получаю исключение EOutOfMemory, что помощь Delphi говорит, что я получу, если недостаточно памяти для перераспределения переменной.

Неужели это замедляет доступ к ожидаемому поведению памяти? Я использую Delphi 6.

ответ

7

Да, потому что когда вы перераспределяете его, если в конце существующего массива недостаточно одного смежного пространства, чтобы просто добавить один элемент, он должен найти еще один достаточно большой блок, выделить его, скопируйте весь существующий массив, а затем освободите исходный код. Чем больше ваш массив, тем дольше будет копия.

TList помогает устранить эту проблему, выделив ее внутренний массив в размерах двух размеров, а не «точно так же, как мне нужно», а затем с помощью переменной Count, чтобы отметить верхние границы того, что на самом деле используется , Может быть, вы могли бы сделать что-то подобное?

Кроме того, если у вас его еще нет, получите FastMM. Гораздо лучше выделять и перераспределять память, чем встроенный менеджер памяти Delphi 6.

+0

Спасибо Мэйсон, хорошее объяснение. У меня есть D2009 (для части FastMM), ожидающий выхода, но сторонний компонент стоит на данный момент. Считаете ли вы, что TList будет лучшим решением в этом случае, где у меня многомерный массив? –

+0

Возможно, нет, но вы можете посмотреть, как реализован TList, и использовать его в качестве шаблона для создания собственного 3-мерного класса массива. –

+0

Спасибо. Вы ответили на первоначальный вопрос о том, почему это замедляется, поэтому благодарим. –

Смежные вопросы