Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.10.14;
Скачать: CL | DM;

Вниз

Объявление "лишних" переменных в процедуре.   Найти похожие ветки 

 
Riply ©   (2007-08-27 16:41) [0]

Здравствуйте !
Допустим, у нас есть следующее:
некая глобальная переменная GlobEntrySize: DWord,
значение которой может оказаться не равно ENTRY_SIZE_1024
на одном из 10 тысяч подопытных дисков
и
рекурсивная процедура FileRecordScanIO,
которая вызывается очень много раз для каждого конкретного диска.

var
GlobEntrySize: DWord;

function _FileRecordScanIO_1024(const ObjLcn: _LCN; const pObjName: PNTFS_Name; const pScan: PMFT_ScanParamsW): DWord;
var
Buff: array[0..pred(ENTRY_SIZE_OUTPUT_1024)] of Byte;
begin
Result := _FileRecordParsingIO(@Buff, ObjLcn, pObjName, pScan);// некая обработка
end;

function _FileRecordScanIO(const ObjLcn: _LCN; const pObjName: PNTFS_Name; const pScanW: PMFT_ScanParamsW): DWord;
var
pBuffer: PByte;
begin
pBuffer := GetMemory(GlobEntrySize);
try
 Result := _FileRecordParsingIO(pBuffer, ObjLcn, pObjName, pScanW);
finally
 FreeMem(pBuffer);
end;
end;

function FileRecordScanIO(const ObjLcn: _LCN; const pObjName: PNTFS_Name; const pScanW: PMFT_ScanParamsW): DWord;
begin
if GlobEntrySize > ENTRY_SIZE_1024
 then Result := _FileRecordScanIO(ObjLcn, pObjName, pScanW)
 else Result := _FileRecordScanIO_1024(ObjLcn, pObjName, pScanW);
end;


Имеет ли смысл городить огород с "разнесением" процедур (как в примере) или лучше
Buff: array[0..pred(ENTRY_SIZE_OUTPUT_1024)] объявить внутри _FileRecordScanIO ?
P.S.
Не зависимо от ответа, хотелось бы понять "почему" :)


 
Игорь Шевченко ©   (2007-08-27 17:06) [1]

Не проще ли выделить потребный буфер в тот момент, когда станет известно значение GlobEntrySize, и пользоваться им ? Насколько я понимаю, оно не меняется в процессе работы ?


 
Riply ©   (2007-08-27 17:10) [2]

> [1] Игорь Шевченко ©   (27.08.07 17:06)
>Не проще ли выделить потребный буфер в тот момент, когда станет известно
>значение GlobEntrySize, и пользоваться им ?
Один и тот же буфер не получается использовать из-за рекурсии.
Для каждого вызова должна быть "своя личная область памяти"


 
Игорь Шевченко ©   (2007-08-27 17:16) [3]

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


 
Leonid Troyanovsky ©   (2007-08-27 17:50) [4]


> Riply ©   (27.08.07 16:41)  

> рекурсивная процедура FileRecordScanIO,
> которая вызывается очень много раз

Очень много может не поместиться в 1Мб - размер стека по умолчанию.
А еще, у локальной процедуры есть ограничение на размер локальных
переменных - 64K, если мне не изменяет склероз.

Т.е., здесь лучше GetMem - FreeMem.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-08-27 17:52) [5]


> Игорь Шевченко ©   (27.08.07 17:16) [3]

> бы и так далее, со всеми остановками до станции Можайск
> Смоленского направления.

Бываешь в тех краях?

--
Regards, LVT.


 
Игорь Шевченко ©   (2007-08-27 18:01) [6]

Leonid Troyanovsky ©   (27.08.07 17:52) [5]

В прошлом :) Голос на вокзале въелся в память.


 
Riply ©   (2007-08-27 21:15) [7]

>[3] Игорь Шевченко © (27.08.07 17:16)
>я бы сделал иначе...
Очень долго думала.
На настоящий момент, мне не удается представить себе реализацию предложенного.
Слишком много типов станций и развилок на Можайск Смоленском направлении
( взаимных ссылок и переплетений в коде :).
Я понимаю, что это плохо, но избавиться пока не получается :(
Сам "объект нужного мне формата" может оказаться не объектом, а списком
адресов, которые надо читать. Точно так же как и любой из его "подобъектов".
Иными словами: для парсинга почти любой из структур MFT
может потребоваться вызов процедуры чтения.

>[4] Leonid Troyanovsky © (27.08.07 17:50)
>Очень много может не поместиться в 1Мб - размер стека по умолчанию.
>А еще, у локальной процедуры есть ограничение на размер локальных
>переменных - 64K, если мне не изменяет склероз.
>Т.е., здесь лучше GetMem - FreeMem.
А если у нас вызовов то много, но рекурсия не очень "глубокая" ?
Рекомендации останутся такими же ?

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

В одной из веток форума (не смогла ее найти) читала, что при
рекурсии следует избегать блоков try/finally,
а слишком частый вызов GetMem - FreeMem ведет к фрагментации памяти.
В общем-то эти два утверждения и послужили поводом для создания данной ветки.


 
Leonid Troyanovsky ©   (2007-08-27 21:39) [8]


> Riply ©   (27.08.07 21:15) [7]


> А если у нас вызовов то много, но рекурсия не очень "глубокая"
> ?
> Рекомендации останутся такими же ?

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

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

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

> а слишком частый вызов GetMem - FreeMem ведет к фрагментации
> памяти.

Если все размеры буферов известны, то можно выделить заведомо
большой блок VirtualAlloc и и собс-ручно нарезать его на массивы буферов.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-08-27 22:23) [9]


> Riply ©   (27.08.07 21:15) [7]

> а слишком частый вызов GetMem - FreeMem ведет к фрагментации

Если, скажем, все буферы одного размера, то фрагментации
не будет. Да и, в любом случае, сделать их одного размера
было б гораздо удобней.

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

И, во-ще, о буферах какаого размера речь?

--
Regards, LVT.


 
Riply ©   (2007-08-28 03:32) [10]

>[9] Leonid Troyanovsky © (27.08.07 22:23)
>Если, скажем, все буферы одного размера, то фрагментации
>не будет. Да и, в любом случае, сделать их одного размера
>было б гораздо удобней.
В пределах одного диска они все одинакового размера.

>И, во-ще, о буферах какаого размера речь?
В любом случае размер не может превышать максимума из
(размера кластера и размера записи в MFT) плюс 32 байта.


 
Игорь Шевченко ©   (2007-08-28 09:29) [11]

А вот народ всякие lookaside-list"ы придумывает зачем-то...Не иначе с жиру бесится.


 
Leonid Troyanovsky ©   (2007-08-28 09:35) [12]


> Riply ©   (28.08.07 03:32) [10]

> В любом случае размер не может превышать максимума из
> (размера кластера и размера записи в MFT) плюс 32 байта.

Таким мне представляется оптимистичный подход:
VirtualAlloc блок размером BufSize * MaxLevel
Это будет двумерный массив [0..BufSize-1, 0..MaxLevel-1] of byte

Теперь, вместе с парметрами рекурсивной функции передаем
var Level: Longint, который будет использоваться  для выбора буфера.

Т.е., при входе в функцию - inc(Level), при выходе - dec.

Пессемистичный подход - Get/FreeMem на каждом уровне.

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

--
Regards, LVT.


 
Riply ©   (2007-08-28 15:37) [13]

>[12] Leonid Troyanovsky ©   (28.08.07 09:35)
Спасибо.
Наверное, попробую использовать "оптимистичный подход".

>[11] Игорь Шевченко ©   (28.08.07 09:29)
>А вот народ всякие lookaside-list"ы придумывает зачем-то...Не иначе с жиру бесится.
Не знала, что такие существуют.
Почитала общее описание их предназначения. Все так красиво выглядит :)


 
GrayFace ©   (2007-09-16 13:07) [14]

Riply ©   (27.08.07 17:10) [2]
Один и тот же буфер не получается использовать из-за рекурсии.
Для каждого вызова должна быть "своя личная область памяти"

_FileRecordParsingIO мыжет вызвать FileRecordScanIO?

Leonid Troyanovsky ©   (27.08.07 17:50) [4]
А еще, у локальной процедуры есть ограничение на размер локальных
переменных - 64K, если мне не изменяет склероз.

Ограниечние компиллятора?

Riply ©   (27.08.07 21:15) [7]
В одной из веток форума (не смогла ее найти) читала, что при
рекурсии следует избегать блоков try/finally

Скорее всего, речь об экономии места в стеке.


 
Riply ©   (2007-09-16 18:17) [15]

> [14] GrayFace ©   (16.09.07 13:07)
> _FileRecordParsingIO мыжет вызвать FileRecordScanIO?
Может вызывать, если ему это понадобиться :)


 
Leonid Troyanovsky ©   (2007-09-20 15:22) [16]


> GrayFace ©   (16.09.07 13:07) [14]

> переменных - 64K, если мне не изменяет склероз.
> Ограниечние компиллятора?

Только, вот, не помню какого :)

C ограничением я погнал, sorry.

--
Regards, LVT.



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

Текущий архив: 2007.10.14;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.027 c
2-1189955487
олег79
2007-09-16 19:11
2007.10.14
можно ли с помощью диалога OpenDialog открыть не файл а папку?


15-1189804543
Petr V. Abramov
2007-09-15 01:15
2007.10.14
день борьбы со спамом :)


3-1181047173
Альф
2007-06-05 16:39
2007.10.14
Прерывание выполнения SELECT


2-1189853106
ProgRAMmer Dimonych
2007-09-15 14:45
2007.10.14
Снова проблемы (вырезка элементов массива)


15-1189689035
novill
2007-09-13 17:10
2007.10.14
Кто знает как из DCU вытянуть исходники?