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

Вниз

маппинг файлов   Найти похожие ветки 

 
Arm79 ©   (2007-06-06 16:58) [0]

Здравствуйте. Сейчас пишу анализатор логовых файлов, решил использовать маппинг файлов. Явных проблем не было, но смущает большое время доступа к маппированным данным.
Пробовал открыть файл размером 100 мегов.

Таким кодом создаю маппинг, использую случай wmReadShare
procedure 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
15-1184710325
Германн
2007-07-18 02:12
2007.08.19
Компилятор Дельфи


15-1184841211
Один
2007-07-19 14:33
2007.08.19
Вопрос


2-1185117841
Elerond
2007-07-22 19:24
2007.08.19
Реестр


1-1181499519
имя
2007-06-10 22:18
2007.08.19
RichEdit глюк


15-1184750417
БарЛог
2007-07-18 13:20
2007.08.19
Сумма нескольких полей MySQL





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский