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

Вниз

Чтение из 2-х гигового лога...   Найти похожие ветки 

 
Owa   (2008-02-04 23:24) [0]

Здравствуйте, хочу у вас поинтересоваться какой метод лучше применять для быстрого поиска в файле?

Лог сервера. Лог текстовой с кодировкой юникод.

Я использую вот что:


var
 BaseItem : string;
 F : textfile;
 STL: TStringList;
begin
if key = VK_return then
begin
STL := TStringList.Create;

AssignFile(F, FP);
reset(f);
try
 while not Eof(F) do
  begin
   Readln(F, BaseItem);
    If pos(pchar(AnsiLowerCase(Edit1.Text)), pchar(AnsiLowerCase(BaseItem))) <>0 then
       STL.Add(UTF8Decode(BaseItem));
       Application.ProcessMessages();
  end;

finally
 CloseFile(F);
end;

RichEdit1.Lines.Text := STL.Text;
Application.ProcessMessages();

STL.Free;
end;


При маленьком объеме файла результат получается давольно быстро. А когда произвожу поиск в файле размером больше 2 гигов то процесс длится очень и очень долго. Есть-ли какой-то более быстрый метод для поиска в файле?
Спасибо.


 
Owa   (2008-02-04 23:25) [1]

Не то ткнул для выделения кода по запаре, простите..


 
DVM ©   (2008-02-04 23:48) [2]


> Application.ProcessMessages();

Убери. Либо быстро либо красиво.


> AnsiLowerCase(Edit1.Text)),

Зачем каждый виток цикла делать одно и то же - переводить в нижний регистр то, что можно перевести туда до цикла?


 
DVM ©   (2008-02-04 23:51) [3]

И может читать стоит более большими блоками, чем по одной строке?


 
palva ©   (2008-02-04 23:52) [4]

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


 
ketmar ©   (2008-02-05 00:20) [5]

>[0] Owa (04.02.08 23:24)
а чо ищем-то? Boyer–Moore string search algorithm не пойдёт?


 
Amoeba ©   (2008-02-05 02:15) [6]

А может не грузить 2 гига в StringList (ЖУТЬ!!! Не дай Бог, чтобы такое приснилось), а использовать MemoryMapping и далее работать как с байтовым массивом-строкой?


 
Германн ©   (2008-02-05 02:21) [7]


> ketmar ©   (05.02.08 00:20) [5]
>
> >[0] Owa (04.02.08 23:24)
> а чо ищем-то? Boyer–Moore string search algorithm не пойдёт?
>
>

Ну если мне не изменяет мой склероз, то авторов там всё-таки трое. "Boyer-Moore-Horspool pattern searching algorithm".


 
ketmar ©   (2008-02-05 03:00) [8]

>[7] Германн ©(05.02.08 02:21)
таки двое. и завсегда было двое. параллельно с ними ещё кто-то то же придумал, и куча народу сочинила модификации.


 
ketmar ©   (2008-02-05 03:01) [9]

и процитировал я поисковую фразу для гугля. по которой сразу ныжные ссылочки даёт.


 
Slym ©   (2008-02-05 05:11) [10]

а так долго ищет?
" VBScript.
Option Explicit

if WScript.Arguments.Count() = 0 Then
 WScript.StdOut.WriteLine "No params"
 WScript.StdOut.WriteLine "cscript.exe cf.vbs filename"
 WScript.Quit()
End If

Dim RE,FSO,F
Set RE = New RegExp
RE.IgnoreCase = True
RE.Pattern = "String to find"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set File= FSO.GetFile(WScript.Arguments(0))
WScript.StdOut.WriteLine ("Scan file: " + File.Path)
ScanFile File

Sub ScanFile(File)
 Dim InStream,OutStream, Line
 Set InStream = File.OpenAsTextStream
 Set OutStream = WScript.StdOut
 While Not InStream.AtEndOfStream
   Line = InStream.ReadLine
   If (Line<>"") and(RE.Test(Line)) Then
     OutStream.WriteLine(Line)
   End If
 WEnd
 InStream.Close()
 InStream=null
End Sub


 
хам   (2008-02-05 09:33) [11]

> [3] DVM ©   (04.02.08 23:51)
> И может читать стоит более большими блоками, чем по одной
> строке?

Это уже забота виндового кеша, а он, поверь, с ней справляется.


 
Skyle ©   (2008-02-05 10:29) [12]


> хам   (05.02.08 09:33) [11]
> > [3] DVM ©   (04.02.08 23:51)
> > И может читать стоит более большими блоками, чем по одной
>
> > строке?
>
> Это уже забота виндового кеша, а он, поверь, с ней справляется.
>

А мягкое всяко лучше красного. И вообще, это вам не громкое.


 
хам   (2008-02-05 10:42) [13]

> [12] Skyle ©   (05.02.08 10:29)
> А мягкое всяко лучше красного. И вообще, это вам не громкое.

Рад за тебя.


 
Skyle ©   (2008-02-05 11:01) [14]


> хам   (05.02.08 10:42) [13]
> > [12] Skyle ©   (05.02.08 10:29)
> > А мягкое всяко лучше красного. И вообще, это вам не громкое.
>
>
> Рад за тебя.

А я за тебя - нет.

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


 
Игорь Шевченко ©   (2008-02-05 11:05) [15]

Skyle ©   (05.02.08 11:01) [14]

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

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


 
Skyle ©   (2008-02-05 11:11) [16]


> Игорь Шевченко ©   (05.02.08 11:05) [15]

Задача не моя, просто решил уточнить, что тут более одного этажа.


 
хам   (2008-02-05 11:13) [17]

> [14] Skyle ©   (05.02.08 11:01)
> Не надо считать, что оптимизация чтения с диска (виндовый
> кэш) и оптимизация обработки внутри программы - это одно
> и то же.

А чего, в [3] я где-то пропустил оптимизацию обработки? Да ито, что в [4] — тоже не оптимизация, а гемморой называется. Оптимизировать по идее нужно pos, но он всяко быстрее диска работает и так…


 
clickmaker ©   (2008-02-05 11:36) [18]


> Owa   (04.02.08 23:24)

RichEdit - плохой кандидат для 2-гиговых логов. Лучше уж просто Memo.
Либо замапить файл и рисовать текст самому - только видимую часть, с учетом прокрутки


 
хам   (2008-02-05 11:39) [19]

> [18] clickmaker ©   (05.02.08 11:36)
> RichEdit - плохой кандидат для 2-гиговых логов.

Любой компонент — любой кандидат для 2-гиговых логов. Пользователю за раз никогда не понадобится больше 100кб информации в одном контролле.


 
ANB   (2008-02-05 11:39) [20]


> Owa   (04.02.08 23:24)

1. Найти, что больше тормозит - чтение или поиск по строке.
Для этого  - закомментарить сравнение Поз и прогнать чисто чтение. Если будет так же медленно - то проблема в этом. ИМХО : реадлн - не самый шустрый способ прочитать файл.
2. Если будет летать - то оптимизить поиск по строке.


 
хам   (2008-02-05 11:41) [21]

> [20] ANB   (05.02.08 11:39)
> реадлн - не самый шустрый способ прочитать файл.

Я тебе так скажу: Прочитать файл с диска — не самый шустрый способ прочитьтать файл. А уж через что он читается, без раницы, все равно чтение с диска медленне копирования в оперативной памяти.


 
clickmaker ©   (2008-02-05 11:42) [22]


> Пользователю за раз никогда не понадобится больше 100кб
> информации в одном контролле.

не факт. Лично я сталкивался с ситуацией поиска в многометровом логе. Правда, я ничего для этого не писал, а юзал вьювер FAR"a )
В стандартные контролы только грузиться такой лог будет несколько минут (десятков секунд в лучшем случае)


 
palva ©   (2008-02-05 11:46) [23]

хам   (05.02.08 09:33) [11]
> Это уже забота виндового кеша, а он, поверь, с ней справляется.

Не понимаю о чем вы. Данные в сабже читаются однократно и не кэшируются. Может быть, вы надеетесь, что Windows будет буферизовать и читать данные большими блоками? Или компилятор делфи буферизует чтение данных? Ни то ни другое не происходит.
Вот если бы вы писали на си, вы действительно, не почувствовали бы особой разницы. В сишных библиотеках последовательный ввод данных буферизуется.


 
ANB   (2008-02-05 11:46) [24]


> хам   (05.02.08 11:41) [21]

Ща потестим . . .
ЗЫ. Кстати, при чтении большими блоками есть грабля из за юникодовой кодировки. Т.е. мона умудрится прочитать токо один байт двухбайтного символа.


 
хам   (2008-02-05 11:46) [25]

> [23] palva ©   (05.02.08 11:46)
> Может быть, вы надеетесь, что Windows будет буферизовать
> и читать данные большими блоками?

Я не надеюсь, я это точно знаю.


 
clickmaker ©   (2008-02-05 11:48) [26]


> ЗЫ. Кстати, при чтении большими блоками есть грабля из за
> юникодовой кодировки. Т.е. мона умудрится прочитать токо
> один байт двухбайтного символа.

для оптимального чтения размер блока должен быть кратен размеру кластера, т.е. минимум 512. По крайней мере, не должен быть нечетным


 
ANB   (2008-02-05 11:50) [27]

Милин. Делфи то нету пока :(
Попробовал фаром - файл 1 Гб, искал строку которой нет. Примерно 30 секунд. Т.е. быстрый способ есть :)


 
хам   (2008-02-05 11:52) [28]

> [26] clickmaker ©   (05.02.08 11:48)
> для оптимального чтения размер блока должен быть кратен
> размеру кластера, т.е. минимум 512.

Есть юникодовые кодировки с нефиксированным размером символа.


 
хам   (2008-02-05 11:52) [29]

> [26] clickmaker ©   (05.02.08 11:48)
> для оптимального чтения размер блока должен быть кратен
> размеру кластера, т.е. минимум 512.

Есть юникодовые кодировки с нефиксированным размером символа.


 
хам   (2008-02-05 11:53) [30]

> [27] ANB   (05.02.08 11:50)
> Попробовал фаром - файл 1 Гб, искал строку которой нет.
> Примерно 30 секунд.

1204/30 = 34 — примерно скорость линейного чтения современного жесткого диска.


 
palva ©   (2008-02-05 12:04) [31]


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

Заполнение большого файла 500000000 байт

{$APPTYPE CONSOLE}
var
 fo: textfile;
 i: Integer;
begin
 Assign(fo, "bigtest.txt");
 Rewrite(fo);
 for i:=1 to 10000000 do
   WriteLn(fo, "012345678901234567890123456789012345678901234567");
 closefile(fo);
end.

Построчное чтение

{$APPTYPE CONSOLE}
uses SysUtils;
var
 fo: textfile;
 i: Integer;
 s: string;
begin
 WriteLn(TimeToStr(now));
 Assign(fo, "bigtest.txt");
 Reset(fo);
 for i:=1 to 10000000 do begin
   ReadLn(fo, s);
   if pos(" ", s) > 0 then WriteLn("OK");
 end;
 closefile(fo);
 WriteLn(TimeToStr(now));
end.

11:42:18
11:42:45
27 секунд

Чтение большими блоками

{$APPTYPE CONSOLE}
uses SysUtils;
var
 fo: file;
 i: Integer;
 s: string;
begin
 WriteLn(TimeToStr(now));
 Assign(fo, "bigtest.txt");
 Reset(fo, 50000);
 SetLength(s, 50000);
 for i:=1 to 10000 do begin
   BlockRead(fo, s[1], 1);
   if pos(" ", s) > 0 then WriteLn("OK");
 end;
 WriteLn(TimeToStr(now));
 closefile(fo);
end.

11:52:03
11:52:11
8 секунд


 
palva ©   (2008-02-05 12:16) [32]


> хам   (05.02.08 11:46) [25]
> > [23] palva ©   (05.02.08 11:46)
> > Может быть, вы надеетесь, что Windows будет буферизовать
> > и читать данные большими блоками?

> Я не надеюсь, я это точно знаю.

Ну значит, вы неправы. Как и в том, что называете буферизацию кэшированием.


 
Slym ©   (2008-02-05 12:18) [33]

palva ©   (05.02.08 12:04) [31]
плохой тест... первое что бросилось - SetLength(s, 50000) - фиксированный буфер, а в первом варианте постоянно он пересоздается (ReadLn(fo, s);) а это утечка времени * 10млн - много


 
хам   (2008-02-05 12:20) [34]

первый вариант: 26 с, второй: 23 с. Хотя конечно, загрузка процессора меньше во втором случае ниже раза в 3-4.


 
ketmar ©   (2008-02-05 12:22) [35]

>[23] palva©(05.02.08 11:46)
>компилятор делфи буферизует чтение данных?

>В сишных библиотеках
как прикажешь понимать тебя, Саид?


>[30] хам (05.02.08 11:53)
FAR использует mmf и далеко не тупой strstr().


 
хам   (2008-02-05 12:23) [36]

ЗЫ. строку «if pos(" ", s) > 0 then WriteLn("OK");» упразднил, т.к. здесь у меня D7, а в D2006 она должны быть более быстрой за счет fastMM


 
Игорь Шевченко ©   (2008-02-05 12:24) [37]

palva ©   (05.02.08 12:04) [31]

У меня просьба - тесты местами поменяй ?

palva ©   (05.02.08 11:46) [23]


> Может быть, вы надеетесь, что Windows будет буферизовать
> и читать данные большими блоками?


Ага. Надеюсь. Более того, он это делает. Правда, "большой размер блока" - термин спорный, но несколько страниц за операцию чтения он читает.

"the Cache Manager reads further ahead for sequential access files--currently about three times more than files that are currently detected for sequential access. " (с) MSDN


 
Slym ©   (2008-02-05 12:24) [38]

на моем компе 8 секунд!:
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils,Windows;
var
 t:DWord;
 s:string;
 i:integer;
begin
 t:=GetTickCount;
 for i:=1 to 10000000 do
 begin
   s:=FloatToStr(Random);
   if s="" then exit;
 end;
 writeln(FloatToStr((GetTickCount-t)/1000));
 readln;
end.


 
хам   (2008-02-05 12:24) [39]

> [37] Игорь Шевченко ©   (05.02.08 12:24)
> У меня просьба - тесты местами поменяй ?

Кстати, да :)


 
palva ©   (2008-02-05 13:14) [40]


> Игорь Шевченко ©   (05.02.08 12:24) [37]
> palva ©   (05.02.08 12:04) [31]
> У меня просьба - тесты местами поменяй ?

У меня обед кончился экспериментировать.
Если вы хотите, чтобы до нас дошла какая-то известная вам высокая истина, то вы выбрали не тот метод. Обсудите условия эксперимента, объясните подноготную, подготовьте и прогоните правильные с вашей точки зрения тесты выложите результаты - в общем, сделайте сами все то, что нам советуете. А ваш опыт и знания мы и так уважаем.

Если вернуться к сабжу, то чтение большими блоками, если говорить о программе на паскале, в разы ускоряет процесс.

> Slym ©   (05.02.08 12:18) [33]
> palva ©   (05.02.08 12:04) [31]
> плохой тест...

Ну это возможно. Напишите хороший тест или модифицируйте нужным образом мой. Возьмите к примеру второй мой тест и поменяйте коэффициент блокирования. Длину блока сделайте 50 и выложите результат. А я сейчас не могу этим заниматься.



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

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

Наверх





Память: 0.56 MB
Время: 0.038 c
2-1202190088
Chebarov
2008-02-05 08:41
2008.03.02
TDbGriid


15-1198581317
Nucer
2007-12-25 14:15
2008.03.02
SendMessage из PHP


2-1202146357
Санек
2008-02-04 20:32
2008.03.02
popupmenu выбор итема


6-1181064594
samael6
2007-06-05 21:29
2008.03.02
Проблемы с ASender.Thread.Connection в Indy 9


2-1202109520
Vasilii777
2008-02-04 10:18
2008.03.02
Помогите запросить Key!





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