Помощь - Поиск - Пользователи - Календарь
Полная версия: Эффективность менеджера памяти в Delphi
Форум «Всё о Паскале» > Pascal, Object Pascal > Теоретические вопросы
TarasBer
Прочитав умные мысли про то, что память эффективнее выделять кусками, размер которых равен степени 2, я решил применить её в D7, подменив менеджер памяти на свой, отличающийся только тем, что размер блока дополняет до степени 2, и сравнить эффективность родного менеджера и подкорректированного.

{$APPTYPE CONSOLE}
uses
Windows;

type
proc = procedure;

procedure Stress; // думаю, достаточно интересная задача для менеджера памяти
var
p1, p2, p3, p4: array of byte;
i: integer;
begin
for i := 0 to 999999 do begin
SetLength(p1, i);
SetLength(p2, i);
SetLength(p3, i);
SetLength(p4, i);
end;
end;

procedure Test(p: proc);
var
T: cardinal;
begin
T := GetTickCount; while T = GetTickCount do; T := GetTickCount;
p;
WriteLn(integer(GetTickCount) - integer(T));
end;

function MyReallocMem(p: Pointer; size: Integer): Pointer; // äîïîëíèòü äî ñòåïåíè 2
var
aSize: integer;
begin
if size = 0 then aSize := 0 else begin
aSize := 1;
while aSize < size do aSize := aSize shl 1;
end;
Result := SysReallocMem(p, size);
end;

var
M: TMemoryManager;

begin
Test(Stress);
M.GetMem := SysGetMem;
M.FreeMem := SysFreeMem;
M.ReAllocMem := MyReAllocMem;
SetMemoryManager(M);
Test(Stress);
ReadLn;
end.


Программа вывела вот что (на современном компе):
Код

1031
1297

Я сделал такой вывод - при работе с динамическими массивами можно не заморачиваться и увеличивать длину по единичке, всё реализовано достаточно эффективно, советы дополнять до степени 2 в D7 (да и в других версиях, наверное, тоже) никакого смысла не имеют. Выходит, так?
volvo
Цитата
Прочитав умные мысли про то, что память эффективнее выделять кусками, размер которых равен степени 2
Это где такие мысли написаны? Можно нам тоже почитать?

Со своей стороны могу подтвердить, да, в Д2009 то же самое, при запуске этой программы (запускал несколько раз) среднее значение для родного менеджера составило около 185, для измененной ReallocMem - около 250.

Еще доп. информация - детальное описание менеджера памяти Д7: RSDN -> Менеджер памяти Delphi, там описан алгоритм, по которому происходит выделение и перераспределение памяти, и сделаны некоторые выводы о его эффективности.
TarasBer
> Это где такие мысли написаны? Можно нам тоже почитать?

Сходу не найду, но вот тут упоминается: http://russian.joelonsoftware.com/Articles/BacktoBasics.html

> Хитрые программисты борются с фрагментацией памяти, выделяя каждый раз память блоками, размер которых равен степени двойки. Ну вы знаете, 4 байта, 8 байт, 16 байт, 18446744073709551616 байт, и т.д. По причинам, которые должны быть очевидны для тех, кто играл с конструктором Lego, это уменьшает фрагментацию списка свободных блоков. Несмотря на то, что такой подход кажется расточительным, также легко показать, что при нём неиспользуемой остаётся не более чем 50% памяти. Так что ваша программа использует не более чем в два раза больше памяти, чем ей надо, что не так уж страшно.
Допустим, вы написали хитрую функцию strcat, которая изменяет по необходимости размер буфера для хранения результата. Сколько именно памяти ей имеет смысл выделять? Ровно столько, сколько сейчас надо? Мой учитель и наставник Стэн Эйзенстет (Stan Eisenstat) рекомендует при вызове realloc удваивать количество памяти по сравнением с прошлым разом. Это значит, что вам никогда не придётся вызывать realloc больше чем lg n раз, что неплохо с точки зрения производительности даже для огромных строк, и вы потратите впустую не больше 50% памяти.

Добавлено через 2 мин.
Я сюда опечятался. Я мерял для Result := SysReallocMem(p, aSize), иначе не меняется ничего.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.