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

Вниз

Самый быстрый способ считать маленький файл в строку   Найти похожие ветки 

 
Nucer   (2011-10-13 15:59) [0]

Подскажите самый быстрый способ считать файл в RawByteString. Необходимо обрабатывать около 50 тысяч файлов размеров в 100-200 килобайт.

При таком варианте только на чтение без обработки уходит минут 5:
var
 S: RawByteString;
 F: File;
 Size: Int64;
begin
 AssignFile(F, Filename);
 Reset(F, 1);
 Size := FileSize(F);
 Reset(F, Size);
 SetLength(S, Size);
 BlockRead(F, S[1], 1);
 CloseFile(F);
end;


 
Плохиш ©   (2011-10-13 16:02) [1]

TFileStream


 
Омлет ©   (2011-10-13 16:07) [2]

> Плохиш ©   (13.10.11 16:02) [1]
> TFileStream


Ага, как будто он вызывает какую-то другую функцию для чтения файла (ReadFile).


 
Омлет ©   (2011-10-13 16:11) [3]

> Nucer   (13.10.11 15:59)

Ты выделяешь память под каждый файл, а потом освобождаешь. А можно выделить один раз большой буфер и с ним работать. И не завязывайся на строки (что такое RawByteString?), работай напрямую с памятью через указатели.


 
Омлет ©   (2011-10-13 16:15) [4]

И не надо вызывать FileSize, почитай справку по BlockRead.


 
Nucer   (2011-10-13 16:19) [5]

Выделение памяти на фоне чтения файла выполняется мгновенно. Если убрать строку и читать из файла только один байт, то времени на чтение всех файлов уходит примерно столько же (по байту с каждого).
С TFileStream быстрее не стало. На один файл уходит около 30 ms. 50 тысяч файлов - около 25 минут. Ужасно долго. Программно никак не ускорить процесс?


 
stas ©   (2011-10-13 16:25) [6]

Nucer   (13.10.11 16:19) [5]
А если отключить антивирус?


 
Ega23 ©   (2011-10-13 16:27) [7]


> 50 тысяч файлов - около 25 минут.


А щито вы хотели? Дисковая операция.


> Программно никак не ускорить процесс?


Ну если более одного ядра, то можно попробовать распараллелить потоки.


 
Nucer   (2011-10-13 16:28) [8]

> А если отключить антивирус?
Отключил первым делом :)


 
Омлет ©   (2011-10-13 16:30) [9]

Какая файловая система? Какой носитель?


 
Ega23 ©   (2011-10-13 16:30) [10]

Потом что-то ещё такое было про количество файлов в директории. Мол, после какого-то количества (1000, например) сканирование начинает ощутимо подтормаживать.
Впрочем, с этим к Розычу.


 
Nucer   (2011-10-13 16:32) [11]

> Какая файловая система? Какой носитель?
NTFS, HDD (SATA 5400)

> Ega23 ©   (13.10.11 16:30) [10]
Попробую раскидать по папкам, вдруг поможет.


 
Омлет ©   (2011-10-13 16:33) [12]

Сильно ли разбросаны файлы по диску?


 
Ega23 ©   (2011-10-13 16:35) [13]

Ещё один вариант: не делать 50.000 маленьких файлов, а сделать один большой из 50.000 частей.


 
sniknik ©   (2011-10-13 16:37) [14]

> около 50 тысяч файлов размеров в 100-200 килобайт.
а сколько времени занимает например копирование их системой? запись конечно дольше но порядок цифр будет показателен...
один большой файл копируется быстрее чем много много мелких. даже при том что размер большого в много раз больше суммы мелких.


 
Anatoly Podgoretsky ©   (2011-10-13 16:39) [15]

> Nucer  (13.10.2011 16:19:05)  [5]

30 миллисекунд это скорость равна 30-60 мб/сек
Вроде бы это нормально для диска.


 
Dennis I. Komarov ©   (2011-10-13 17:51) [16]

50000 файлов вдруг оказываются? Может поменять логику и обрабатывать их по мере появления (ReadDirectoryChangesW), или вообще исключить файловый обмен в пользу TCP?


 
RWolf ©   (2011-10-13 17:53) [17]

вариант: не подгружать файл в буфер вообще.
вместо этого получать отображение файла на память (CreateFileMapping и т. д.).


 
Inovet ©   (2011-10-13 18:02) [18]

> [10] Ega23 ©   (13.10.11 16:30)
> Мол, после какого-то количества (1000, например) сканирование
> начинает ощутимо подтормаживать.

Это на ФАТ, там поиск не индексированный.


 
Inovet ©   (2011-10-13 18:03) [19]

> [5] Nucer   (13.10.11 16:19)
> На один файл уходит около 30 ms. 50 тысяч файлов - около 25 минут. Ужасно долго.

Зажрались однако.


 
Игорь Шевченко ©   (2011-10-13 20:11) [20]

Смотря зачем читать


 
Slym ©   (2011-10-14 07:24) [21]

4,3 секунды 50тыс открытие и "чтение" 1 файла в 356мб
procedure TForm1.Button2Click(Sender: TObject);
const FileName="D:\_films\Bones.s03e01.HDTVRip.NovaFilm.TV.avi";//356мб
var
 t:dword;
 i:integer;
 hFile,hMap:THandle;
 hMem:pointer;
begin
 t:=GetTickCount;
 for i:=0 to 50000 do
 begin
   hFile:=CreateFile(PChar(FileName),GENERIC_READ,FILE_SHARE_READ,nil, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, 0);
   hMap:=CreateFileMapping(hFile,nil,PAGE_READONLY,0,0,nil);
   hMem:=MapViewOfFile(hMap,FILE_MAP_READ,0,0,0);
   UnmapViewOfFile(hMem);
   CloseHandle(hMap);
   CloseHandle(hFile);
 end;
 t:=GetTickCount-t;
 Caption:=InttoStr(t);
end;


 
MBo ©   (2011-10-14 08:53) [22]

Просто вход в папку с 20тыс мелких файлов FAR или проводником (в режиме без иконок) в первый раз занимает около минуты, во второй раз несколько секунд, но тоже не мгновенно.


 
han_malign   (2011-10-14 09:06) [23]


> открытие и "чтение" 1 файла в 356мб

- не правильный тест:
1. чтения, собственно, не происходит... - надо обратиться к странице памяти, чтобы она подгрузилась(Page Fault)...
2. файл в кэше(даже после закрытия(как минимум метаданные))...

- но направление мысли правильное...
1. сбоев страниц памяти не меньше чем в случае если каждый раз буфер создавать(зависит от менеджера памяти), зато нет дополнительного заполнения нулями(см. VirtualAlloc)...
2. (IMHO) поток не переходит в альтернативное состояние(на ReadFile) и соответственно есть шанс не потерять лишний квант(из тех 2-х, которые 30мс)...

З.Ы. еще можно попробовать FILE_FLAG_SEQUENTIAL_SCAN(без File Mapping), но по этому поводу у меня некоторые сомнения(поможет ли чем-то удвоенный буфер предвыборки если читаешь все?)...


 
han_malign   (2011-10-14 09:15) [24]


> Просто вход в папку с 20тыс мелких файлов FAR или проводником (в режиме без иконок) в первый раз занимает около минуты

- добавление 20тыс элементов в TListView(не виртуальный) занимает минут пять(без побочной работы)...
Это надо "чистый" тест делать, и отдельный поток на заполнение списка тоже никто не запрещал(если порядок обработки не имеет значения).


 
MBo ©   (2011-10-14 09:26) [25]

>обавление 20тыс элементов в TListView
В Far примерно то же самое.
И  я сталкивался с тем, что FindFirst/Next безо всяких гуёв по подобным папкам выполняется в первый раз ощутимое время


 
han_malign   (2011-10-14 10:05) [26]


> И  я сталкивался с тем, что FindFirst/Next безо всяких гуёв по подобным папкам выполняется в первый раз ощутимое время

- проверка прав - скорее всего...
Можно попробовать поиграться с владельцем, наследованием и т.д., но правильнее всего разбивать такую лапшу на дерево подпапок(при грамотном именовании можно делать(загрубленно) и фильтрацию, и сортировку)...

З.Ы. Сам не проверял, но некоторые клиенты утверждают, что после 64К наступает полная опа...


 
QAZ   (2011-10-14 10:47) [27]


> Nucer   (13.10.11 16:19) [5]

ктож блин, читает файлы по байту?
минимальная единица чтения должна быть равна размеру кластера
а при твоих размерах нужно читать весь файл зараз


 
han_malign   (2011-10-14 11:03) [28]


> ктож блин, читает файлы по байту?

- кури мануал...
procedure Reset(var F: file; RecSize: Integer);


 
QAZ   (2011-10-14 11:27) [29]


> han_malign   (14.10.11 11:03) [28]

данунафиг я такими файлофункциями в жизни не пользовался и не собираюсь


 
Slym ©   (2011-10-14 11:28) [30]

первый запуск 29700:10215 т.е. 30 сек по всему диску d:\ по маске pas+dcu найдено 10215 файлов
второй запуск 9900:10215
чтение побайтовое :) REPNE   SCASB

function LCharPos(Str:PChar;char:char;Size:integer): Integer;
asm  {Str - EAX, char - DL (EDX), Size - ECX}
       PUSH    EDI
       MOV     EDI, EAX { Point EDI to str}

       MOV     AL,DL        { AL = Search char}
       MOV     EDX,ECX   {remember Length}

       REPNE   SCASB
       JNE     @@fail
       MOV     EAX,EDX { Calc offset }
       SUB     EAX,ECX
       JMP     @@fin
@@fail:
       XOR     EAX,EAX
@@fin:
       POP     EDI
end;

procedure FastOpenFile(const FileName:string);
var
 i:integer;
 hFile,hMap:THandle;
 hMem:pointer;
begin
 try
 hFile:=CreateFile(PChar(FileName),GENERIC_READ,FILE_SHARE_READ,nil, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, 0);
 if hFile=INVALID_HANDLE_VALUE then RaiseLastOSError;
 hMap:=CreateFileMapping(hFile,nil,PAGE_READONLY,0,0,nil);
 if hMap=0 then RaiseLastOSError;
 hMem:=MapViewOfFile(hMap,FILE_MAP_READ,0,0,0);
 if hMem=nil then RaiseLastOSError;
 LCharPos(hMem,#1,GetFileSize(hFile,nil));
 UnmapViewOfFile(hMem);
 CloseHandle(hMap);
 CloseHandle(hFile);
 except
 end;
end;

procedure TForm1.EnumFolder(dir:string);
var
 f:WIN32_FIND_DATA;
 hf: HFile;
 flag: boolean;
begin
 dir:=IncludeTrailingPathDelimiter(dir);
 hf:=FindFirstFile(PChar(dir+"*.*"),f);
 while FindNextFile(hf,f) do
 begin
   if (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)>0 then
   begin
     if (StrComp(f.cFileName,".")<>0) and (StrComp(f.cFileName,"..")<>0) then
       EnumFolder(dir+f.cFileName);
   end else
   begin
     if (pos(".pas",f.cFileName)>0) or (pos(".dcu",f.cFileName)>0) then
     begin
       inc(fc);
       FastOpenFile(dir+f.cFileName);
     end;
   end;
 end;
 windows.FindClose(hf);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 t:dword;
begin
 fc:=0;
 t:=GetTickCount;
 EnumFolder("d:\");
 t:=GetTickCount-t;
 Caption:=InttoStr(t)+":"+InttoStr(fc);
end;


 
Inovet ©   (2011-10-14 12:01) [31]

> [22] MBo ©   (14.10.11 08:53)
> Просто вход в папку с 20тыс мелких файлов FAR или проводником
> (в режиме без иконок) в первый раз занимает около минуты,
> во второй раз несколько секунд, но тоже не мгновенно.

Так он их имена и пр. грузит в свои структуры, а для открытия файла достаточно найти один в каталоге. На NTFS это быстро - каталог двоичное дерево, на FAT долго - каталог линейный.


 
Игорь Шевченко ©   (2011-10-14 20:11) [32]

цель чтения файлов не озвучена.


 
Rouse_ ©   (2011-10-14 20:28) [33]


> REPNE   SCASB

ужс, кто "такому ассемблеру" учит? Это из старых дельфийских библиотек или самописка?


 
Игорь Шевченко ©   (2011-10-14 20:41) [34]

Rouse_ ©   (14.10.11 20:28) [33]

Нормальный ассемблер


 
Rouse_ ©   (2011-10-14 20:50) [35]


> Rouse_ ©   (14.10.11 20:28) [33]
> Нормальный ассемблер

Интеловские мануалы в плане профилирования кода с тобой не согласны, особливо в части рекомендаций по использованию исключающих префиксов опкодов первой группы (из четырех):

 pfxRepn = $F2;
 pfxRep = $F3;


куда идут инструкции типа REPNE/REPNZ и т.д. тратящие пять тиков минимум  на итерации, так и инструкции LOOP например...
Впрочем ты и сам это должен помнить...


 
Игорь Шевченко ©   (2011-10-14 20:56) [36]

Во-первых, на цитату из мануала нефигово приводить ссылку.
Во-вторых, открываем внутренности VCL и видим примеры нормального ассемблера.
В-третьих, помним первый принцип оптимизации - по возможности ее избегать.


 
Rouse_ ©   (2011-10-14 20:57) [37]

ЗЫ: кусок из реализации дизасма, где описаны все 4 группы префиксов (если я не прав - поправь, скажу спасибо):

const
 // Lock and repeat prefixes:
 pfxLock = $F0;
 // The LOCK prefix can be prepended only to the following instructions and only to those forms
 // of the instructions where the destination operand is a memory operand: ADD, ADC, AND,
 // BTC, BTR, BTS, CMPXCHG, CMPXCH8B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR,
 // XADD, and XCHG

 pfxRepn = $F2;
 pfxRep = $F3;

 // Segment override prefixes:
 pfxCSSegmentOverride = $2E;
 pfxSSSegmentOverride = $36;
 pfxDSSegmentOverride = $3E;
 pfxESSegmentOverride = $26;
 pfxFSSegmentOverride = $64;
 pfxGSSegmentOverride = $65;

 // Operand-size override prefix
 // (when used with the escape opcode 0FH, this
 // is treated as a mandatory prefix for some SIMD instructions)
 pfxOperandSizeOverride = $66;
 pfxEscapeOpcode = $0F;

 // Address-size override prefix
 pfxAddressSizeOverride = $67;


 
Anatoly Podgoretsky ©   (2011-10-14 21:06) [38]


> ужс, кто "такому ассемблеру" учит?

Это пример не профессионализма. Тупо сделаный код. Не читая ни умных книг, не руководство по оптимизации от Интела, не вглядываясь в генофонд.


 
Rouse_ ©   (2011-10-14 21:09) [39]


> Игорь Шевченко ©   (14.10.11 20:56) [36]
> Во-первых, на цитату из мануала нефигово приводить ссылку.

Ну блин: http://developer.intel.com/design/pentiumii/manuals/245127.htm
Ну и до кучи: http://agner.org/optimize/


 
Rouse_ ©   (2011-10-14 21:11) [40]


> Anatoly Podgoretsky ©   (14.10.11 21:06) [38]
> Это пример не профессионализма. Тупо сделаный код.

Собственно именно эту мысль я и попытался озвучить в первом посте :)



Страницы: 1 2 вся ветка

Текущий архив: 2012.02.12;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.011 c
15-1319401805
Юрий
2011-10-24 00:30
2012.02.12
С днем рождения ! 24 октября 2011 понедельник


15-1319444691
Фокс Йожин
2011-10-24 12:24
2012.02.12
Странные тормоза при загрузке Windows XP


15-1319661005
Юрий
2011-10-27 00:30
2012.02.12
С днем рождения ! 27 октября 2011 четверг


15-1319498590
Kerk
2011-10-25 03:23
2012.02.12
Умер John McCarthy


2-1320687478
flur
2011-11-07 20:37
2012.02.12
база paradox вставить новую запись