Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
6-1141079808
Кефир87
2006-02-28 01:36
2006.07.09
HTTP метод POST принцип отправки данных


15-1149783297
grisme
2006-06-08 20:14
2006.07.09
Преобразование указателя


1-1148908777
AFfonya
2006-05-29 17:19
2006.07.09
CMD.EXE выполение произвольной команды


15-1150172793
fun.exe
2006-06-13 08:26
2006.07.09
SQL в Delphi


2-1150729557
Gizza
2006-06-19 19:05
2006.07.09
Колическтво дней в месяце.





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