У меня есть приложение на C ++, и я заранее знаю, что я ожидаю, что около 1000 элементов (иногда немного больше) будут храниться и обрабатываться для сотен экземпляров.
Проблема заключается в том, что память, используемая процессом, увеличивается медленно, но память сервера перегружается за несколько часов.
Я использую valgrind для обнаружения возможных утечек памяти.
редактировать
Во-первых, спасибо всем за предложения. Мне удалось решить много ошибок. Я добавил виртуальные деструкторы в некоторые классы и изменил некоторые указатели на boost::shared_ptr
используя сброс, чтобы удалить их. Однако со временем у меня все больше и больше памяти.
Основными частями приложения являются следующие:
#ifdef GLOBAL
#define Global
#else
#define Global extern
#endif
typedef std::map<uint32_t, ResultStruct> ClassDResultMap ;
typedef std::map<uint32_t, ClassDResultMap > ClassCResultMap ;
typedef std::map<uint32_t, ClassCResultMap > ClassBResultMap ;
typedef std::map<uint32_t, ClassBResultMap > ClassAResultMap ;
Global ClassAResultMap classAresultmap;
ClassZero создает много ClassA
typedef std::map<uint32_t,ClassA*> classAMap;
classA_[aid] = new ClassA(io_service_, filename.c_str(), id, pri_queue_);
Внутри ClassA создается до 3200 экземпляров ClassB:
typedef std::map<uint32_t, boost::shared_ptr<ClassB >> classBMap ;
classBMap[aid].insert(std::pair<uint32_t, boost::shared_ptr<ClassB>>(bid, boost::make_shared<ClassB >(io_service_, pri_queue_, ...)));
Внутри ClassB до 4 экземпляров ClassC создаются внутри структуры ConfigMap, имеющей член boost::shared_ptr<ClassC > classC_;
:
typedef std::map<uint32_t, classCConfig> ConfigMap;
(ConfigMap::iterator)->second.classC_ = boost::make_shared<ClassC >(io_service_, pri_queue_, ...);
Внутри ClassC один ClassD создается конструктором ClassC
ClassC::ClassC(...): ClassD(io_service_, pri_queue_,...),... { }
Затем внутри ClassD элементы обрабатываются и результаты вычисляются каждые 10-30 секунд, а не сохраняются в ClassDResultMap:
(ClassDResultMap::iterator)->second[results.stime] = results;
Наконец, внутри другого класса, ClassStorage, все результаты в глобальном ClassAResultmap сохраняются в файлы и очищаются:
std::ofstream res_stream_;
res_stream_ << "{ \"start\" : " << results_it->second.stime << ...;
(ClassDResultMap::iterator)->second.clear();
std::map<uint32_t, ClassDResultMap>().swap((ClassDResultMap::iterator)->second);
Это то, что я получаю с Valgrind с 1 класса A: 8 ClassB: 32 класса C / D
==9544== HEAP SUMMARY:
==9544== in use at exit: 25,817 bytes in 171 blocks
==9544== total heap usage: 148,771 allocs, 148,600 frees, 16,803,272 bytes allocated
==9544==
==9544== 1,216 bytes in 4 blocks are possibly lost in loss record 39 of 45
==9544== at 0x4C2677B: calloc (vg_replace_malloc.c:593)
==9544== by 0x40118A2: _dl_allocate_tls (in /lib64/ld-2.12.so)
==9544== by 0x5F971E8: pthread_create@@GLIBC_2.2.5 (in /lib64/libpthread-2.12.so)
==9544== by 0x4E3ACC0: boost::thread::start_thread_noexcept() (in /usr/local/lib/libboost_thread.so.1.54.0)
==9544== by 0x45EE92: boost::thread::start_thread() (thread.hpp:180)
==9544== by 0x461429: boost::thread::thread<boost::_bi::bind_t<unsigned long, boost::_mfi::mf0<unsigned long, boost::asio::io_service>, boost::_bi::list1<boost::reference_wrapper<boost::asio::io_service> > >&>(boost::_bi::bind_t<unsigned long, boost::_mfi::mf0<unsigned long, boost::asio::io_service>, boost::_bi::list1<boost::reference_wrapper<boost::asio::io_service> > >&) (thread.hpp:267)
==9544== by 0x4605F7: boost::thread* boost::thread_group::create_thread<boost::_bi::bind_t<unsigned long, boost::_mfi::mf0<unsigned long, boost::asio::io_service>, boost::_bi::list1<boost::reference_wrapper<boost::asio::io_service> > > >(boost::_bi::bind_t<unsigned long, boost::_mfi::mf0<unsigned long, boost::asio::io_service>, boost::_bi::list1<boost::reference_wrapper<boost::asio::io_service> > >) (thread_group.hpp:78)
==9544== by 0x45CAC9: main (main.cpp:151)
==9544==
==9544== LEAK SUMMARY:
==9544== definitely lost: 0 bytes in 0 blocks
==9544== indirectly lost: 0 bytes in 0 blocks
==9544== possibly lost: 1,216 bytes in 4 blocks
==9544== still reachable: 24,601 bytes in 167 blocks
==9544== suppressed: 0 bytes in 0 blocks
==9544== Reachable blocks (those to which a pointer was found) are not shown.
==9544== To see them, rerun with: --leak-check=full --show-reachable=yes
==9544==
==9544== For counts of detected and suppressed errors, rerun with: -v
==9544== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)
и часть main.cpp, на которую жалуется Valgrind:
boost::asio::io_service work_io_service;
ClassZero manager(work_io_service);
boost::thread_group work_threads;
uint32_t workers = boost::thread::hardware_concurrency();
for (std::size_t i = 0; i != workers; ++i)
{
work_threads.create_thread(
boost::bind(&boost::asio::io_service::run, boost::ref(work_io_service)));
}
Моя проблема в том, что почти за 20 минут серверная память (4 ГБ) увеличилась с 3% до 17% и продолжает работать. Использование памяти процесса увеличивается, но остается ниже 4%!
Задача ещё не решена.