![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Быстрый доступ к файлу [D7]
pirate © (2006-05-24 21:15:00)Уважаемые мастера!
Пожалуйста, посоветуйте самый быстрый способ побайтового чтения всего файла (Он у меня 16 Мб, загружается около 2 минут). А вот к примеру Lingvo загружает свою базу слов практически мгновенно. Как бы и мне ускорить процесс чтения из файла?
pirate (2006-05-29 15:37:00) [1]Хочу поблагодарить всех участников обсуждения: загрузка проходит за 0.11 сек. Спасибо!
tytus (2006-05-26 15:41:00) [2]han_malign[20] правильно пишет. Я сам давно ТОЛЬКО так работаю - файлы размером в 160 метров обрабатываются на раз. Для поиска нужного слова использую StrPos, которая возвращает указатель на найденное слово. Начало отображения описываю как PByte. Очень просто работать:INC, DEC. Если нужно скопировать строку (слово) - использую MOVE. Довольно хорошо эту тему описали Ксавье и Пачеко.
pirate (2006-05-26 15:22:00) [3]
> Имеем структуру :
> RDicWord = record // Можно поиграть упаковкой
> OffSet : Int64;
> Length : DWord;
> end;
> Обявляем динамический массив :
> DicWordList : array of RDicWord;
Разве на написано:
> type TWord=record
> wOFF:int64; //
> wLEN:byte; // сдвиг и длина самого слова
> dOFF:int64;
> dLEN:integer; // сдвиг и длина его описания
> end;
>
> type TDict=record
> count:longint;
> words:array of TWord; // динамический массив записей
> end;
Я ведь так и делаю.
http://www.delphimaster.ru/articles/dyntable/index.html
Вот это действительно тема!
ANB (2006-05-25 16:08:00) [4]Да, всеь словарь можно хранить и просто в длинной строке. Тогда точно будет работать. А ползать по словарю можно через указатели на RDicWord.
ANB (2006-05-25 16:07:00) [5]Значится, вариант решения задачи.
Сами слова в словаре не храним - это хорошо, следовательно, описание слова имеет фиксированнуб длинну.
Имеем структуру :
RDicWord = record // Можно поиграть упаковкой
OffSet : Int64;
Length : DWord;
end;
Обявляем динамический массив :
DicWordList : array of RDicWord;
Узнаем размер файла (FileSeek). Делим длинну на размер записи SizeOf(RDicWord). Обрабатываем некруглую длинну (проще отбросить лишние байты в файле).
Устанавливаем длинну массива DicWordList. И за одну операцию чтения прямо в него загружаем содержимое файла.
Все имхо, мог чего и напутать. Критики - поправьте плиз.
han_malign (2006-05-25 15:53:00) [6]упс: len:= i - offs;
- это другая len, не та что (i<len)... :)
han_malign (2006-05-25 15:52:00) [7]
> s1:=s1+buf[i];
> if (c1=#13)and(c2=#10) then // проверка на "новую строку"
> begin
> p:=pos('#',s1);
> q:=length(s1);
i:= 0;
while(i < len)do begin
while((i < len)and(buf[i] in [ #10, #13]))do inc(i);
offs:= i;
while((i < len)and(not(buf[i] in [ #10, #13, '#'])))do inc(i);
dush:= i - offs;
while((i < len)and(not(buf[i] in [ #10, #13])))do inc(i);
len:= i - offs;
with D.words[D.count-1] do begin
...
end;
end;
- примерно так, а операции со строками(изменение, поиск) - тоже не маленькие, и весьма...
han_malign (2006-05-25 15:40:00) [8]
> файлы, отображаемые в память посмотрите, плиз..
- 4-и раз вставлять не буду - смотри тут
http://www.delphimaster.ru/cgi-bin/forum.pl?n=0&id=1146027596&p=2
- 16 Мб - халява, спокойно целиком отмапируется...
IOs (2006-05-25 15:24:00) [9]файлы, отображаемые в память посмотрите, плиз..
Конечно, это не побайтово :-), но все же...
Loginov Dmitry (2006-05-25 15:15:00) [10]pirate © (25.05.06 13:25) [17]
Потом еще много чего оптимизировал, добился загрузки за 22 сек
Вам еще много чего придется оптимизировать. Нормальная скорость загрузки для вашего случая не должна превышать одной секунды.
pirate (2006-05-25 13:25:00) [11]Спасибо большое.
Я переделал функцию для TFileStream.
заработала быстрее.
Длину хранить в начале я не могу. Придумал вот что:
Сделал заведомо большой размер, а после загрузки уменьшаю его до необходимого.А если в процессе загрузки размера не хватает, то начинаем его увеличивать...
Заработала во много раз быстрее. Потом еще много чего оптимизировал, добился загрузки за 22 сек. Но и это многовато.
Я взял и сохранил количество и сдвиги всех записей в отдельном файле, что-то вроде индексного файла в 1С Бухгалтерии.
Но вот в чем проблема:
Написал функцию, которая делает seek по сдвигу и считывает Len байт.
Хотел загрузить в TList список имеющихся слов: стал в цикле загружать слова в список и получил 41 секунду загрузки. В первом случае, когда я
обрабатывал весь файл, на ходу загружая список слов затрачивал 22сек.
Почему так?
Из-за seek'а в цикле?
Romkin (2006-05-25 12:17:00) [12]pirate © (24.05.06 22:41) [11] Делай что хочешь, но наращивать длину на 1 в цикле - эффектное убийство памяти :)
Есть же TList, TStringList и тд.
http://www.delphimaster.ru/articles/dyntable/index.html
Читай первые несколько абзацев.
Подсказка: хотя там для строк, но все действительно и для массива
Loginov Dmitry (2006-05-25 08:52:00) [13]Leonid Troyanovsky © (24.05.06 23:21) [14]
Была какая-то сверх-точная, но сверх-сложная формула для вычисления разов. Она говорит, что "по крайней мере в два". Найду - выложу :)))
Leonid Troyanovsky (2006-05-24 23:21:00) [14]
> Loginov Dmitry © (24.05.06 22:55) [13]
> чтения рекомендую использовать TMemoryStream. По крайней
> мере в пару раз скорость загрузки должна
А почему именно в два?
А не, скажем, в полтора?
--
Regards, LVT.
Loginov Dmitry (2006-05-24 22:55:00) [15]Ваш файл не очень большой (16 Мбайт), поэтому для ускорения чтения рекомендую использовать TMemoryStream. По крайней мере в пару раз скорость загрузки должна увеличиться (по сравнению с BlockRead).
Джо (2006-05-24 22:48:00) [16]> [11] pirate © (24.05.06 22:41)
> Но я ведь теоретически не знаю размер словаря, для того
> и динамический массив. А так я сразу мог бы сделать статический
> массив.
Один из вариантов: хранить длину массива в файле, перед данными. То есть, алгоритм сведется к следующему: прочитать из файла длину массива, установить ее (один раз!) и далее в уже заданный массив считывать сами данные.
pirate (2006-05-24 22:41:00) [17]Но я ведь теоретически не знаю размер словаря, для того и динамический массив. А так я сразу мог бы сделать статический массив.
Джо (2006-05-24 22:39:00) [18]Все дело в SetLength. Нужно сделать так, чтобы длину дин. массива задавать один раз.
pirate (2006-05-24 22:21:00) [19]Странно.
Что может быть причиной томозов?
Может потому что я использую динамический массив?
Кстати, следует отметить, что у меня сначала дело идет быстро, а потом начинает тормозить, все сильнее и сильнее.
Я хочу загрузить в программу эту самую структуру словаря.
Словарь представлен в виде:
СЛОВО#Описание
СЛОВО#Описание и т д
я хочу в массив загрузить байтовые сдвиги всех слов и их описаний, а потом считывать нужное слово. Но что-то так долго грузит словарь, что я в шоке прямо...
type TWord=record
wOFF:int64; //
wLEN:byte; // сдвиг и длина самого слова
dOFF:int64;
dLEN:integer; // сдвиг и длина его описания
end;
type TDict=record
count:longint;
words:array of TWord; // динамический массив записей
end;
procedure LoadDict(path:string;var D:TDict);
var
FromF: file;
NumRead: Integer;
Buf: array[1..512] of Char;
c1,c2,c3,c4,c5:char;
i,j:integer;
k:int64;
s1,s2,s3:string;
B,p,q:integer;
begin
k:=1; // общий сдвиг, необходимый для рассчетов.
B:=0;
s1:='';
c1:=#0;
c2:=#0;
...................................
for i:=1 to numread do
begin
c1:=c2;
c2:=buf[i];
s1:=s1+buf[i];
if (c1=#13)and(c2=#10) then // проверка на "новую строку"
begin
p:=pos('#',s1);
q:=length(s1);
D.count:=D.count+1;
SetLength(D.words,D.count);
D.words[D.count-1].wOFF:=k;
D.words[D.count-1].wLEN:=p-1;
D.words[D.count-1].dOFF:=k+p;
D.words[D.count-1].dLEN:=q-p-3; // записываем координаты нужных строк.
rd:=d.count;
if (rd mod 1000)=0 then //раз в тысячу слов делаем ProcessMesages
begin
form1.Caption:=inttostr(rd)+' '+copy(s1,1,p-1);
application.ProcessMessages;
end;
k:=k+q;
s1:='';
end;
end;
.....................
pirate (2006-05-24 21:56:00) [20]Ладно, спасибо большое!