Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

SetFilePointer, WriteFile -- курим долго

16K
24 апреля 2006 года
Баювар
10 / / 16.04.2006
Привет!

Имееем файл на гигабайт и больше. Открываем так (надо такие атрибуты!)
hFile= ::CreateFile( sName ,
GENERIC_WRITE,
0 ,
NULL,
OPEN_EXISTING ,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING ,
NULL
);

Ставим пойнтер в разумную середину
#define TEST_WR_SIZE 839680
LARGE_INTEGER fsize;
GetFileSizeEx(hFile,&fsize);
__int64 llCurrPos = fsize.QuadPart/2;
llCurrPos-=llCurrPos%TEST_WR_SIZE;
fsize.QuadPart=llCurrPos;

b = ::SetFilePointerEx( hFile ,fsize,NULL , FILE_BEGIN );

Пока все нормально.

b=::WriteFile( hFile , pb ,TEST_WR_SIZE, &dwWr , NULL );

М курим, курим...

Покурили? Теперь все будет навсегда нормально до перезагрузки компа, включая обращения к другим файлам таким же образом. Курение отменяется, если файл свежесозданный.

Как избежать? Хотя бы не разобраться -- что дернуть, чтобы курить поменьше?
17K
24 апреля 2006 года
blurred
7 / / 17.04.2006
Может быть, буфер pb не выравнен по границе сектора - в MSDN написано, что при работе с FILE_FLAG_NO_BUFFERING буфер в памяти тоже должен выравниваться. Если так, попробуй использовать VirtualAlloc для выделения памяти под pb
9.5K
24 апреля 2006 года
Damarus
101 / / 08.04.2006
Цитата:
Originally posted by blurred
Может быть, буфер pb не выравнен по границе сектора - в MSDN написано, что при работе с FILE_FLAG_NO_BUFFERING буфер в памяти тоже должен выравниваться. Если так, попробуй использовать VirtualAlloc для выделения памяти под pb



Это всё фигня. С файлами такого размера надо использовать File mapping.

16K
24 апреля 2006 года
Баювар
10 / / 16.04.2006
Цитата:
Originally posted by Damarus
Это всё фигня. С файлами такого размера надо использовать File mapping.



Спасибо, похоже что так.

Тогда уточню свою задачу. Два процесса работают с одним файлом, обычно два компа по сети. Один создает блоки (вроде 839680, там что-то выравнивали) и пишет в файл, другой соответственно их с другой позиции того файла читает. Эдакие догонялки. Сейчас сделано через SetFilePointerEx, причем почему-то без LockFile.

Улучшу ли я производительность с помощью File mapping? Нужно ли сразу оба процесса на это дело переводить, или можно начать с пишущего, более критичного?

9.5K
26 апреля 2006 года
Damarus
101 / / 08.04.2006
Я думаю производительность улучшится. Но подожди переделывать. Я тут MSDN почитал, и вот что вычитал (приношу свои извинения blurred'у - возможно он был прав):
 
Код:
hFile = ::CreateFile(sName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL);


MSDN:
Цитата:

FILE_ATTRIBUTE_NORMAL:
[QUOTE]
A file does not have other attributes set. [color=red]This attribute is valid only if used alone.[/color]


FILE_FLAG_NO_BUFFERING:

Цитата:

The system opens a file with no system caching. This flag does not affect hard disk caching. When combined with FILE_FLAG_OVERLAPPED, the flag gives maximum asynchronous performance, because the I/O does not rely on the synchronous operations of the memory manager. However, some I/O operations take more time, because data is not being held in the cache. Also, the file metadata may still be cached. To flush the metadata to disk, use the FlushFileBuffers function.
An application must meet certain requirements when working with files that are opened with FILE_FLAG_NO_BUFFERING:
[color=red]
File access must begin at byte offsets within a file that are integer multiples of the volume sector size.

File access must be for numbers of bytes that are integer multiples of the volume sector size. For example, if the sector size is 512 bytes, an application can request reads and writes of 512, 1024, or 2048 bytes, but not of 335, 981, or 7171 bytes.

Buffer addresses for read and write operations should be sector aligned, which means aligned on addresses in memory that are integer multiples of the volume sector size. Depending on the disk, this requirement may not be enforced.
One way to align buffers on integer multiples of the volume sector size is to use VirtualAlloc to allocate the buffers. It allocates memory that is aligned on addresses that are integer multiples of the operating system's memory page size. Because both memory page and volume sector sizes are powers of 2, this memory is also aligned on addresses that are integer multiples of a volume sector size.[/color]

An application can determine a volume sector size by calling the GetDiskFreeSpace function.


[/QUOTE]

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог