0

I came across a code in How to get memory usage at run time in c++?. The code is due to @DonWakefield I ran two instances of the code and got different results.

Code:
#include <unistd.h>
#include <ios>
#include <iostream>
#include <fstream>
#include <string>

//////////////////////////////////////////////////////////////////////////////
//
// process_mem_usage(double &, double &) - takes two doubles by reference,
// attempts to read the system-dependent data for a process' virtual memory
// size and resident set size, and return the results in KB.
//
// On failure, returns 0.0, 0.0

void process_mem_usage(double& vm_usage, double& resident_set)
{
using std::ios_base;
using std::ifstream;
using std::string;

vm_usage     = 0.0;
resident_set = 0.0;

// 'file' stat seems to give the most reliable results
//
ifstream stat_stream("/proc/self/stat",ios_base::in);

// dummy vars for leading entries in stat that we don't care about
//
string pid, comm, state, ppid, pgrp, session, tty_nr;
string tpgid, flags, minflt, cminflt, majflt, cmajflt;
string utime, stime, cutime, cstime, priority, nice;
string O, itrealvalue, starttime;

// the two fields we want
//
unsigned long vsize;
long rss;

stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr
           >> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt
           >> utime >> stime >> cutime >> cstime >> priority >> nice
           >> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the 
rest

stat_stream.close();

long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to  
use 2MB pages
vm_usage     = vsize / 1024.0;
resident_set = rss * page_size_kb;
}

Test1#
int main()
{
 using std::cout;
 using std::endl;

 std::vector<int> vec1;
 double vm, rss;
 double vm1, rss1;

 process_mem_usage(vm, rss);

 vec1.resize(800000);

 process_mem_usage(vm1, rss1);
 cout << "VM: " << vm1-vm << "; RSS: " << rss1-rss << endl;

 vec1.erase(vec1.begin(), vec1.end());
 process_mem_usage(vm1, rss1);
 cout << "VM: " << vm1-vm << "; RSS: " << rss1-rss << endl;
 }

 Output:
 VM: 3128; RSS: 3208
 VM: 3132; RSS: 3316

 Test2#
 int main() 
 {
 using std::cout;
 using std::endl;
 int *vec1;
 double vm, rss;
 double vm1, rss1;

 process_mem_usage(vm, rss);

 vec1 = new int [800000];

 process_mem_usage(vm1, rss1);
 cout << "VM: " << vm1-vm << "; RSS: " << rss1-rss << endl;

 delete[] vec1;
 process_mem_usage(vm1, rss1);
 cout << "VM: " << vm1-vm << "; RSS: " << rss1-rss << endl;
 }

 Output:
 VM: 3128; RSS: 76
 VM: 4; RSS: 180

Why do these tests behave differently. Shouldn't the results be closer to each other? Even the memory consumed by vector/pointer is not reflected in the output.

Another question I have is that the output shows vector occupying large memory while test2# shows the int array occupying low memory. 80k ints would require 3125kB of memory. Why is there a difference?

Community
  • 1
  • 1
Suman Vajjala
  • 217
  • 1
  • 2
  • 8
  • erasing elements from a vector doesn't recover any memory. – Roger Rowland Mar 15 '13 at 05:42
  • @roger_rowland I had some thought about this. how do I recover memory in the program then? So, whenever an erase operation is done, is memory reclaimed only when the program exits? If a vector is erased then can new allocations get access to this memory? – Suman Vajjala Mar 15 '13 at 05:53

1 Answers1

0

The underlying structure of a vector is an array that may be bigger or equal to the number of populated elements (this is called the capacity of the vector). This is to prevent constant reallocation of the entire array as you insert and remove elements.

When you erase the elements, the capacity doesn't change and the underlying structure is still there.

This question covers how to change the capacity. The recommended way appears to be:

vector<int>().swap(vec1);
Community
  • 1
  • 1
Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
  • Ok. So, in test1# the vector's memory would still be 80,000? – Suman Vajjala Mar 15 '13 at 07:46
  • @SumanVajjala Yes, until the vector goes out of scope or you use `swap` to swap its structure with a smaller vector as above (an empty one in this case). – Bernhard Barker Mar 15 '13 at 07:49
  • Shouldn't the program consume just 312.5 kB of memory? This is not reflected in the output – Suman Vajjala Mar 15 '13 at 07:53
  • @SumanVajjala It's 800,000 elements, not 80,000, so 800,000*4 bytes = 3125 KB. – Bernhard Barker Mar 15 '13 at 07:57
  • Ohh. My bad. I did swap the vector but the program shows around 1000 KB of memory. Another question is why does the program show that VM is consumed? Also, why are the memory statistics different for the 2 tests? – Suman Vajjala Mar 15 '13 at 08:01
  • @SumanVajjala I don't understand the first question. [This](https://ideone.com/9GjHkw) shows similar results to the array test, except that the resident size is different, this may be because the compiler saw the `int[800000]` and reserved memory for that or something along those lines. – Bernhard Barker Mar 15 '13 at 08:15