Я разрабатываю приложение, предназначенное для настольных систем, которые могут иметь всего 256 МБ RAM (Windows 2000 и). В моем приложении у меня есть этот большой файл (> 256 МБ), который содержит фиксированные записи приблизительно 160 байтов/каждых. Это приложение имеет довольно долгий процесс, в котором, со временем, оно будет случайным образом получать доступ приблизительно к 90% файла (для чтения и записи). Любая данная рекордная запись не будет больше чем 1 000 рекордных доступов далеко от чтения той конкретной записи (я могу настроить это значение).
У меня есть две очевидных опции для этого процесса: регулярный ввод-вывод (FileRead, FileWrite) и размещение в ОЗУ (CreateFileMapping, MapViewOfFile). Последний должен быть намного более эффективным в системах с достаточной памятью, но в системах с низкой памятью она выгрузит большую часть памяти других приложений, которая в моем приложении является нет - нет. Существует ли способ помешать процессу съедать всю память (например, как принуждение сбрасывания страниц памяти, к которым я больше не получаю доступ)? Если это не возможно, то я должен обратиться назад к регулярному вводу-выводу; мне понравилось бы использовать перекрытый ввод-вывод для части записи (так как доступ является настолько произвольным), но в документации говорится, что записи меньше, чем 64K всегда подаются синхронно.
Любые идеи для улучшения ввода-вывода одобрены.
Наконец-то я нашел способ, полученный из нити здесь . Уловка заключается в использовании VirtualUnlock () для диапазонов, которые мне нужно разблокировать; хотя эта функция возвращает FALSE с ошибкой 0x9e («Сегмент уже разблокирован»), память фактически освобождается, даже если страницы были изменены (файл обновлен правильно).
Вот мой пример тестовой программы:
#include "stdafx.h"
void getenter(void)
{
int ch;
for(;;)
{
ch = getch();
if( ch == '\n' || ch == '\r' ) return;
}
}
int main(int argc, char* argv[])
{
char* fname = "c:\\temp\\MMFTest\\TestFile.rar"; // 54 MB
HANDLE hfile = CreateFile( fname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL );
if( hfile == INVALID_HANDLE_VALUE )
{
fprintf( stderr, "CreateFile() error 0x%08x\n", GetLastError() );
getenter();
return 1;
}
HANDLE map_handle = CreateFileMapping( hfile, NULL, PAGE_READWRITE | SEC_RESERVE, 0, 0, 0);
if( map_handle == NULL )
{
fprintf( stderr, "CreateFileMapping() error 0x%08x\n", GetLastError() );
getenter();
CloseHandle(hfile);
return 1;
}
char* map_ptr = (char*) MapViewOfFile( map_handle, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0 );
if( map_ptr == NULL )
{
fprintf( stderr, "MapViewOfFile() error 0x%08x\n", GetLastError() );
getenter();
CloseHandle(map_handle);
CloseHandle(hfile);
return 1;
}
// Memory usage here is 704KB
printf("Mapped.\n"); getenter();
for( int n = 0 ; n < 10000 ; n++ )
{
map_ptr[n*4096]++;
}
// Memory usage here is ~40MB
printf("Used.\n"); getenter();
if( !VirtualUnlock( map_ptr, 5000 * 4096 ) )
{
// Memory usage here is ~20MB
// 20MB already freed!
fprintf( stderr, "VirtualUnlock() error 0x%08x\n", GetLastError() );
getenter();
UnmapViewOfFile(map_ptr);
CloseHandle(map_handle);
CloseHandle(hfile);
return 1;
}
// Code never reached
printf("VirtualUnlock() executed.\n"); getenter();
UnmapViewOfFile(map_ptr);
CloseHandle(map_handle);
CloseHandle(hfile);
printf("Unmapped and closed.\n"); getenter();
return 0;
}
Как вы Как видите, рабочий набор программы сокращается после выполнения VirtualUnlock (), как и мне было нужно. Мне нужно только отслеживать страницы, которые я меняю, чтобы разблокировать при необходимости.
Просто сопоставьте весь файл с памятью. Это потребляет виртуальную, но не физическую память. Файл читается с диска по частям и удаляется из памяти теми же политиками, которые управляют файлом подкачки.
Отображаете ли вы весь файл как один блок с помощью MapViewOfFile? Если да, попробуйте нанести на карту более мелкие детали. Вы можете очистить представление с помощью FlushViewOfFile ()