хочу оптимизации
хочу "закидывать" элементы односвязного списка в заранее выделенный большой блок памяти и при этом не обращатся к менежеру памяти каждый раз при добавлении нового элемента в список, а лишь тогда когда "большой кусок памяти" заполнен и следующий элемент не помещяется. Подскажите с реализацией или прокомментируйте! Может менежер и так быстр? Заранее спасибо!
Здравствуйте, Ruzzz, Вы писали:
R>хочу оптимизации
Односвязный список — не массив. Память под элементы выделяется вовсе не непрерывная. Зато и вставка в любое место (и удаление) — дешевые операции.
R>хочу оптимизации
R>хочу "закидывать" элементы односвязного списка в заранее выделенный большой блок памяти и при этом не обращатся к менежеру памяти каждый раз при добавлении нового элемента в список, а лишь тогда когда "большой кусок памяти" заполнен и следующий элемент не помещяется. Подскажите с реализацией или прокомментируйте! Может менежер и так быстр? Заранее спасибо!
С большой долей вероятности в библиотеках вашего языка программирования уже есть готовое решение этой проблемы.
В целом — действительно, выделение памяти — не самая быстрая операция и в
некоторых случаях стоит подумать о выделении памяти большими блоками.
Вот, к примеру, как устроен рост списка TList в библиотеке VCL (Delphi):
procedure TList.Grow;
var
Delta: Integer;
begin
if FCapacity > 64 then
Delta := FCapacity div 4
else
if FCapacity > 8 then
Delta := 16
else
Delta := 4;
SetCapacity(FCapacity + Delta);
end;
Правда, список тут устроен как динамический массив указателей (а не как чистый односвязный список), но работает неплохо (особенно, если не увлекаться удалением элементов из середины)
Здравствуйте, Ruzzz, Вы писали:
R>хочу оптимизации
хочешь ясно выражать свои мысли?
R>хочу "закидывать" элементы односвязного списка в заранее выделенный большой блок памяти и при этом не обращатся к менежеру памяти каждый раз при добавлении нового элемента в список, а лишь тогда когда "большой кусок памяти" заполнен и следующий элемент не помещяется. Подскажите с реализацией или прокомментируйте! Может менежер и так быстр? Заранее спасибо!
Если вопрос о выборе контейнера, то:
Список (неважно, скольки-связный): дешёвая модификация, но каждый элемент хранится в собственном блоке памяти. Плюс накладные расходы (помимо данных, надо хранить указатели).
Чтобы не нагружать штатный менеджер кучи, можно использовать список в паре с рукодельным аллокатором (маленьким персональным менеджером кучи). Получится 4-ступенчатая система:
— список выделяет память под каждый элемент у аллокатора
— аллокатор выделяет блоки под сразу несколько элементов у рантайма
— рантайм обращается к менеджеру кучи операционной системы, запрашивая крупные блоки
— а тот, наконец, к виртуальной памяти
Вектор (динамический переразмещаемый массив): один сплошной блок памяти, дорогая модификация.
Чтобы уменьшить количество перемещений, память выделяется с запасом (в полтора-два раза от исходного количества элементов).
Собственный аллокатор здесь не нужен.
Дек (список массивов): более дешёвая модификация, зато более дорогая навигация (среднее между списком и вектором).
Б-дерево (дерево массивов): ещё более дешёвая модификация и навигация (за логарифмическое время).
Б-деревья были изобретены для того, чтобы оптимально хранить данные на внешних носителях. Узел дерева имеет размер, кратный странице памяти (кластеру диска).
Но разумеется, чтобы выбирать сознательно, нужно
— сделать оценку своих алгоритмов по скорости и расходу памяти (чтобы отсечь заведомо неудобные варианты)
— выполнить профилирование программы (может быть, тип контейнера не является узким местом)
Например, если у тебя много операций, требующих доступ по индексу — то список отпадает сразу, лидирует вектор, а Б-дерево может побороться за второе место.
Если много операций вставки/удаления с головы и хвоста — то вектор отпадает, а конкурировать будут в первую очередь список и дек.
... << RSDN@Home 1.2.0 alpha rev. 655>>