Когда я читаю файл размером 1 миллион URL-адресов размером 17 МБ, моя программа занимает размер 163 МБ. - PullRequest
0 голосов
/ 04 июня 2018

Я читаю файл следующим образом.

std::vector<std::string> urlList;
std::ifstream infile("top1m.txt");
std::string line;
std::cout << "Loading urls from file" << std::endl;
for (int offset = 0; offset < _urlCount; offset++) {  //_urlCount=1000000
    std::getline(infile, line);
    if (!line.empty()){
        if (line.back() == '\r')
            line.erase(line.length() - 1, std::string::npos);
    }
    urlList.push_back(std::string("http://").append(line));
}
inflie.close();

Размер файла top1m.txt составляет 17 МБ.Перед чтением файла мой .exe всего 6 мб.Что я делаю не так и как уменьшить объем памяти, занимаемой программой?

1 Ответ

0 голосов
/ 05 июня 2018

Учитывая, что вы знаете значение _urlCount до начала цикла, самый простой способ сохранить память - это зарезервировать элементы вектора перед началом цикла, используя следующую строку:

urlList.reserve(_urlCount);

Причина, по которой это сэкономит огромный объем памяти, заключается в том, что любая реализация вектора работает путем резервирования исходного небольшого количества элементов, обычно в первый раз, когда он становится не пустым, затем каждый раз, когда push_back будет превышать емкость хранилища вектора, который он выделяетбольший буфер с емкостью, которая в несколько раз превышает старую емкость (иногда эта константа равна 2, но зависит от реализации), затем копирует существующие элементы из старого буфера в новый буфер перед добавлением нового элемента.Старые буферы часто остаются в памяти как кандидаты для повторного использования.

Итак, давайте предположим, что емкость, выбранная для исходного размера, равна 8 элементам, а коэффициент роста равен 2, и игнорируем служебные данные malloc, но предполагаем, что чем меньшебуферы не используются повторно, по крайней мере, в тот момент, когда вы проверяете размер вашей программы.

Когда у вас есть 1 строка, первое тело вектора может вместить 8 строк.К тому времени, когда у вас есть 8 + 1 строк, новое тело вектора имеет емкость 2 * 8, но у вас все еще есть (как освобожденная память) старый буфер для старого тела тела с емкостью 8.

если у вас есть 1 000 000 строк, у вас потенциально могут быть следующие буферы в памяти:

1 используется буфер для тела вектора с емкостью для 2 ** 20 строк

1 свободный буфер с емкостью для 2 **19 строк

1 свободный буфер с емкостью для 2 ** 18 строк

...

1 свободный буфер с емкостью для 8 строк

Конечновозможно, что некоторые из этих меньших буферов могут быть повторно использованы в какой-то момент, и я просто набрал начальную емкость 8 и использовал фактор роста 2, потому что я видел это на какой-то старой реализации std :: vector, и я такжеигнорируя детали реализации std :: string, но вы поймете, что идея.

Когда вы зарезервируете место для 1 000 000 строк, вы получите только один большой буфер для вектора.тело.Учитывая размер строк, у вас все еще будет 1 000 000 меньших буферов, связанных со строками URL, и вы могли бы сэкономить огромное количество места, не используя std :: string, но это уже другая история, которая не рассматривается в этом ответе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...