powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / При работе с потоками СИЛЬНО растет используемая память
20 сообщений из 20, страница 1 из 1
При работе с потоками СИЛЬНО растет используемая память
    #39650257
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть у меня файлы с данными по месяцам. Я решил перегруппировать их по клиентам, т.е. создать файлы, которые хранят данные за весь период для каждого отдельного клиента.

Сначала я, обрабатывая каждый месяц исходных данных, открывал и закрывал файл клиента с добавлением нового в конец:
Код: plaintext
1.
File->open(FileName, std::ios::out | std::ios::binary | std::ios::app);



Но это работало очень долго и я решил один раз открывать файл клиента, после каждого месяца делать flush(), а закрывать только когда по клиенту в течении месяца не было сделок. Для этого я создал такой объект:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
    using closerWriteFile = std::function<void(std::ofstream*)>;
    using uptr_ofstream = std::unique_ptr<std::ofstream, closerWriteFile>;

uptr_ofstream OpenBinFileForWrite(cstring& FileName)
{
    closerWriteFile&& Closer = std::bind(CloseFileForWrite, _1, FileName, true);
    uptr_ofstream File(new std::ofstream, std::move(Closer));

    File->open(FileName, std::ios::out | std::ios::binary | std::ios::trunc); //ТЕПЕРЬ ПРИ ОТКРЫТИИ ОЧИЩАЕМ ФАЙЛ КЛИЕНТА
    return std::move(File);
}

void CloseFileForWrite(std::ofstream* File)
{
    File->close();
}

class OpenFiles
    {
        std::map<string, uptr_ofstream> Files;
        std::map<string, uint32> Monthes;

        mutable std::mutex MutexFiles;

    public:

        uptr_ofstream&& Get(cstring& FileName, cuint32 CurrentMonth)
        {
            std::lock_guard<std::mutex> Guard(MutexFiles);

            //remember working with data
            Monthes[FileName] = CurrentMonth;

            //initial find file in map
            std::map<string, uptr_ofstream>::iterator it;
            it = Files.find(FileName);
            if(it != Files.end()) return std::move(it->second);

            //add to map
            Files[FileName] = OpenBinFileForWrite(FileName);

            return std::move(Files[FileName]);
        }

        void CloseOldFiles(cuint32 CurrentMonth)
        {
            if(CurrentMonth != Consistency.GetOldestMonth()) return;

            std::lock_guard<std::mutex> Guard(MutexFiles);

            std::map<string, uptr_ofstream>::const_iterator it;

            for(const auto& Value: Monthes)
            {
                if(Value.second >= CurrentMonth) continue;

                //find files
                it = Files.find(Value.first);
                if(it == Files.end()) continue;

                //delete this file from map
                Files.erase(it);
            }

        }

    } CurrentFiles;



Теперь я могу написать такую функцию дозаписи в файлы:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
void WriteDataForClient(const myLib::array<writeData>& ArrayOfClient,
                                   const uint32 CurrentMonth,
                                   const string& Client)
{
    const string FileName = Settings.at("SubDirectoryWithOutputFiles") + Client + ".bin";

    //find file
    uptr_ofstream&& File = CurrentFiles.Get(FileName, CurrentMonth);

    //write file
    ArrayOfClient.WriteArrayToBinFile(std::move(File)); //ТУТ ДОБАВЛЯЮТСЯ ДАННЫЕ

    //flush added data
    File->flush();
}



Метод CloseOldFiles(cuint32 CurrentMonth) вызывается после обработки каждого месяца (таким образом закрываются файлы, что видно в отладчике).
Но почему- то ОЧЕНЬ сильно растет потребление памяти. Ведь по логике я делаю flush(), и все данные должны сбрасываться на диск. В чем косяк?
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650265
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Заведи себе БД.
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650267
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
a guestЗаведи себе БД.

Любая БД- это накладные расходы, которые замедлят работу (я работаю на домашнем компе и у меня нет отдельного сервера).
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650281
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLЛюбая БД- это накладные расходы, которые замедлят работу (я работаю на домашнем компе и у меня нет отдельного сервера).
Прежде чем заявлять о замедлении работы, стоило бы провести бенчмаркинг и выяснить так ли это на самом деле, скажем, в случае файл-серверной БД (Access, SQLite, ...), и точно ли тебе нужна производительность в 1000000 операций записи-чтения в секунду.
Ведь так можно и до FVMas'а дойти, а там всё плохо закончилось
Используй SQLite как вариант, встроив в приложение как статик-либу. Можно сделать его полностью in-memory и потом дампить на диск когда нужно, не думаю, что данных у тебя столько, что не помещаются в современный объём RAM.
Ну или запили свой LSM-tree
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650296
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLНо почему- то ОЧЕНЬ сильно растет потребление памяти.

При любых проблемах с памятью Вам поможет DrMemory. Очень рекомендую.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650333
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLНо почему- то ОЧЕНЬ сильно растет потребление памяти. Ведь по логике я делаю flush(), и все данные должны сбрасываться на диск. В чем косяк?
Файлы тут ни при чем. Данные пишутся в буфер размером 4-8 кб и по заполнению буфера сбрасываются на диск, т.е. flush() вообще никак не влияет на расход памяти, это просто команда принудительно записать из буфера на диск не дожидаясь заполнения. Дополнительный тормоз защищающий от потери данных в случае вылета проги.
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650338
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima TФайлы тут ни при чем. Данные пишутся в буфер размером 4-8 кб и по заполнению буфера сбрасываются на диск, т.е. flush() вообще никак не влияет на расход памяти, это просто команда принудительно записать из буфера на диск не дожидаясь заполнения. Дополнительный тормоз защищающий от потери данных в случае вылета проги.

Не соглашусь: я в свое время записывал файлы на диск без вызова метода flush(), просто закрывая их (при этом делается принудительный flush()). Так вот закрытие файла было о-о-очень долгим делом, и в итоге я его перенес в отдельный асинхронный поток, чтобы повысить производительность. Не думаю, что эти тормоза были из- за записи 4 кб (а остальные 100-500 МБайт файла писались относительно быстро).
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650345
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLDima TФайлы тут ни при чем. Данные пишутся в буфер размером 4-8 кб и по заполнению буфера сбрасываются на диск, т.е. flush() вообще никак не влияет на расход памяти, это просто команда принудительно записать из буфера на диск не дожидаясь заполнения. Дополнительный тормоз защищающий от потери данных в случае вылета проги.

Не соглашусь: я в свое время записывал файлы на диск без вызова метода flush(), просто закрывая их (при этом делается принудительный flush()). Так вот закрытие файла было о-о-очень долгим делом, и в итоге я его перенес в отдельный асинхронный поток, чтобы повысить производительность. Не думаю, что эти тормоза были из- за записи 4 кб (а остальные 100-500 МБайт файла писались относительно быстро).
ОС кэширует запись на диск, она под это задействует свободную память, но не память процесса. Внутри процесса небольшой буфер, если не веришь - есть исходники, вот одна из реализаций .

Ты повышенный расход памяти как определил: твой процесс много памяти забирает или в целом занято много?
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650349
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima TОС кэширует запись на диск, она под это задействует свободную память, но не память процесса. Внутри процесса небольшой буфер, если не веришь - есть исходники, вот одна из реализаций .

Ты повышенный расход памяти как определил: твой процесс много памяти забирает или в целом занято много?

Процесс потребляет 7 ГБ (при конвертации исходных файлов размером 5 ГБ). Но после завершения обработки память почему- то не высвобождается, так что я буду искать ошибку: какие- то объекты не вызывают своих деструкторов.
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650373
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLя буду искать ошибку

Слушать чужих советов и использовать DrMemory ты отказываешься по идеологическим или
религиозным мотивам?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650395
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем спасибо, ошибка найдена!

Оказалось все дело в том, что в структуру, которой я наполнял массив, было добавлено поле с типом std::string. Это примерно в три раза увеличило размер структуры и как следствие- в три раза увеличился объем потребляемой памяти. Поэтому часть памяти начала свопиться на диск и работа программы сильно замедлилась.

Я завтра протестирую что быстрее: постоянное открытие / закрытие файлов с дозаписью или хранение открытых файлов в коллекции и использование flush().
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650411
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLЯ завтра протестирую что быстрее: постоянное открытие / закрытие файлов с дозаписью или хранение открытых файлов в коллекции и использование flush().
Быстрее второе, а еще быстрее второе без flush()
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650425
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry SibiryakovСлушать чужих советов и использовать DrMemory ты отказываешься по идеологическим или
религиозным мотивам?


Спасибо за советы.
С помощью Vtune Amplifier я проанализировал выделение и освобождение памяти. Оказалось, что никаких утечек нет. Другими словами это не техническая, а логическая ошибка. Поэтому автоматические инструменты не помогут.
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650427
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima TБыстрее второе, а еще быстрее второе без flush()

Если потоки действительно пишут по 4 кб, то тогда так и есть. Завтра проверю.
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650531
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Получилось, что работа с открытием / закрытием файла- самая быстрая. Скорее всего дело в том, что накладные расходы на обслуживание коллекции с открытыми потоками выше, чем накладные расходы на открытие и закрытие файлов.

Да и так проще код. Так как этот код выполняется только один раз, то я за простоту.
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650550
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovAlekseySQLНо почему- то ОЧЕНЬ сильно растет потребление памяти.

При любых проблемах с памятью Вам поможет DrMemory. Очень рекомендую.

им можно отлавливать:
1. переполнение буфера
2. использование после free
?
и ещё выходы за пределы стекового массива или глобального массива он находит ?
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650551
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а с Valgrind не сравнивали его?
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650562
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tip78им можно отлавливать:

Да. И ещё утечки, неинициализированное чтение, неосвобождённые ресурсы и т.д.
Сравнение в Валгриндом есть на сайте. Но лично для меня у Валгринда есть смертельный
недостаток - не работает под Виндой.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650618
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А ларчик просто открывался.

Прозевал.
...
Рейтинг: 0 / 0
При работе с потоками СИЛЬНО растет используемая память
    #39650858
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tip78а с Valgrind не сравнивали его?

У меня из Qt Creator "Анализатор памяти Valgrind" писал ошибку: "Не удалось запустить программу. Путь или права недопустимы?"

Так что я быстро на Intel- овский инструмент перепрыгнул.
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / При работе с потоками СИЛЬНО растет используемая память
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]