Я пытаюсь лучше понять объем памяти, который выделяется в куче в С++. Я написал небольшую тестовую программу, которая в основном делает не что иное, как заполнение ряда 2D-векторов. Я запускаю это на 64-битной виртуальной машине Linux и использую инструмент valgrind massif для профилирования памяти.
В среде, в которой я запускаю этот тест, на: Linux VM работает в VirtualBox на Win10. Конфигурация VM: Базовая память: 5248 МБ, 4CPU, колпачок На 100% дисковый VDI (динамически распределенная память).
Программа тестирования профилей памяти c++:
/**
* g++ -std=c++11 test.cpp -o test.o
*/
#include <string>
#include <vector>
#include <iostream>
using namespace std;
int main(int argc, char **arg) {
int n = stoi(arg[1]);
vector<vector<int> > matrix1(n);
vector<vector<int> > matrix2(n);
vector<vector<int> > matrix3(n);
vector<vector<int> > matrix4(n);
vector<vector<int> > matrix5(n);
vector<vector<int> > matrix6(n);
vector<vector<int> > matrix7(n);
vector<vector<int> > matrix8(n);
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix1[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix2[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix3[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix4[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix5[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix6[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix7[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix8[i].push_back(j);
}
}
}
Я запускаю следующий bash script, чтобы извлечь профили памяти при разных значениях n
(test.o - это программа выше, скомпилированная с g++ -std = С++ 11, g++ - версия 5.3 0,0)
valgrind --tool=massif --massif-out-file=massif-n1000.txt ./test.o 250
valgrind --tool=massif --massif-out-file=massif-n1000.txt ./test.o 500
valgrind --tool=massif --massif-out-file=massif-n1000.txt ./test.o 1000
valgrind --tool=massif --massif-out-file=massif-n2000.txt ./test.o 2000
valgrind --tool=massif --massif-out-file=massif-n4000.txt ./test.o 4000
valgrind --tool=massif --massif-out-file=massif-n8000.txt ./test.o 8000
valgrind --tool=massif --massif-out-file=massif-n16000.txt ./test.o 16000
valgrind --tool=massif --massif-out-file=massif-n32000.txt ./test.o 32000
Это дает мне следующие результаты:
|--------------------------------|
| n | peak heap memory usage |
|-------|------------------------|
| 250 | 2.1 MiB |
| 500 | 7.9 MiB |
| 1000 | 31.2 MiB |
| 2000 | 124.8 MiB |
| 4000 | 496.5 MiB |
| 8000 | 1.9 GiB |
| 16000 | 6.2 GiB |
| 32000 | 6.1 GiB |
|--------------------------------|
Каждая матрица будет размером n ^ 2, у меня всего 8 матриц, поэтому я ожидал, что использование памяти будет около f(n) = 8 * n^2
.
Вопрос 1 От n = 250 до n = 8000, почему использование памяти более или менее умножается на 4 при n * = 2?
От n = 16000 до n = 32000 происходит что-то очень странное, потому что valgrind действительно сообщает об уменьшении памяти.
Вопрос 2 Что происходит между n = 16000 и n = 32000, как может быть возможно, что кучная память меньше, а в теории больше данных должно быть выделено?
См. ниже выход массива-визуализатора для n = 16000 и n = 32000.