Форум: "Основная";
Текущий архив: 2006.07.09;
Скачать: [xml.tar.bz2];
ВнизБыстрый доступ к файлу Найти похожие ветки
← →
pirate © (2006-05-24 21:15) [0]Уважаемые мастера!
Пожалуйста, посоветуйте самый быстрый способ побайтового чтения всего файла (Он у меня 16 Мб, загружается около 2 минут). А вот к примеру Lingvo загружает свою базу слов практически мгновенно. Как бы и мне ускорить процесс чтения из файла?
← →
begin...end © (2006-05-24 21:20) [1]А зачем читать файл побайтно?
← →
Cash © (2006-05-24 21:20) [2]Потаму, что Lingvo не побайтово читает! У него есть структура словаря.
Словарь в файле, программа читает структуру и формирует словарь.
Поэтому она работает быстрее.
Используй TFileStream, низкий уровень и всякие такие примочки хорошо
сказываются на общении с файлом.
← →
pirate © (2006-05-24 21:26) [3]А у меня по моему структура тоже не маленькая.
И еще. Может подкинете пару ссылок на инфу о том как юзать TFileStream или свой пример?
← →
pirate © (2006-05-24 21:35) [4]Я вот простой blockread использую. Что-то никогда TFileStream не юзал..
← →
begin...end © (2006-05-24 21:40) [5]> pirate © (24.05.06 21:35) [4]
А можно увидеть, КАК Вы его используете?
← →
pirate © (2006-05-24 21:44) [6]Адын момент...
procedure LoadDict(path:string;var D:TDict);
var
FromF: file;
NumRead: Integer;
Buf: array[1..512] of Char;
...
i:integer;
..
begin
...
AssignFile(FromF, path);
Reset(FromF, 1);
repeat
BlockRead(FromF, Buf, SizeOf(Buf), NumRead);
for i:=1 to numread do
begin
....
end;
until (NumRead = 0);
CloseFile(FromF);
end;
← →
begin...end © (2006-05-24 21:54) [7]> pirate © (24.05.06 21:44) [6]
Вполне приличный код. У меня он читает 13-мегабайтный файл за время менее 1 секунды. Вероятно, основное время у Вас занимает обработка того, что прочитано (в цикле по i).
← →
pirate © (2006-05-24 21:56) [8]Ладно, спасибо большое!
← →
pirate © (2006-05-24 22:21) [9]Странно.
Что может быть причиной томозов?
Может потому что я использую динамический массив?
Кстати, следует отметить, что у меня сначала дело идет быстро, а потом начинает тормозить, все сильнее и сильнее.
Я хочу загрузить в программу эту самую структуру словаря.
Словарь представлен в виде:
СЛОВО#Описание
СЛОВО#Описание и т д
я хочу в массив загрузить байтовые сдвиги всех слов и их описаний, а потом считывать нужное слово. Но что-то так долго грузит словарь, что я в шоке прямо...
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;
.....................
← →
Джо © (2006-05-24 22:39) [10]Все дело в SetLength. Нужно сделать так, чтобы длину дин. массива задавать один раз.
← →
pirate © (2006-05-24 22:41) [11]Но я ведь теоретически не знаю размер словаря, для того и динамический массив. А так я сразу мог бы сделать статический массив.
← →
Джо © (2006-05-24 22:48) [12]> [11] pirate © (24.05.06 22:41)
> Но я ведь теоретически не знаю размер словаря, для того
> и динамический массив. А так я сразу мог бы сделать статический
> массив.
Один из вариантов: хранить длину массива в файле, перед данными. То есть, алгоритм сведется к следующему: прочитать из файла длину массива, установить ее (один раз!) и далее в уже заданный массив считывать сами данные.
← →
Loginov Dmitry © (2006-05-24 22:55) [13]Ваш файл не очень большой (16 Мбайт), поэтому для ускорения чтения рекомендую использовать TMemoryStream. По крайней мере в пару раз скорость загрузки должна увеличиться (по сравнению с BlockRead).
← →
Leonid Troyanovsky © (2006-05-24 23:21) [14]
> Loginov Dmitry © (24.05.06 22:55) [13]
> чтения рекомендую использовать TMemoryStream. По крайней
> мере в пару раз скорость загрузки должна
А почему именно в два?
А не, скажем, в полтора?
--
Regards, LVT.
← →
Loginov Dmitry © (2006-05-25 08:52) [15]Leonid Troyanovsky © (24.05.06 23:21) [14]
Была какая-то сверх-точная, но сверх-сложная формула для вычисления разов. Она говорит, что "по крайней мере в два". Найду - выложу :)))
← →
Romkin © (2006-05-25 12:17) [16]pirate © (24.05.06 22:41) [11] Делай что хочешь, но наращивать длину на 1 в цикле - эффектное убийство памяти :)
Есть же TList, TStringList и тд.
http://www.delphimaster.ru/articles/dyntable/index.html
Читай первые несколько абзацев.
Подсказка: хотя там для строк, но все действительно и для массива
← →
pirate © (2006-05-25 13:25) [17]Спасибо большое.
Я переделал функцию для TFileStream.
заработала быстрее.
Длину хранить в начале я не могу. Придумал вот что:
Сделал заведомо большой размер, а после загрузки уменьшаю его до необходимого.А если в процессе загрузки размера не хватает, то начинаем его увеличивать...
Заработала во много раз быстрее. Потом еще много чего оптимизировал, добился загрузки за 22 сек. Но и это многовато.
Я взял и сохранил количество и сдвиги всех записей в отдельном файле, что-то вроде индексного файла в 1С Бухгалтерии.
Но вот в чем проблема:
Написал функцию, которая делает seek по сдвигу и считывает Len байт.
Хотел загрузить в TList список имеющихся слов: стал в цикле загружать слова в список и получил 41 секунду загрузки. В первом случае, когда я
обрабатывал весь файл, на ходу загружая список слов затрачивал 22сек.
Почему так?
Из-за seek"а в цикле?
← →
Loginov Dmitry © (2006-05-25 15:15) [18]pirate © (25.05.06 13:25) [17]
Потом еще много чего оптимизировал, добился загрузки за 22 сек
Вам еще много чего придется оптимизировать. Нормальная скорость загрузки для вашего случая не должна превышать одной секунды.
← →
IOs (2006-05-25 15:24) [19]файлы, отображаемые в память посмотрите, плиз..
Конечно, это не побайтово :-), но все же...
← →
han_malign © (2006-05-25 15:40) [20]
> файлы, отображаемые в память посмотрите, плиз..
- 4-и раз вставлять не буду - смотри тут
http://delphimaster.net/view/1-1146027596/
- 16 Мб - халява, спокойно целиком отмапируется...
← →
han_malign © (2006-05-25 15:52) [21]
> 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:53) [22]упс: len:= i - offs;
- это другая len, не та что (i<len)... :)
← →
ANB © (2006-05-25 16:07) [23]Значится, вариант решения задачи.
Сами слова в словаре не храним - это хорошо, следовательно, описание слова имеет фиксированнуб длинну.
Имеем структуру :
RDicWord = record // Можно поиграть упаковкой
OffSet : Int64;
Length : DWord;
end;
Обявляем динамический массив :
DicWordList : array of RDicWord;
Узнаем размер файла (FileSeek). Делим длинну на размер записи SizeOf(RDicWord). Обрабатываем некруглую длинну (проще отбросить лишние байты в файле).
Устанавливаем длинну массива DicWordList. И за одну операцию чтения прямо в него загружаем содержимое файла.
Все имхо, мог чего и напутать. Критики - поправьте плиз.
← →
ANB © (2006-05-25 16:08) [24]Да, всеь словарь можно хранить и просто в длинной строке. Тогда точно будет работать. А ползать по словарю можно через указатели на RDicWord.
← →
pirate © (2006-05-26 15:22) [25]
> Имеем структуру :
> 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
Вот это действительно тема!
← →
tytus (2006-05-26 15:41) [26]han_malign[20] правильно пишет. Я сам давно ТОЛЬКО так работаю - файлы размером в 160 метров обрабатываются на раз. Для поиска нужного слова использую StrPos, которая возвращает указатель на найденное слово. Начало отображения описываю как PByte. Очень просто работать:INC, DEC. Если нужно скопировать строку (слово) - использую MOVE. Довольно хорошо эту тему описали Ксавье и Пачеко.
← →
pirate © (2006-05-29 15:37) [27]Хочу поблагодарить всех участников обсуждения: загрузка проходит за 0.11 сек. Спасибо!
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.07.09;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.012 c