Форум: "Начинающим";
Текущий архив: 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