【问题标题】:process and threads consumes a lot of memory after job is done作业完成后进程和线程消耗大量内存
【发布时间】:2021-05-11 10:14:24
【问题描述】:

最近我遇到了一些内存线程相关的问题。 下面的代码创建 5 个线程,每个线程 push_back 到向量 500'000'000 int 值。 在带有 push_back 的循环结束后,程序仍然使用 ~375M 的虚拟内存,这是我的问题,为什么进程仍然使用这么多内存?

我正在使用 g++ (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0

#include <chrono>
#include <iostream>
#include <thread>
#include <vector>

using namespace std;
  

void joinAll(vector<thread>& arg)
{
    for(auto& item : arg) item.join();
}

int main()
{

    vector<thread> threads;
    
    for(int i=0; i<5; ++i)
    {
        threads.emplace_back([](){
            
            {   // block
                vector<int> data;
                
                for(int idx=0; idx<500'000'000; ++idx)
                {
                        data.push_back(idx);    
                }
            }   // end of block
            
            cout<<"loop is over\n";
            
            std::this_thread::sleep_for(chrono::seconds(5));
            
            });
    }    
    
    cout<<"wait in main\n";  
    
    std::this_thread::sleep_for(std::chrono::seconds(5));
    
    joinAll(threads);
        
}

图片呈现htop输出

enter image description here

【问题讨论】:

  • 您永远不会检查任何内存不足/资源处理异常。线程和继续执行中未捕获的异常可能会导致整体未定义行为。让您的操作系统停滞不前的大量机会。
  • 为了记录,这个例子创建了 1B 个元素的向量,而不是 500M。它最初定义了一个包含 500M 元素的向量,然后再添加 500M。
  • 虚拟内存在不再使用时通常不会返回给操作系统。就操作系统所知,该过程即将创建另一个巨大的向量——来回传输内存毫无意义。当进程终止时,或者当另一个进程请求虚拟内存并且操作系统没有任何闲置时,操作系统将回收该内存。仅在内存压力下回收未使用的内存会更有效 - 大多数时候,有很多事情要做。
  • 编译您的 C++ 代码,将 GCC 调用为 g++ -Wall -Wextra -O2 -g,然后使用 strace(1)gdb(1) 了解行为和您的可执行文件完成的 syscalls(2)

标签: c++ linux multithreading memory


【解决方案1】:

进程不需要在不再使用时将其内存返回给操作系统。如果有这样的要求,也是非常低效的。

另外,让我们快速分析一下您的程序的内存需求。假设int 的典型情况为 4 个字节,并假设您的线程并行运行并在相似的时间完成,那么您的程序仅用于您的vectors 就需要大约 2.5GB,更不用说线程本身的内存需求了和任何其他进程内存。您只看到大约 375MB 的使用量这一事实表明,该进程的内存大部分已返回给操作系统。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-29
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    • 2014-09-21
    相关资源
    最近更新 更多