CreateFileMapping, MapViewOfFile, как постараться не держать системную память

Я разрабатываю приложение, предназначенное для настольных систем, которые могут иметь всего 256 МБ RAM (Windows 2000 и). В моем приложении у меня есть этот большой файл (> 256 МБ), который содержит фиксированные записи приблизительно 160 байтов/каждых. Это приложение имеет довольно долгий процесс, в котором, со временем, оно будет случайным образом получать доступ приблизительно к 90% файла (для чтения и записи). Любая данная рекордная запись не будет больше чем 1 000 рекордных доступов далеко от чтения той конкретной записи (я могу настроить это значение).

У меня есть две очевидных опции для этого процесса: регулярный ввод-вывод (FileRead, FileWrite) и размещение в ОЗУ (CreateFileMapping, MapViewOfFile). Последний должен быть намного более эффективным в системах с достаточной памятью, но в системах с низкой памятью она выгрузит большую часть памяти других приложений, которая в моем приложении является нет - нет. Существует ли способ помешать процессу съедать всю память (например, как принуждение сбрасывания страниц памяти, к которым я больше не получаю доступ)? Если это не возможно, то я должен обратиться назад к регулярному вводу-выводу; мне понравилось бы использовать перекрытый ввод-вывод для части записи (так как доступ является настолько произвольным), но в документации говорится, что записи меньше, чем 64K всегда подаются синхронно.

Любые идеи для улучшения ввода-вывода одобрены.

12
задан Guillermo Prandi 10 December 2009 в 12:36
поделиться

3 ответа

Наконец-то я нашел способ, полученный из нити здесь . Уловка заключается в использовании 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 (), как и мне было нужно. Мне нужно только отслеживать страницы, которые я меняю, чтобы разблокировать при необходимости.

13
ответ дан 2 December 2019 в 18:54
поделиться

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

3
ответ дан 2 December 2019 в 18:54
поделиться

Отображаете ли вы весь файл как один блок с помощью MapViewOfFile? Если да, попробуйте нанести на карту более мелкие детали. Вы можете очистить представление с помощью FlushViewOfFile ()

1
ответ дан 2 December 2019 в 18:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: