Проецируемые на память файлы
, быстродействие и т.д.
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [152.53.39.118] |
|
|
Правила раздела C/C++: Системное программирование и WinAPI
FAQ Сайта (C++)
FAQ Форума
Наши Исходники
Поиск по Разделу
MSDN Library Online (Windows Driver Kit)
Google| Страницы: (5) [1] 2 3 ... Последняя » все ( Перейти к последнему сообщению ) |
Проецируемые на память файлы
, быстродействие и т.д.
|
Сообщ.
#1
,
|
|
|
|
|
Сообщ.
#2
,
|
|
|
|
вот только ненужно называть проецируемые в память файлы - мапами, совершенно не понятно что ты имел ввиду, а под мапом в с++ подразумевается нечто другое. |
|
Сообщ.
#3
,
|
|
|
|
Цитата Snike @ мапом в с++ подразумевается нечто другое. ![]() А в RTS (Real-Time Strategy) под мапом понимается совсем другое. |
|
Сообщ.
#4
,
|
|
|
|
Цитата под "мапом" я подразумевал проецируемые в память файлыпод мапом в с++ подразумевается нечто другое. CreateFileMapping() и MapViewOf File(); память DDR 256Mb PC3200 Kingston + DDR 512Mb PC3200 Samsung винчестер -SamsungSP 0802N 80Gb , 7200 об/мин тест проводился следующим образом: *создается файл длиной 104857600 б (100 мб ) содержащий цифру , 0 например * запоминается системное время *файл обрабатывается тестируемой процедурой *берется текущее время и вычетается из запомненного *проверяется правильность нового содержимого файла код № 3: ![]() ![]() HANDLE hfile=CreateFile("sourcefile.bin",GENERIC_READ|GENERIC_WRITE,0, NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if(hfile==(HANDLE)-1) { MessageBox(NULL,"error in opening file","error",0); return; } HANDLE hmap=CreateFileMapping(hfile,NULL,PAGE_READWRITE, 0,0,NULL); if(hmap==NULL) { MessageBox("NULL,"error in map create","error",0); CloseHandle(hfile); return; } DWORD fsh; int filesize=GetFileSize(hfile,&fsh); filesize+=(((int)fsh)<<32); CloseHandle(hfile); int fileoffset=0; while(filesize>0) { DWORD block=65536; if(filesize<block) block=(DWORD)filesize; PBYTE pbfile=(PBYTE)MapViewOfFile(hmap,FILE_MAP_ALL_ACCESS, (DWORD)(fileoffset>>32),0,block); for(DWORD i=0;i<block;i++) pbfile[i]=pbfile[i]+5; //обработка UnmapViewOfFile(pbfile); filesize-=block; } CloseHandle(hmap); //дальше идет подсчет времени |
|
Сообщ.
#5
,
|
|
|
|
Цитата Snike @ Что именно в С++ понимается под "мапом"? Достаточно указать пункт стандарта. а под мапом в с++ подразумевается нечто другое. |
|
Сообщ.
#6
,
|
|
|
|
bobjones
Ты сам то понял, что с MapViewOfFile "натворил" Младший дворд dwFileOffsetLow = 0, старший тоже dwFileOffsetHigh == fileoffset == 0. В результате ты всегда читаешь и звписываешь одни и теже первые 64К. Осюда и "суперскорость", хотя реально скорость чтения с диска обычно не превышает 50 Мб/с и 100Мб должны читаться не менее или около 2 сек. Во-вторых, если размер файла заведомо меньше размера ОЗУ, то делать блочную обработку с Map\Unmap никакого смыла нет - лишь дополнительные тормоза (хоть и не столь значительные по сравнению с временем чтения\записи). Да и ждать чудес от MMF тоже не стоит - при последовательной обработке обычно он не дает выигрыша по сравнению с ReadFile\WriteFile блоками до 64К |
|
Сообщ.
#7
,
|
|
|
|
Цитата Младший дворд dwFileOffsetLow = 0, старший тоже dwFileOffsetHigh == fileoffset == 0. точно, ошибка здесь. надо вот так: PBYTE pbfile=(PBYTE)MapViewOfFile(hmap,FILE_MAP_ALL_ACCESS,0,(DWORD)(fileoffset&0xFFFFFFFF),block); fileoffset+=block; однако результаты теста не отменяются: 0.521 - 0.540 секунды. привожу полный код: ![]() ![]() #include <fstream.h> #include <dateutils.hpp> #include <iostream.h> #pragma hdrstop #pragma argsused createfile(int); bool checkfile(int ); //--------------------------------------------------------------------------- int main(int argc, char* argv[]) { int value=0; createfile(value); char * name="sourcefile.bin"; SYSTEMTIME tbegin,tend; GetSystemTime(&tbegin); HANDLE hfile=CreateFile(name,GENERIC_READ| GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if(hfile==(HANDLE)-1) { MessageBox(NULL,"error in opening file","",0); return 0; } HANDLE hmap=CreateFileMapping(hfile,NULL,PAGE_READWRITE, 0,0,NULL); if(hmap==NULL) { MessageBox(NULL,"error in map create","",0); CloseHandle(hfile); return 0; } DWORD fsh; int filesize=GetFileSize(hfile,&fsh); filesize+=(((int)fsh)<<32); CloseHandle(hfile); int fileoffset=0; while(filesize>0) { DWORD block=65536; if(filesize<block) block=(DWORD)filesize; PBYTE pbfile=(PBYTE)MapViewOfFile(hmap,FILE_MAP_ALL_ACCESS, 0,(DWORD)(fileoffset&0xFFFFFFFF),block); fileoffset+=block; for(DWORD i=0;i<block;i++) pbfile[i]=pbfile[i]+5; UnmapViewOfFile(pbfile); filesize-=block; } CloseHandle(hmap); GetSystemTime(&tend); cout << tend.wSecond - tbegin.wSecond << "\n" << tend.wMilliseconds-tbegin.wMilliseconds; if (checkfile(value+5)) cout << "\nYES!"; cin >> name; } //--------------------------------------------------------------------------- createfile(int n) { ofstream cf; cf.open("sourcefile.bin",ios::out | ios::binary); for(int i=0;i<104857600;i++) cf.put(n); cf.close(); } //----------------------------------------------------------------- bool checkfile(int n) { ifstream in; char *sym; in.open("sourcefile.bin",ios::in|ios::binary); int count=0; for(int i=0;i<104857600;i++) { in.get(*sym); if((int)*sym != n) { cout << "\nERROR IN FILE" << count; return 0; } count++; } in.close(); } |
|
Сообщ.
#8
,
|
|
|
|
Цитата Возьми реальный ненулевой файл и посмотри, что получится взял , посмотрел. все равно - 0.5 секунды теперь код вот такой: ![]() ![]() #include <fstream.h> #include <dateutils.hpp> #include <iostream.h> #pragma hdrstop //--------------------------------------------------------------------------- #pragma argsused createnewfile(); int main(int argc, char* argv[]) { createnewfile(); char * name="sourcefile.bin"; SYSTEM_INFO *sinf=new SYSTEM_INFO; SYSTEMTIME tbegin,tend; GetSystemTime(&tbegin); HANDLE hfile=CreateFile(name,GENERIC_READ| GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if(hfile==(HANDLE)-1) { MessageBox(NULL,"error in opening file","",0); return 0; } HANDLE hmap=CreateFileMapping(hfile,NULL,PAGE_READWRITE, 0,0,NULL); if(hmap==NULL) { MessageBox(NULL,"error in map create","",0); CloseHandle(hfile); return 0; } DWORD fsh; __int64 filesize=GetFileSize(hfile,&fsh); filesize+=(((int)fsh)<<32); CloseHandle(hfile); __int64 fileoffset=0; while(filesize>0) { DWORD block=sinf->dwAllocationGranularity; if(filesize<block) block=(DWORD)filesize; PBYTE pbfile=(PBYTE)MapViewOfFile(hmap,FILE_MAP_ALL_ACCESS, (DWORD)(fileoffset>>32),(DWORD)(fileoffset&0xFFFFFFFF),block); if(pbfile==NULL) { MessageBox(NULL,"Error in view","error",0); return 0; } fileoffset+=block; for(DWORD i=0;i<block;i++) pbfile[i]=pbfile[i]+5; UnmapViewOfFile(pbfile); filesize-=block; } delete sinf; CloseHandle(hmap); GetSystemTime(&tend); cout << tend.wSecond - tbegin.wSecond << "\n" << tend.wMilliseconds-tbegin.wMilliseconds << "\n\nEnd of test"; cin >> name; } //--------------------------------------------------------------------------- createnewfile() { cout << "creating test file...\n"; ofstream cf; cf.open("sourcefile.bin",ios::out | ios::binary); for(int i=0;i<104857600;i++) cf.put(random(256)); // теперь в файл пишутся [псевдо]случайные числа cf.close(); cout << "done.\n\n"; } Добавлено я намеренно опустил проверку файла после преобразования чтобы не загромождать код |
|
Сообщ.
#9
,
|
|
|
|
Представление о преимуществах MMF по скорости это очень распространенный миф, основанный на голословных отрывочных фразах из официальных док MS и на некорректных сравнениях некоторых горе-популяризаторов. Последовательное чтение данных с диска путем MMF в принципе не может быть быстрее правильно организованного блочного чтения через ReadFile, а на деле часто оказывается чуть медленее, т.к. весь MMF основан на исключениях отказа страниц, обработка которых занимает заметное время.
С записью\копированием дело обстоит несколько сложнее, т.к. сюда замешиваются доп.факторы - особенности работы HDD и хитрости ОС. Во-первых, при MMF данные после UnmapView не сразу записываются на диск и могут находиться в ОЗУ неопределенно долго. Считать ли это преимуществом MMF - вопрос спорный, т.к. накопленные страницы могут начать выгружаться на диск в любой неподходящий момент. Например, если прога после копирования переходит в режим ожидания или занимается длительными вычислениями, то это м.б. незаметно, а вот если нужно обработать еще десяток таких же файлов (или размер одного копируемого файла превышает размер ОЗУ), то тут отложенная запись может проявить себя во всей красе. Если же сравнивать по честному и перед UnmapView вызывать FlushView, то время копирования будет примерно таким же как и при обычном Read\Write c тем же размером буфера. Во-вторых, размер буфера при копировании должен быть больше, чем при простом чтении. Но устремлять размер в "бесконечность" смысла нет, т.к. тут есть разумный предел. При чередовании чтения и записи HDD вынужден каждый раз позиционировать головки, на что уходит не менее 60(с)/7200(об/мин) = 8 мс. Поэтому при размере блока 64К у нас только на одно позиционирование в данном случае уходит (100М/64К)*8мс ~ 13 сек. Вычтем 13 из 18-19 сек и получим разумные 5-6 сек = 2*(2.5-3). Но чтобы снизить потери скажем до 5-10%, достаточно при макс.скорости чтения ~50 Мб/с увеличить размер буфера до (10-20)*8(мс)*50(Мб/с) =4-8 Мб (ну можно с запасом до 10-20 Мб - дальше просто смысла нет). Однако при увеличении размера буфера может проявиться еще одна "хитрость" - скорость обычного буферированного чтения может несколько снизиться из-за возрастания числа промахов быстрого чтения из файлового кэша. Например, в WinXP максимальная скорость чтения получается при размере буфера до 64К, а затем резко увеличивается число кэш-промахов и скорость чтения несколько падает (вообще-то это выглядит довольно глуповато - пытаться лезть в кэш, когда размер считываемых данных превышает размер упреждающего чтения). Но если использовать FILE_FLAG_NO_BUFFERING, то ничего подобного не происходит и скорость копирования оказывается всегда выше чем у MMF c FlushView. Ну а если без Flush, то конечно MMF за счет отложенной записи может формально показывать вдвое лучшие результаты. |
|
Сообщ.
#10
,
|
|
|
|
все же у filemapping должны быть плюсы - например достаточно простой неоднократный доступ к файлу.
допустим, алгоритм, проходящий файл несколько раз. отобразили на память , поработали, записали на диск. по-любому быстрей чем каждый раз читать/ писать на винт. |
|
Сообщ.
#11
,
|
|
|
|
Цитата bobjones @ все же у filemapping должны быть плюсы - например достаточно простой неоднократный доступ к файлу. допустим, алгоритм, проходящий файл несколько раз. отобразили на память , поработали, записали на диск. по-любому быстрей чем каждый раз читать/ писать на винт. Но для просто копирования, обычный метод чуууточку шустрее. |
|
Сообщ.
#12
,
|
|
|
|
Цитата bobjones @ допустим, алгоритм, проходящий файл несколько раз. отобразили на память , поработали, записали на диск. по-любому быстрей чем каждый раз читать/ писать на винт. Зато есть один здоровенный минус: файл > 4Gb на 32-битной архитектуре не обработать. |
|
Сообщ.
#13
,
|
|
|
|
Цитата linuxfan @ Зато есть один здоровенный минус: файл > 4Gb на 32-битной архитектуре не обработать. Глупость |
|
Сообщ.
#14
,
|
|
|
|
До тех пор, пока не напорешься так и будешь думать, что глупость.
На самом деле, при использовании mmap'а теряется еще одна возможность: потоковая обработка. |
|
Сообщ.
#15
,
|
|
|
|
32 разрядность архитектуры тут не причем...
Цитата linuxfan @ До тех пор, пока не напорешься так и будешь думать, что глупость. Изв. но почему-то не напоролся |