Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / При работе с потоками СИЛЬНО растет используемая память / 20 сообщений из 20, страница 1 из 1
26.05.2018, 10:30
    #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
26.05.2018, 10:44
    #39650265
a guest
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
При работе с потоками СИЛЬНО растет используемая память
Заведи себе БД.
...
Рейтинг: 0 / 0
26.05.2018, 10:46
    #39650267
AlekseySQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
При работе с потоками СИЛЬНО растет используемая память
a guestЗаведи себе БД.

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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


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