Re: избежать частого вызова new в TMyList
От: Кодт Россия  
Дата: 11.12.07 11:32
Оценка: 3 (1)
Здравствуйте, Ruzzz, Вы писали:

R>хочу оптимизации


хочешь ясно выражать свои мысли?

R>хочу "закидывать" элементы односвязного списка в заранее выделенный большой блок памяти и при этом не обращатся к менежеру памяти каждый раз при добавлении нового элемента в список, а лишь тогда когда "большой кусок памяти" заполнен и следующий элемент не помещяется. Подскажите с реализацией или прокомментируйте! Может менежер и так быстр? Заранее спасибо!


Если вопрос о выборе контейнера, то:

Список (неважно, скольки-связный): дешёвая модификация, но каждый элемент хранится в собственном блоке памяти. Плюс накладные расходы (помимо данных, надо хранить указатели).
Чтобы не нагружать штатный менеджер кучи, можно использовать список в паре с рукодельным аллокатором (маленьким персональным менеджером кучи). Получится 4-ступенчатая система:
— список выделяет память под каждый элемент у аллокатора
— аллокатор выделяет блоки под сразу несколько элементов у рантайма
— рантайм обращается к менеджеру кучи операционной системы, запрашивая крупные блоки
— а тот, наконец, к виртуальной памяти

Вектор (динамический переразмещаемый массив): один сплошной блок памяти, дорогая модификация.
Чтобы уменьшить количество перемещений, память выделяется с запасом (в полтора-два раза от исходного количества элементов).
Собственный аллокатор здесь не нужен.

Дек (список массивов): более дешёвая модификация, зато более дорогая навигация (среднее между списком и вектором).
Б-дерево (дерево массивов): ещё более дешёвая модификация и навигация (за логарифмическое время).
Б-деревья были изобретены для того, чтобы оптимально хранить данные на внешних носителях. Узел дерева имеет размер, кратный странице памяти (кластеру диска).

Но разумеется, чтобы выбирать сознательно, нужно
— сделать оценку своих алгоритмов по скорости и расходу памяти (чтобы отсечь заведомо неудобные варианты)
— выполнить профилирование программы (может быть, тип контейнера не является узким местом)

Например, если у тебя много операций, требующих доступ по индексу — то список отпадает сразу, лидирует вектор, а Б-дерево может побороться за второе место.
Если много операций вставки/удаления с головы и хвоста — то вектор отпадает, а конкурировать будут в первую очередь список и дек.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
избежать частого вызова new в TMyList
От: Ruzzz  
Дата: 10.12.07 22:05
Оценка:
хочу оптимизации

хочу "закидывать" элементы односвязного списка в заранее выделенный большой блок памяти и при этом не обращатся к менежеру памяти каждый раз при добавлении нового элемента в список, а лишь тогда когда "большой кусок памяти" заполнен и следующий элемент не помещяется. Подскажите с реализацией или прокомментируйте! Может менежер и так быстр? Заранее спасибо!
Re: избежать частого вызова new в TMyList
От: deniok Россия  
Дата: 10.12.07 22:11
Оценка:
Здравствуйте, Ruzzz, Вы писали:

R>хочу оптимизации


Односвязный список — не массив. Память под элементы выделяется вовсе не непрерывная. Зато и вставка в любое место (и удаление) — дешевые операции.
Re: избежать частого вызова new в TMyList
От: andy1618 Россия  
Дата: 10.12.07 22:32
Оценка:
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;


Правда, список тут устроен как динамический массив указателей (а не как чистый односвязный список), но работает неплохо (особенно, если не увлекаться удалением элементов из середины)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.