Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.07.09;
Скачать: CL | DM;

Вниз

Быстрый доступ к файлу   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.047 c
15-1149949840
tesseract
2006-06-10 18:30
2006.07.09
процессорные байки.


2-1150993556
Duk_
2006-06-22 20:25
2006.07.09
Цвета


1-1147960648
MegaVolt
2006-05-18 17:57
2006.07.09
При разворачивании формы на весь экран ищезает прогрессбар из...


2-1151060877
Alex_1qaz_2006
2006-06-23 15:07
2006.07.09
Как получить код завершения внешнего приложения


1-1148748141
Ярослав
2006-05-27 20:42
2006.07.09
Вызов MDI из DLL