Форум: "Начинающим";
Текущий архив: 2007.10.14;
Скачать: [xml.tar.bz2];
Вниз
Объявление "лишних" переменных в процедуре. Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.056 c