| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Системное программирование и WinAPI > Системный кэш |
| Автор: Lazin 1.11.2008, 17:08 |
| В общем возникла такая проблема. Некоторое приложение записывает в файл, асинхронно, N Gb данных, после этого диспетчер задач windows показывает, что размер системного кэша ровно N Gb и он не освобождается. Что не так? |
| Автор: GremlinProg 1.11.2008, 21:21 |
| показывай как пишешь в файл (я так полагаю, речь не о системном кэше, а о своп-файле [файле подкачки]) |
| Автор: Lazin 1.11.2008, 22:18 |
| нет, именно о системном кэше, не о своп файле |
| Автор: GremlinProg 1.11.2008, 23:16 | ||
ну, тогда пробуй выключить буферизацию: FILE_FLAG_NO_BUFFERING
но писать/читать при этом можно будет только по кратным адресам, кратным размеру сектора (обычно 512 байт) проще всего взять размер страницы, т.к. он точно ему кратен если есть желание, можешь так же использовать физическую память, если важна скорость: AllocateUserPhysicalPages, MapUserPhysicalPages, FreeUserPhysicalPages Добавлено через 3 минуты и 49 секунд в смысле и адрес и размер блока, передаваемые в Red/WriteFile должны быть кратны размеру сектора (если это условие не выполняется, функции вернут ошибку) актуально только если файл открыт с флагом FILE_FLAG_NO_BUFFERING |
| Автор: Lazin 1.11.2008, 23:52 |
| Я думал пробовал, но мне нужно писать данные именно асинхронно... то есть с флагом FILE_FLAG_OVERLAPPED |
| Автор: GremlinProg 2.11.2008, 00:16 |
и в чем проблема? эти флаги не противоречат друг другу |
| Автор: GremlinProg 2.11.2008, 00:56 | ||
вот простое чтение без буфера с задержкой
файл читается со смещения 512 байт, и размер блока 512 байт (т.е. в файле должно быть по крайней мере килобайт данных) Добавлено через 2 минуты и 19 секунд с записью точно так же |
| Автор: J0ker 3.11.2008, 05:01 |
| я так думаю надо flush сделать или commit |
| Автор: Lazin 3.11.2008, 10:27 |
flush делается в общем после выходных попробую)) |
| Автор: Lycifer 10.11.2008, 18:54 |
| Думаю поможет flush. А вообще я не знаю как это в винде устроинно, а вот в Linux это не совсем запись в файл, ядро сохраняет некоторые данные в оперативе а потом когда небудь сохраняет на диск, это связано с производительностью, так как файл могут заново открыть, для синхронизации делается системные вызов sync() - да кажется так.))) |
| Автор: Lazin 27.11.2008, 17:05 | ||
| В общем, проблема никуда не делась. Запись в файл без буферизации я сделать не могу, так-как в один файл у меня пишут несколько экземпляров одной программы, синхронизируя доступ к нему. В случае эксклюзивного доступа к файлу это решает проблему, но я не могу придумать алгоритм записи в файл нескольких приложений для случая, когда за один write можно записать 512*n байт, притом, что каждая программа записывает данные блоками по N байт, причем N - переменная величина. Файл я открываю так:
причем, если FILE_SHARE_READ убрать, то проблема исчезает, но в этом случае нельзя читать данные во время записи, что то-же важно. |
| Автор: Lazin 27.11.2008, 20:31 |
может отличаться каждый следующий блок данных, в общем сильно переменная величина По ТЗ писать нужно обязательно в один файл, в общем, пока пришел к выводу, что буду время от времени закрывать файлы а потом опять открывать. Скажем каждые 50 мегабайт... потом попробую сделать нормально, с записью без буферизации |
| Автор: Lazin 3.12.2008, 11:30 | ||
Проблема оказалась глубже чем я думал, вот код, который ее иллюстрирует:
эта программа просто пишет в файл, синхронно, при этом, файл открыт для записи и к тому-же система позволит открыть этот файл для записи и для чтения другому процессу. Что-бы наблюдать утечку памяти, нужно запустить эту программу, при этом, она начнет писать данные в файл. Системный кэш расти при этом не будет. Но, если открыть этот файл чем нибудь еще, даже просто для просмотра(я пробовал это делать TotalCommander-ом и FAR-ом, а так-же утилитой grep) системный кэш начнет расти, причем ровно настолько, сколько данных записано в файл. Если после того, как вы открыли файл на просмотр программа запишет гигабайт данных в файл, то размер системного кэша увеличится на гигабайт - железно, при этом, если не будет хватать памяти, будет выгружено все что только может быть выгружено Короче это какой-то .... мне нужно именно в таком режиме его записывать, в общем, я не знаю что делать... |
| Автор: GremlinProg 3.12.2008, 11:42 |
| FILE_FLAG_SEQUENTIAL_SCAN - флаг для последовательного доступа а при FILE_SHARE_READ|FILE_SHARE_WRITE доступ к файлу из чужих процессов уже явно не последовательный т.е. тут нужно скорее всего выбрать что-то одно: либо скорость эксклюзивного доступа, либо интерактивность с чужими процессами по крайней мере это логично, когда система отменяет влияние флага FILE_FLAG_SEQUENTIAL_SCAN и начинает кэшировать данные, когда файл последовательно не читается |
| Автор: Lazin 3.12.2008, 13:02 | ||
логично, но неправильно. по сути это утечка памяти, если файл будет очень большим и будет открыт долго, то это приведет к неработоспособности системы в целом, даже, если файл в данный момент открыт только одной программой. |
| Автор: GremlinProg 3.12.2008, 15:06 |
а как правильно? правильно, если операционка будет запрещать левым процессам читать файл, если они обращаются к нему непоследовательно? или правильно, если твои процессы, в момент вклинивая левых, будут получать при доступе к файлу ошибку, типа "последовательный доступ к файлу нарушен"? Добавлено через 58 секунд это не утечка памяти, это нормальная работа кэша. Добавлено через 14 минут и 6 секунд Есть, в принципе выход сейчас могу только кинуть ориентир: 1. запрети открытый доступ всем процессам, кроме своего, т.е. убери все флаги FILE_SHARE_xxx 2. при создании очередного "своего" процесса, дублируй дескриптор файла (DuplicateHandle), открытый в первом процессе, для вновь созданного со всеми необходимыми правами доступа. тогда левые процессы не смогут читать/писать в этот файл, а "свои" процессы - смогут |
| Автор: J0ker 4.12.2008, 01:18 |
| FILE_FLAG_SEQUENTIAL_SCAN If an application moves the file pointer for random access, optimum caching may not occur. |