Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.01.06;
Скачать: [xml.tar.bz2];

Вниз

не устраивает ReallocMem   Найти похожие ветки 

 
Ruzzz ©   (2007-12-10 23:40) [0]

в хелпе написано:
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) хочется обойти, но как же потом проходить по строкам если это будет не сплошной участок памяти?

Заранее спасибо!


 
@!!ex ©   (2007-12-10 23:44) [1]

Бегать поинтером по памяти из кусков нельзя.
List(списки) тебе в руки, они решают такую проблему.


 
Ruzzz ©   (2007-12-10 23:57) [2]

в list нужно каждый раз new делать, как это отразится на моей оптимизации по скорости?

подскажите где почитать об Memory maneger в делфи. как быстро работает new? да, и если я буду использовать KOL? хотелось бы максимально не зависить от Memory maneger. например как можна меньше вызывать allocmem, и конечно же без reallocmem.


 
@!!ex ©   (2007-12-11 00:04) [3]

> [2] Ruzzz ©   (10.12.07 23:57)

Не понял... А как ты память собираешься выделять без new?? :)))
new очень быстрая операция. У себя в проектах выделяю/удаляю каждую секунду по несколько метров(в пиковые моменты), на FPS почти не сказывается. Во всяком случае визуально. Так что это фигня.


 
Ruzzz ©   (2007-12-11 00:16) [4]

вот мои мысли:
вместо <данные,указатель_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:21) [5]

> [4] Ruzzz ©   (11.12.07 00:16)

Блин. Гугли на тему "односвязные списки" ты придумываешь велосипед, причем левый какой то.


 
Ruzzz ©   (2007-12-11 00:27) [6]

спасибо за то что отвечаешь, но. я знаю что такое одн. списки, проблемы как таковой нет, но я хочу оптимально оптимизировать программу :)

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

прокомментируйте позжлста! подскажите!


 
@!!ex ©   (2007-12-11 00:34) [7]

> [6] Ruzzz ©   (11.12.07 00:27)
> при добавлении нового элемента в список, а лишь тогда когда
> "большой кусок памяти" заполнен и следующий элемент не помещяется

Имеет ли смысл заморачиваться?
Повторяю: Выделение нескольких мегабайт в секунду операция настолько быстрая, что практически не заметна визуально.


 
Плохиш ©   (2007-12-11 00:36) [8]


> Ruzzz ©   (10.12.07 23:57) [2]
> в list нужно каждый раз new делать

Где ж вы такое вычитываете-то? TList хранит указатели. А для получения указателя new совсем не обязательно...


 
Ruzzz ©   (2007-12-11 00:49) [9]

под 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)


 
Ruzzz ©   (2007-12-11 00:53) [10]

и я таким образом буду выделять не важно скока, но важно что очень часто в секунду, и это важно для быстродействия


 
Плохиш ©   (2007-12-11 00:56) [11]


> Ruzzz ©   (11.12.07 00:49) [9]


> Ruzzz ©   (11.12.07 00:53) [10]
> и это важно для быстродействия

Не в том месте тормоза ищешь. Они находяться в заполнении data: TData


 
Ruzzz ©   (2007-12-11 01:27) [12]

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 01:36) [13]

> Ruzzz ©   (11.12.07 01:27) [12]

Вы сначала запустите программу и посмотрите, что получится. Может, ее скорость и так Вас устроит. Может и нет - но тогда прогоните профайлер и точно выявите, где идут тормоза. Потому что есть основания считать, что время, которое сожрет менеджер окажется несравнимо меньше времени, которое сожрут дисковые операции - и тогда вся Ваша оптимизация будет практически бесполезной.


 
Ruzzz ©   (2007-12-11 01:50) [14]

вот, большое спасибо за коммент! я вот тоже думал об этом, но, скорость не то что не устраивает, просто хотелось бы если есть возможность увеличить.

да, заставить бы саму винду выдавать не по одному файлу! :) да еще и в заранее выделенную(подготовлинную:) память

все равно есть подозрение что скорость можна увеличить. Вот как думаю: при 100.000 файлах - делаем и 100.000 раз new(обращений к менеджеру)! а так можна ж 100.000*MAX_PATH/SizeOfMyBlock!


 
Германн ©   (2007-12-11 02:06) [15]


> Ruzzz ©   (11.12.07 01:50) [14]


> да, заставить бы саму винду выдавать не по одному файлу!
>  :) да еще и в заранее выделенную(подготовлинную:) память
>

А Винда - есть непременное условие?


 
Ruzzz ©   (2007-12-11 02:35) [16]

:) нет, но я больше не под что не умею программировать :( и в kylix и freepascal я не сидел :( под linux и на си не могу :(

а пока думаю использовать TStringList, он все же выделяет память сразу большим куском, а не под одну строку каждый раз, если бы еще reallocmem не делал при не достаточном capacity а выделял еще память и как-то "менежерил" эти куски, и смотрел за границами этих кусков! :)


 
Сергей М. ©   (2007-12-11 08:25) [17]


> TStringList, он все же выделяет память сразу большим куском,
>  а не под одну строку каждый раз


Где ты такое вычитал ?


 
Ruzzz ©   (2007-12-11 11:18) [18]

Вы чо тут прикалуйтесь, нафиг эти вопросы? Хоть бы кто-то что-то толковое подсказал. Извиняюсь канешно, но чуть ли не вся дискусия моя тут превратилась в доказывание.

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 11:23) [19]

И чему, по-твоему, равно значение выражения

SizeOf(TStringItem)

?


 
Ruzzz ©   (2007-12-11 11:58) [20]

:( извиняюсь! глупо забыть что-такое String!

 TStringItem = record
   FString: string;
   FObject: TObject;
 end;


беру свои слова обратно! никто не прикалывается! Но в этом случае тем более хочу оптимизировать.

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


 
@!!ex ©   (2007-12-11 12:09) [21]

> [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! БАЙТ.


 
Сергей М. ©   (2007-12-11 12:14) [22]


> думаю reallocmem все же очень тормозит программу


Конечно тормозит, если вызывать ее бездумно, к месту и не к месту.

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


> Думаю почитать как работает менеджер памяти в Делфи


И какие проблемы ?

Штатный getmem.inc всегда перед глазами, есть и альтарнативный FasmMM, он тоже с исходниками.

Заменить любой менеджер на свой "оптимальный" тоже не проблема - на то и существует глоб.структура TMemoryManager


 
Ruzzz ©   (2007-12-11 12:26) [23]

Требования:
-сформировать как можна быстрее список строк
-список формируется последовательно(без вставок)
-в дальнейшем список изменятся не будет
-требуется быстро пройтись по списку
-требуется быстро сохранить в файл
-список может быть как очень мал так и очень огромен (при большом обьеме файлов и сложной иерархии подпапок == 2 000 000 строк * 100 (ну например средняя длина) = 200мб). Думаю при такой ситуации частое перераспределение(копирование уже имеющейся информации в новую область) может сильно тормозить.

Пока не изучал работу менежера, но вот что думаю:

хранить список указателей на строки, причем это будет простой масив а не односвязный список, а точнее хранить и длину:

TStrP = packed record
   Offset: Pointer;
   Size: Cardinal;
end;

эта область будет использовать ReAllocMem - думаю это не критично. будет что-то типа TStringList.Grow, но другой Delta, ведь я заранее знаю что строк будет много, по этой же причине и изначально буду выделять достаточно памяти. SizeOf(TStrP) = 8 байт - 100 000 строк - это 800 кб, нормально.

Теперь при "обходе" я не буду переживать за выход из какого-то выделленого кусочка памяти. проблема будет лишь при добавлении строки.
Но зная инфомацию о текущем выделеном куске памяти мы можем быстро выполнять проверку, и если что попросить еще памяти и переключится на нее.

При обходе пользоватся списком из TStrP. При сохранении сохранять блоки памяти.

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


TMemBlock = packed record
   Offset: Pointer;
   Size: Cardinal;
   CurrentOffset: Pointer;
end;


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


 
Сергей М. ©   (2007-12-11 12:28) [24]


> "закидывать" элементы односвязного списка в заранее выделенный
> большой блок памяти


Это еще зачем ?
Строишь односвязный список, попутно подсчитывая число его элементов (ListCount).

По окончанию построения создаешь TList, устанавливаешь его Capacity равным ListCount * SizeOf(PChar), пробегаешь по построенному односвязному списку с попутным заполнением соотв. элеменов TList ссылками на строки, ассоциированные с соотв. элементами односвязного цикла.

Все !
И никаких множественных реаллокаций)


 
@!!ex ©   (2007-12-11 12:29) [25]

> [23] Ruzzz ©   (11.12.07 12:26)

ИМХО это не правильно.
Копирование строки занимает больше времени, чем выделение памяти.
Ты сейчас не тем занимаешься.

Если уж так хочеться оптимизировать работу менеджера памяти - перед добавлением строк дефрагментируй память.
ТОгда realloc не будет ничего никуда перемещать, а просто расширять.


 
Сергей М. ©   (2007-12-11 12:30) [26]


> устанавливаешь его Capacity равным ListCount * SizeOf(PChar)


Вру.
Просто Capacity <-- ListCount


 
Ruzzz ©   (2007-12-11 12:36) [27]

SizeOf(TStrP) = 32 байта )


 
Ruzzz ©   (2007-12-11 12:38) [28]

точнее бита, значить смогу быстренько в одном регистре смотреть, щас почитаю ваши комменты, спасибо большое, про дефрагментацию буду искать что-то


 
ЮЮ ©   (2007-12-11 12:45) [29]

> [21] @!!ex ©   (11.12.07 12:09)
> > [20] Ruzzz ©   (11.12.07 11:58)

> выполняется 110 мс...
> выделение 100!!! мегабайт по 100! БАЙТ.



> Вот как думаю: при 100.000 файлах - делаем и 100.000 раз
> new(обращений к менеджеру)! а так можна


Ну пусть даже сократишь с 0.2 секунды до абсоолютного 0, дальше то придется Винду переписывать, ибо  
> да, заставить бы саму винду выдавать не по одному файлу!
> :) да еще и в заранее выделенную(подготовлинную:) память


 
Юрий Зотов ©   (2007-12-11 12:50) [30]

> Ruzzz ©   (11.12.07 12:26) [23]

Увы, сдается мне, что горьким будет Ваше разочарование...

После того, как Вы потратите кучу времени и труда, все сделаете - а в результате обнаружите, что программа стала работать быстрее... на 1%.


 
sniknik ©   (2007-12-11 12:57) [31]

основные задержки в прикладном программировании не в улучшении стандартных механизмов, а в оптимальных алгоритмах.

> что программа стала работать быстрее... на 1%.
скорее даже наоборот на 10% медленнее...


 
Ruzzz ©   (2007-12-11 13:04) [32]

да вы правы, оперция копирования строки и дисковые операции все сводят на нет.

думаю быстрее будет если написать драйвер и считывать по секторам MFT


 
Ruzzz ©   (2007-12-11 13:05) [33]

%) шучу! :) всем спасибо за комментарии!


 
Skyle ©   (2007-12-11 13:05) [34]

Может не стоит всё хранить в памяти? Хранить всё на диске и использовать MMF?


 
@!!ex ©   (2007-12-11 13:07) [35]

> [34] Skyle ©   (11.12.07 13:05)

Он не хранит файлы в памяти. Он хранит пути к ним, если я правильно понял.


 
Ruzzz ©   (2007-12-11 13:09) [36]

чесна говоря я не знаю что такое MMF, но в любом случае в оперативке быстрее будет


 
@!!ex ©   (2007-12-11 13:21) [37]

> [36] Ruzzz ©   (11.12.07 13:09)

ФАйл спроецированный в память.
MemoryMappedFile


 
Skyle ©   (2007-12-11 13:30) [38]


> @!!ex ©   (11.12.07 13:07) [35]
> > [34] Skyle ©   (11.12.07 13:05)
>
> Он не хранит файлы в памяти. Он хранит пути к ним, если
> я правильно понял.

Я тоже так понял. Просто вопрос такой: зачем одновременно в памяти 2 мильёна путей?


 
@!!ex ©   (2007-12-11 13:32) [39]

> [38] Skyle ©   (11.12.07 13:30)

х.з.

Кстати, автор, а может тебе дерево хранить? Тогда не будет дублирующей информации.
И поиск файла, если что, будет значительно быстрее.


 
Ruzzz ©   (2007-12-11 13:54) [40]

MemoryMappedFile - тоже идея, и про дерево идея хорошая, действительно! подумаю над этим, спасибо!



Страницы: 1 2 вся ветка

Форум: "Начинающим";
Текущий архив: 2008.01.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.005 c
2-1197028876
Мурзик
2007-12-07 15:01
2008.01.06
Как удалить выделенный контрол?


15-1196713499
Ega23
2007-12-03 23:24
2008.01.06
Я что-то пропустил?


2-1197224693
slavon
2007-12-09 21:24
2008.01.06
Создание массива компонентов в real-time


9-1164813712
nordic3
2006-11-29 18:21
2008.01.06
прыжок в игре


2-1197294681
Zheksik
2007-12-10 16:51
2008.01.06
Почему в Memo и Блокноте разное выравнивание текста?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский