为什么流程的WorkingSet会增加以及如何处理呢?

时间:2017-03-31 08:36:52

标签: c++ visual-c++

在解决应用程序中的内存泄漏问题时,我发现了另一种我担心的现象。当重复地在堆(new和delete)上分配和释放大量对象时,进程的工作集似乎随着每个循环而不断增加。我在Windows 7上使用MS Visual Studio 2013做了一个例子。

这是我用来显示工作集大小的函数:

#include <windows.h>
#include <Psapi.h>

size_t getWorkingSetInBytes()
{
  size_t result = 0;

  long   lProcessId = GetCurrentProcessId();

  HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
    FALSE,
    lProcessId);

  PROCESS_MEMORY_COUNTERS memoryInfo;
  GetProcessMemoryInfo(hProcess, &memoryInfo, sizeof(memoryInfo));
  result = size_t(memoryInfo.WorkingSetSize);

  CloseHandle(hProcess);

  return result;
}

我有一个简单的示例类:

class A
{
public:
  long m_one;
  long m_two;
};

使用new / delete的功能:

void loopWithNew(size_t loops, size_t objects)
{
  for(size_t i = 0; i < loops; ++i)
  {
    {
      std::vector<A*> vecA;

      for(size_t j = 0; j < objects; ++j)
      {
        A* a = apsnew A();
        a->m_one = 42;
        a->m_two = 43;
        vecA.push_back(a);
      }

      for(auto iter = vecA.begin(); iter != vecA.end(); ++iter)
      {
        delete *iter;
      }
    }

    std::cout << "working set in bytes after deleting all objects: " << getWorkingSetInBytes() << std::endl;
  }
}

一个不使用new / delete:

void loopWithoutNew(size_t loops, size_t objects)
{
  for(size_t i = 0; i < loops; ++i)
  {
    {
      std::vector<A> vecA(objects);

      for(size_t j = 0; j < objects; ++j)
      {
        vecA[j].m_one = 42;
        vecA[j].m_two = 43;
      }
    }

    std::cout << "working set in bytes after deleting all objects: " << getWorkingSetInBytes() << std::endl;
  }
}

主要来自:

int main(int argc, char** argv)
{
  size_t loops = 10;
  size_t objects = 10000000;

  size_t beforeStart = getWorkingSetInBytes();
  std::cout << "working set before start: " << beforeStart << std::endl;

  std::cout << std::endl << "loops with new: " << std::endl;
  loopWithNew(loops, objects);


  std::cout << std::endl << "loops without new: " << std::endl;
  loopWithoutNew(loops, objects);
}

程序产生以下输出:

working set before start: 2396160

loops with new:
working set in bytes after deleting all objects: 3923968
working set in bytes after deleting all objects: 3813376
working set in bytes after deleting all objects: 3964928
working set in bytes after deleting all objects: 3866624
working set in bytes after deleting all objects: 3923968
working set in bytes after deleting all objects: 3989504
working set in bytes after deleting all objects: 4059136
working set in bytes after deleting all objects: 4067328
working set in bytes after deleting all objects: 4210688
working set in bytes after deleting all objects: 4259840

loops without new:
working set in bytes after deleting all objects: 4259840
working set in bytes after deleting all objects: 4259840
working set in bytes after deleting all objects: 4259840
working set in bytes after deleting all objects: 4259840
working set in bytes after deleting all objects: 4259840
working set in bytes after deleting all objects: 4259840
working set in bytes after deleting all objects: 4259840
working set in bytes after deleting all objects: 4259840
working set in bytes after deleting all objects: 4259840
working set in bytes after deleting all objects: 4259840

虽然带有new / delete的循环会随着时间的推移而增加工作集,但没有new / delete的版本似乎不会增加工作集。这带来了多个相关问题:

  • 此问题是堆碎片的症状吗?
  • 这对长时间运行的流程有什么影响?
  • 即使我正确删除了所有对象,进程是否会越来越多地使用并最终耗尽内存?
  • 在完成对象集合或避免问题后,有没有办法真正“清理”内存? (除了分配一个连续内存池以手动管理我的对象)

0 个答案:

没有答案