Форум: "Основная";
Текущий архив: 2007.08.19;
Скачать: [xml.tar.bz2];
Внизмаппинг файлов Найти похожие ветки
← →
Arm79 © (2007-06-06 16:58) [0]Здравствуйте. Сейчас пишу анализатор логовых файлов, решил использовать маппинг файлов. Явных проблем не было, но смущает большое время доступа к маппированным данным.
Пробовал открыть файл размером 100 мегов.
Таким кодом создаю маппинг, использую случай wmReadShareprocedure TCustomMappedFile.Open;
var
FileMode: Integer;
PageMode: Integer;
MapMode : Integer;
begin
case FWorkMode of
wmWrite:
begin
FileMode := fmOpenReadWrite;
PageMode := PAGE_READWRITE;
MapMode := FILE_MAP_ALL_ACCESS;
end;
wmReadShare:
begin
FileMode := fmOpenRead + fmShareDenyNone;
PageMode := PAGE_READONLY;
MapMode := FILE_MAP_READ;
end;
wmWriteShare:
begin
FileMode := fmOpenReadWrite + fmShareDenyNone;
PageMode := PAGE_READWRITE;
MapMode := FILE_MAP_ALL_ACCESS;
end;
else
begin
FileMode := fmOpenRead;
PageMode := PAGE_READONLY;
MapMode := FILE_MAP_READ;
end;
end;
iFileHandle := FileOpen(FFileName, FileMode);
if iFileHandle >= 0
then begin
FFileSize := FileSeek(iFileHandle, 0, 2);
iMapHandle := CreateFileMapping(iFileHandle, nil, PageMode, 0, 0, nil);
if iMapHandle > 0
then begin
FDataPtr := MapViewOfFile(iMapHandle, MapMode, 0, 0, 0);
end;
end;
if (iFileHandle < 0) or (iMapHandle <=0) or not Assigned(FDataPtr)
then begin
GetErrorMessage;
try
if iMapHandle > 0
then CloseHandle(iMapHandle);
except
end;
try
if iFileHandle >=0
then FileClose(iFileHandle);
except
end;
iFileHandle := 0;
iMapHandle := 0;
FDataPtr := nil;
RaiseError;
end;
end;
все вроде нормально, но функция StrPos почему то очень долго думает. Первый вызов функции вызывает зависание программы на минутуfunction TCustomLogReader.IsNodeExists(var Ptr: PAnsiChar; KeyWord: string; var Node: string): boolean;
var
BeginStr, EndStr: string;
pcTemp : PAnsiChar;
begin
Result := False;
Node := EmptyStr;
BeginStr := "<@" + KeyWord;
EndStr := KeyWord + "@>";
pcTemp := StrPos(Ptr, PAnsiChar(BeginStr));
if Assigned(pcTemp)
then begin
Inc(pcTemp, Length(BeginStr));
Ptr := pcTemp;
pcTemp := StrPos(pcTemp, PAnsiChar(EndStr));
if Assigned(pcTemp)
then begin
SetString(Node, Ptr, Integer(pcTemp) - Integer(Ptr));
Inc(pcTemp, Length(EndStr));
Ptr := pcTemp;
Result:= True;
end;
end;
end;
Может я изначально неправильно что то использую? В чем могут быть траблы? Или так и должно быть? Я, например, часто пользуюсь viewer-ом от Total Commander, он файлы такого размера влет открывает, и ищет в них текст гораздо шустрее
← →
Leonid Troyanovsky © (2007-06-06 21:19) [1]
> Arm79 © (06.06.07 16:58)
> Может я изначально неправильно что то использую?
Изначально непонятно, как оное планировалось использовать.
Если требуется произвольный доступ, то неясно, почему StrPos,
а не, скажем, разбор всего файла.
Если доступ последовательный, а StrPos лишь для примера, то неясно,
что хотелось от filemapping.
--
Regards, LVT.
← →
Arm79 © (2007-06-07 14:18) [2]Файл имеет структуру:
<@entry
...
entry@>
<@entry
...
entry@>
<@entry
...
entry@>
и т.д.
Он может быть большого размера, до 500-600 Мбайт, поэтому я решил попробовать использовать FileMapping
Алгоритм работы следующий:
Получить указатель на данные, затем в цикле (ПОКА НАХОДИТСЯ пара <@entry entry@> производить анализ данных между ними, и перемещаться далее
pcTemp := DataPtr;
while IsNodeExists(pcTemp, "entry", sNode)
do begin
if Assigned(FonNode)
then FOnNode(Self,
Value(sNode, "datetime"),
Value(sNode, "category"),
Value(sNode, "place"),
Value(sNode, "text"));
end;
← →
MBo © (2007-06-07 14:20) [3]пара <@entry entry@> может находиться на разных строках?
← →
Arm79 © (2007-06-07 14:22) [4]она и находится на разных строках )))
вот пример из файла:<@entry
<@datetime 09:09:39:213 datetime@>
<@category Информация category@>
<@place TfrmMain.Create place@>
<@text Началась ротация логов... text@>
entry@>
<@entry
<@datetime 09:09:39:229 datetime@>
<@category Информация category@>
<@place TfrmMain.Create place@>
<@text Окончание ротации логов text@>
entry@>
<@entry
<@datetime 09:09:39:229 datetime@>
<@category Информация category@>
<@place TfrmMain.aFileGetBrokersExecute place@>
<@text Включена работа через ADO text@>
entry@>
<@entry
<@datetime 09:57:51:305 datetime@>
<@category Информация category@>
<@place TfrmMain.aFileGetBrokersExecute place@>
<@text Начало соединения... text@>
entry@>
← →
MBo © (2007-06-07 14:29) [5]Похоже, что достаточно жесткий формат, тогда проще построчно читать.
По строке <@entry переходим в состояние " читаем данные"
Если в состоянии "читаем данные" встретили строку entry@> (или конец файла, если это возможно) - обрабатываем блок и переходим в состояние " ждем нового блока"
← →
Arm79 © (2007-06-07 14:32) [6]То есть я так понял вы рекомендуете отказаться от FileMapping и использовать обычный ReadLn?
Наверное я так и сделаю, но ведь хотелось бы разобраться почему через FileMapping не получается...
← →
MBo © (2007-06-07 14:40) [7]>То есть я так понял вы рекомендуете отказаться от FileMapping и использовать обычный ReadLn
Не обязательно, можно с маппингом построчно читать - искать символы перевода строки. Не исключено, что можно в пару раз скорость чтения поднять по сравнению с Readln, но если разбор данных ведется заметно дольше чтения- то смысла особого нет.
← →
Arm79 © (2007-06-07 14:53) [8]
> MBo © (07.06.07 14:40) [7]
> >То есть я так понял вы рекомендуете отказаться от FileMapping
> и использовать обычный ReadLn
>
> Не обязательно, можно с маппингом построчно читать - искать
> символы перевода строки. Не исключено, что можно в пару
> раз скорость чтения поднять по сравнению с Readln, но если
> разбор данных ведется заметно дольше чтения- то смысла особого
> нет.
в том то и дело, что именно поиск символов и подстрок гораздо больше отнимает времени чем разбор найденных данных.
банальный StrPos в самый первый поиск целую минуту думает.
Сейчас буду пробовать самому написать поиск подстроки
← →
homm © (2007-06-07 15:01) [9]> банальный StrPos в самый первый поиск целую минуту думает.
Во время думания обращается к жесткому диску?
← →
MBo © (2007-06-07 15:02) [10]>банальный StrPos
так не надо им пользоваться
чтение одной строки:
function TMMFTextRead.ReadLine: string;
var
i: integer;
begin
i := 0;
PMap := @PBegin[FPosition];
while (FPosition + i < FSize) and (PMap[i] <> 13) do
Inc(i);
SetString(Result, PChar(PMap), i);
Inc(FPosition, i + 2);
end;
PBegin - PByteArray
← →
Deka © (2007-06-07 15:12) [11]Возможно надо оптимизировать код функции StrPos конкретно для Вашего применения ...
← →
Arm79 © (2007-06-07 15:40) [12]
> homm © (07.06.07 15:01) [9]
> > банальный StrPos в самый первый поиск целую минуту думает.
>
>
> Во время думания обращается к жесткому диску?
Грузит процессор со страшной силой
> Deka © (07.06.07 15:12) [11]
> Возможно надо оптимизировать код функции StrPos конкретно
> для Вашего применения ...
Думаю, что слегка переделанный вариант MBo © (07.06.07 15:02) [10] (отдельное спасибо за участие) и и есть там самая оптимизация функции
← →
Anatoly Podgoretsky © (2007-06-07 19:36) [13]При чтение с помощью ReadLn вообще никакой Pos не требуется и размер файла не ограничен.
← →
Arm79 © (2007-06-09 16:59) [14]
> Anatoly Podgoretsky © (07.06.07 19:36) [13]
> При чтение с помощью ReadLn вообще никакой Pos не требуется
> и размер файла не ограничен.
Я в курсе )). Просто хочу потренироваться в этой области.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2007.08.19;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.048 c