Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Системный кэш 
:(
    Опции темы
Lazin
Дата 1.11.2008, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 8
Всего: 154



В общем возникла такая проблема. Некоторое приложение записывает в файл, асинхронно, N Gb данных, после этого диспетчер задач windows показывает, что размер системного кэша ровно N Gb и он не освобождается. Что не так?
PM MAIL Skype GTalk   Вверх
GremlinProg
Дата 1.11.2008, 21:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



показывай как пишешь в файл (я так полагаю, речь не о системном кэше, а о своп-файле [файле подкачки])


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Lazin
Дата 1.11.2008, 22:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 8
Всего: 154



нет, именно о системном кэше, не о своп файле
PM MAIL Skype GTalk   Вверх
GremlinProg
Дата 1.11.2008, 23:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



ну, тогда пробуй выключить буферизацию: FILE_FLAG_NO_BUFFERING
Цитата(MSDN)

Instructs the system to open the file with no system caching

но писать/читать при этом  можно будет только по кратным адресам, кратным размеру сектора (обычно 512 байт) проще всего взять размер страницы, т.к. он точно ему кратен

если есть желание, можешь так же использовать физическую память, если важна скорость: AllocateUserPhysicalPages, MapUserPhysicalPages, FreeUserPhysicalPages

Добавлено через 3 минуты и 49 секунд
Цитата(GremlinProg @  2.11.2008,  01:16 Найти цитируемый пост)
по кратным адресам

в смысле и адрес и размер блока, передаваемые в Red/WriteFile должны быть кратны размеру сектора (если это условие не выполняется, функции вернут ошибку)

актуально только если файл открыт с флагом FILE_FLAG_NO_BUFFERING


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Lazin
Дата 1.11.2008, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 8
Всего: 154



Я думал пробовал, но мне нужно писать данные именно асинхронно... то есть с флагом FILE_FLAG_OVERLAPPED
PM MAIL Skype GTalk   Вверх
GremlinProg
Дата 2.11.2008, 00:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Lazin @  2.11.2008,  01:52 Найти цитируемый пост)
с флагом FILE_FLAG_OVERLAPPED

и в чем проблема? эти флаги не противоречат друг другу


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 2.11.2008, 00:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



вот простое чтение без буфера с задержкой
Код

    OVERLAPPED ovl;
    LPBYTE lpalmem,lpmem;
    HANDLE hFile;
    //
    hFile    = ::CreateFile(
        _T("C:\\test.avi"),
        GENERIC_READ | GENERIC_WRITE,0,NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED,0
    );
    //    подготовка события и смещения в файле
    ::memset(&ovl,0,sizeof(ovl));
    ovl.hEvent    = ::CreateEvent(NULL,TRUE,FALSE,NULL);
    ovl.Offset    = 512;
    //    подготовка буфера
    lpmem        = (LPBYTE)malloc(4096 * 5);
    lpalmem        = LPBYTE(DWORD_PTR(lpmem) + 512 - (DWORD_PTR(lpmem) % 512));
    //    зануление буфера(просто для проверки)
    ::memset(lpalmem,0,512);
    //    чтение
    if(!::ReadFile(hFile,lpalmem,512,NULL,&ovl) && (::GetLastError() != ERROR_IO_PENDING)){
        ::MessageBox(0,_T("ReadFile"),0,0);
        ::CloseHandle(ovl.hEvent);
        ::CloseHandle(hFile);
        free(lpmem);
        return false;
    }
    //    ожидание
    ::WaitForSingleObject(ovl.hEvent,INFINITE);
    //    проверка
    for(int i = 512;(i--) && (!lpalmem[i]););
    if(i + 1){
        ::MessageBox(0,_T("не нули"),0,0);
        ::CloseHandle(ovl.hEvent);
        ::CloseHandle(hFile);
        free(lpmem);
        return false;
    }
    //    освобождение данных
    ::CloseHandle(ovl.hEvent);
    ::CloseHandle(hFile);
    free(lpmem);
    return true;

файл читается со смещения 512 байт, и размер блока 512 байт (т.е. в файле должно быть по крайней мере килобайт данных)

Добавлено через 2 минуты и 19 секунд
с записью точно так же


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
J0ker
Дата 3.11.2008, 05:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: -1
Всего: 14



я так думаю надо flush сделать
или commit


--------------------
user posted image
PM MAIL   Вверх
Lazin
Дата 3.11.2008, 10:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 8
Всего: 154



Цитата(J0ker @  3.11.2008,  05:01 Найти цитируемый пост)
я так думаю надо flush сделать
или commit 

flush делается 
в общем после выходных попробую))
PM MAIL Skype GTalk   Вверх
Lycifer
Дата 10.11.2008, 18:54 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 144
Регистрация: 4.11.2007

Репутация: нет
Всего: нет



Думаю поможет flush.
А вообще я не знаю как это в винде устроинно, а вот в Linux это не совсем запись в файл, ядро сохраняет некоторые данные в оперативе а потом когда небудь сохраняет на диск, это связано с производительностью, так как файл могут заново открыть, для синхронизации делается системные вызов sync() - да кажется так.)))
PM MAIL ICQ   Вверх
Lazin
Дата 27.11.2008, 17:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 8
Всего: 154



В общем, проблема никуда не делась. Запись в файл без буферизации я сделать не могу, так-как в один файл у меня пишут несколько экземпляров одной программы, синхронизируя доступ к нему. В случае эксклюзивного доступа к файлу это решает проблему, но я не могу придумать алгоритм записи в файл нескольких приложений для случая, когда за один write можно записать 512*n байт, притом, что каждая программа записывает данные блоками по N байт, причем N - переменная величина. 
Файл я открываю так:

Код

                        CreateFile (    filename,
                                        GENERIC_WRITE,
                                        FILE_SHARE_WRITE|FILE_SHARE_READ,
                                        NULL,
                                        OPEN_ALWAYS,
                    FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED,
                                        NULL)

причем, если FILE_SHARE_READ убрать, то проблема исчезает, но в этом случае нельзя читать данные во время записи, что то-же важно.
PM MAIL Skype GTalk   Вверх
GremlinProg
Дата 27.11.2008, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Lazin @  27.11.2008,  19:05 Найти цитируемый пост)
за один write можно записать 512*n байт, притом, что каждая программа записывает данные блоками по N байт, причем N - переменная величина. 

На сколько N - переменная величина? Значение этой величины может различаться между разными экземплярами программы?
Если да, то нет смысла писать все это в один файл, проще выделить для каждого процесса свой файл,
либо разделить однородные данные в разных файлах, т.е. зафиксировать за каждым файлом свое N. Тогда можно использовать следующий расчет:
Код

int buffers = 1;
while( (buffers * 512) % N){
  ++buffers;
}

по завершению итераций blocks будет содержать число буферов по 512 байт, которыми можно оперировать при чтении и записи автономно из разных процессов, т.е. blocks * 512 - это минимальный размер буфера, который можно считать/записать в файл не опасаясь перекрыть соседние блоки данных (на границах буферов).


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Lazin
Дата 27.11.2008, 20:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 8
Всего: 154



Цитата(GremlinProg @  27.11.2008,  18:24 Найти цитируемый пост)
На сколько N - переменная величина?

может отличаться каждый следующий блок данных, в общем сильно переменная величина smile 
По ТЗ писать нужно обязательно в один файл, в общем, пока пришел к выводу, что буду время от времени закрывать файлы а потом опять открывать. Скажем каждые 50 мегабайт... потом попробую сделать нормально, с записью без буферизации smile 
PM MAIL Skype GTalk   Вверх
Lazin
Дата 3.12.2008, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 8
Всего: 154



Проблема оказалась глубже чем я думал, вот код, который ее иллюстрирует:
Код

#include <windows.h>
#include <cstdio>
#include <iostream>

int main(int argc, char* argv[])
{
    HANDLE file_ = INVALID_HANDLE_VALUE;
    file_ = CreateFile(
                            "test_file.txt",
                            GENERIC_WRITE, 
                            FILE_SHARE_READ|FILE_SHARE_WRITE, 
                            0, 
                            OPEN_ALWAYS, 
                            FILE_FLAG_SEQUENTIAL_SCAN, 
                            NULL
                            );
    if (file_ == INVALID_HANDLE_VALUE || file_ == NULL)
    {
        std::cout << "create error " << GetLastError() << std::endl;
        system("pause");
        return GetLastError();
    }
    int counter = 0;
    DWORD io_bytes = 0;
    while(true)
    {
        char buffer[0x1000];
        int len = _snprintf_s(buffer, 0x1000, 0xffff, "test message %d\r\n", counter);
        counter++;
        if ( !WriteFile(file_, buffer, len, &io_bytes, NULL) )
        {
            std::cout << "write error " << GetLastError() << std::endl;
            system("pause");
            return GetLastError();
        }
        //Sleep(0);
    }
}

эта программа просто пишет в файл, синхронно, при этом, файл открыт для записи и к тому-же система позволит открыть этот файл для записи и для чтения другому процессу. 
Что-бы наблюдать утечку памяти, нужно запустить эту программу, при этом, она начнет писать данные в файл. Системный кэш расти при этом не будет. Но, если открыть этот файл чем нибудь еще, даже просто для просмотра(я пробовал это делать TotalCommander-ом и FAR-ом, а так-же утилитой grep) системный кэш начнет расти, причем ровно настолько, сколько данных записано в файл. Если после того, как вы открыли файл на просмотр программа запишет гигабайт данных в файл, то размер системного кэша увеличится на гигабайт - железно, при этом, если не будет хватать памяти, будет выгружено все что только может быть выгружено smile . Причем эта память не освобождается до тех пор, пока файл не будет закрыт всеми приложениями, открывшими его.
Короче это какой-то .... мне нужно именно в таком режиме его записывать, в общем, я не знаю что делать...

Это сообщение отредактировал(а) Lazin - 3.12.2008, 11:32
PM MAIL Skype GTalk   Вверх
GremlinProg
Дата 3.12.2008, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



FILE_FLAG_SEQUENTIAL_SCAN -  флаг для последовательного доступа
а при FILE_SHARE_READ|FILE_SHARE_WRITE доступ к файлу из чужих процессов уже явно не последовательный
т.е. тут нужно скорее всего выбрать что-то одно: либо скорость эксклюзивного доступа, либо интерактивность с чужими процессами

по крайней мере это логично, когда система отменяет влияние флага FILE_FLAG_SEQUENTIAL_SCAN и начинает кэшировать данные, когда файл последовательно не читается


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0593 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.