Форум: "Начинающим";
Текущий архив: 2012.02.12;
Скачать: [xml.tar.bz2];
ВнизСамый быстрый способ считать маленький файл в строку Найти похожие ветки
← →
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 SCASBfunction 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;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.004 c