![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
не устраивает ReallocMem
Ruzzz © (2007-12-10 23:40:00)в хелпе написано:
if P is not nil and Size is not zero, ReallocMem reallocates the block referenced by P to the size given by Size. Existing data in the block is not affected by the reallocation, but if the block is made larger, the contents of the newly allocated portion of the block are undefined. If the block cannot be reallocated in place, it is moved to a new location in the heap, and P is updated accordingly.
Меня не устраивает этот MOVE! :)
Подскажите позжлста, есть ли какие-либо способы "бегать" Pointer'ом по "куску" памяти, который при этом сосотоит из частей? Т.е. я хочу вместо перераспределения памяти в случае не хватки, выделить еще и как-то это учитывать.
Может есть что-то подобное, например токой себе менеджер памяти :), обращаясь к памяти смотреть а не награнице ли мы части, если да то перепрыгиваем. Или это все "плохо"?
Мне нужен простой список строк, делитель #0, строки только добавляются, список не будет редактироваться, нужно очень быстро его составить, при этом в последствии нужно будет быстро по нему пробежаться (например также как и в SysUtils.StrEnd) и все, но изначально его длина не известна, она может быть как малой так и очень большой и поэтому заранее выделять много вроде как нельзя но и частое перераспределение(move) хочется обойти, но как же потом проходить по строкам если это будет не сплошной участок памяти?
Заранее спасибо!
Сергей М. (2007-12-11 12:14:00) [21]
> думаю reallocmem все же очень тормозит программу
Конечно тормозит, если вызывать ее бездумно, к месту и не к месту.
Но тебе предложили идеальный для твоего случая вариант с связным списком - при этом никаких реаллокаций не потребуется вообще.
> Думаю почитать как работает менеджер памяти в Делфи
И какие проблемы ?
Штатный getmem.inc всегда перед глазами, есть и альтарнативный FasmMM, он тоже с исходниками.
Заменить любой менеджер на свой "оптимальный" тоже не проблема - на то и существует глоб.структура TMemoryManager
@!!ex (2007-12-11 12:09:00) [22]> [20] Ruzzz © (11.12.07 11:58)
Блин. Те уже 10 раз сказали, операция выделения памяти очень быстрая!!!
Вот это:
var
Index:integer;
Tm:integer;
begin
Tm:=GetTickCount;
for Index := 0 to 1048576 do
AllocMem(1);
writeln(GetTickCount-Tm);
readln;
end.
показывает результат 16! мс!!! Это выдлеление мегабайта ПОБАЙТНО!
а вот это:
var
Index:integer;
Tm:integer;
begin
Tm:=GetTickCount;
for Index := 0 to 1048576 do
AllocMem(100);
writeln(GetTickCount-Tm);
readln;
end.
выполняется 110 мс...
выделение 100!!! мегабайт по 100! БАЙТ.
Ruzzz (2007-12-11 11:58:00) [23]:( извиняюсь! глупо забыть что-такое String!
TStringItem = record
FString: string;
FObject: TObject;
end;
беру свои слова обратно! никто не прикалывается! Но в этом случае тем более хочу оптимизировать.
Думаю почитать как работает менеджер памяти в Делфи, и как-то этим воспользоватся у себя. Хочу сам запоминать выделенные области памяти и контролировать границы при "обходе" этих областей, думаю reallocmem все же очень тормозит программу и дополнителная логика все же будет выгодной. Тем более что эти области будут большого размера а значит их будет не много.
Сергей М. (2007-12-11 11:23:00) [24]И чему, по-твоему, равно значение выражения
SizeOf(TStringItem)
?
Ruzzz (2007-12-11 11:18:00) [25]Вы чо тут прикалуйтесь, нафиг эти вопросы? Хоть бы кто-то что-то толковое подсказал. Извиняюсь канешно, но чуть ли не вся дискусия моя тут превратилась в доказывание.
procedure TStringList.InsertItem(Index: Integer; const S: string; AObject: TObject);
begin
Changing;
if FCount = FCapacity then Grow; ...
procedure TStringList.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;
procedure TStringList.SetCapacity(NewCapacity: Integer);
begin
ReallocMem(FList, NewCapacity * SizeOf(TStringItem));
FCapacity := NewCapacity;
end;
Перераспределение памати через обращение к встроенному менеджеру памяти (ReallocMem) идет для всех строк, включая возможных будущих
Сергей М. (2007-12-11 08:25:00) [26]
> TStringList, он все же выделяет память сразу большим куском,
> а не под одну строку каждый раз
Где ты такое вычитал ?
Ruzzz (2007-12-11 02:35:00) [27]:) нет, но я больше не под что не умею программировать :( и в kylix и freepascal я не сидел :( под linux и на си не могу :(
а пока думаю использовать TStringList, он все же выделяет память сразу большим куском, а не под одну строку каждый раз, если бы еще reallocmem не делал при не достаточном capacity а выделял еще память и как-то "менежерил" эти куски, и смотрел за границами этих кусков! :)
Германн (2007-12-11 02:06:00) [28]
> Ruzzz © (11.12.07 01:50) [14]
> да, заставить бы саму винду выдавать не по одному файлу!
> :) да еще и в заранее выделенную(подготовлинную:) память
>
А Винда - есть непременное условие?
Ruzzz (2007-12-11 01:50:00) [29]вот, большое спасибо за коммент! я вот тоже думал об этом, но, скорость не то что не устраивает, просто хотелось бы если есть возможность увеличить.
да, заставить бы саму винду выдавать не по одному файлу! :) да еще и в заранее выделенную(подготовлинную:) память
все равно есть подозрение что скорость можна увеличить. Вот как думаю: при 100.000 файлах - делаем и 100.000 раз new(обращений к менеджеру)! а так можна ж 100.000*MAX_PATH/SizeOfMyBlock!
Юрий Зотов (2007-12-11 01:36:00) [30]> Ruzzz © (11.12.07 01:27) [12]
Вы сначала запустите программу и посмотрите, что получится. Может, ее скорость и так Вас устроит. Может и нет - но тогда прогоните профайлер и точно выявите, где идут тормоза. Потому что есть основания считать, что время, которое сожрет менеджер окажется несравнимо меньше времени, которое сожрут дисковые операции - и тогда вся Ваша оптимизация будет практически бесполезной.
Ruzzz (2007-12-11 01:27:00) [31]TData = array[0..MAX_PATH - 1] of AnsiChar;
заполнять например так:
hFind := Windows.FindFirstFile(PChar(ParentDirectory + '*'), FindFileData);
if hFind <> INVALID_HANDLE_VALUE then begin
repeat
...
AddElement(FindFileData.cFileName);
...
until not Windows.FindNextFile(hFind, FindFileData);
Windows.FindClose(hFind);
end;
думаю быстрее заполнять data: TDataне смогу.
И вообще я другое хочу, хочу сократить обращения к менеджеру памяти(а я так понимаю new это обращение к нему), за счет того что выделять буду сразу большой кусок, т.е. "просить" память не под один элемент каждый раз, а под несколько, но вот при этом появляются проблемы. Прошу подсказать, как это лучше организовать, или прокомментировать - возможно это того не стоит!
Плохиш (2007-12-11 00:56:00) [32]
> Ruzzz © (11.12.07 00:49) [9]
> Ruzzz © (11.12.07 00:53) [10]
> и это важно для быстродействия
Не в том месте тормоза ищешь. Они находяться в заполнении data: TData
Ruzzz (2007-12-11 00:53:00) [33]и я таким образом буду выделять не важно скока, но важно что очень часто в секунду, и это важно для быстродействия
Ruzzz (2007-12-11 00:49:00) [34]под TList я не имел ввиду Delphi встроенный TList :), а просто односвязный список
type
PElement = ^TElement;
TElement = record
Data: TData;
Next: PElement;
end;
var
Head: PElement;
procedure AddElement(data: TData)
var
NewHead: PElement;
begin
New(NewHead);
NewHead.Data := data;
NewHead.Next := Head;
Head := NewHead;
end;
возможно я чего-то не знаю, но вот и хочу узнать, хочу поменьше вызывать New(NewHead)
Плохиш (2007-12-11 00:36:00) [35]
> Ruzzz © (10.12.07 23:57) [2]
> в list нужно каждый раз new делать
Где ж вы такое вычитываете-то? TList хранит указатели. А для получения указателя new совсем не обязательно...
@!!ex (2007-12-11 00:34:00) [36]> [6] Ruzzz © (11.12.07 00:27)
> при добавлении нового элемента в список, а лишь тогда когда
> "большой кусок памяти" заполнен и следующий элемент не помещяется
Имеет ли смысл заморачиваться?
Повторяю: Выделение нескольких мегабайт в секунду операция настолько быстрая, что практически не заметна визуально.
Ruzzz (2007-12-11 00:27:00) [37]спасибо за то что отвечаешь, но. я знаю что такое одн. списки, проблемы как таковой нет, но я хочу оптимально оптимизировать программу :)
вот такое я пока что надумал:
"закидывать" элементы односвязного списка в заранее выделенный большой блок памяти и при этом не обращатся к менежеру памяти каждый раз при добавлении нового элемента в список, а лишь тогда когда "большой кусок памяти" заполнен и следующий элемент не помещяется
прокомментируйте позжлста! подскажите!
@!!ex (2007-12-11 00:21:00) [38]> [4] Ruzzz © (11.12.07 00:16)
Блин. Гугли на тему "односвязные списки" ты придумываешь велосипед, причем левый какой то.
Ruzzz (2007-12-11 00:16:00) [39]вот мои мысли:
вместо <данные,указатель_next> как в list выделяю память и начинаю в ней заполнять свой список, дохожу до конца(очередная строка не помещается) выделяю еще и начинаю заполнять его. каждый кусок буду выделять например MAX_PATH(260)(заполнять нужно строками-путь+имя файла)*10000 - это 2,5 метра, думаю оптимально, если мало файлов(<10000) окажется, то и памяти не сильно сьем, ... вообщем писал я тут и думаю проблем куча, все эти куски помнить нужно, чтоб потом освободить, проверять хватит ли или еще выделять, эт уже менажер какой-то
вот если бы знать как new работает. может он так и делает выделяет память в сплошном куске пока есть возможность? но вот этож он для каждого new запоминает pointer и size, можно было бы без этого, я ведь могу по списку бегать и без pointer_to_next. Хотя получается выбор таков - или (pointer_to_next, но много раз new при построении списка) или (не знаю еще что :), но REPNE SCASB при прохождении списка)
@!!ex (2007-12-11 00:04:00) [40]> [2] Ruzzz © (10.12.07 23:57)
Не понял... А как ты память собираешься выделять без new?? :)))
new очень быстрая операция. У себя в проектах выделяю/удаляю каждую секунду по несколько метров(в пиковые моменты), на FPS почти не сказывается. Во всяком случае визуально. Так что это фигня.