Предположим, вы хотите прочитать данные из большого текстового файла (~ 300 МБ) в массив векторов: vector<string> *Data
(предположим, что количество столбцов известно).
//file is opened with ifstream; initial value of s is set up, etc...Data = new vector<string>[col];
string u;
int i = 0;
do
{
istringstream iLine = istringstream(s);
i=0;
while(iLine >> u)
{
Data[i].push_back(u);
i++;
}
}
while(getline(file, s));
Этот код отлично работает для небольших файлов (<50mb), но использование памяти увеличивается в геометрической прогрессии при чтении большого файла. Я уверен, что проблема заключается в создании istringstream
объекты каждый раз в цикле. Тем не менее, определяя istringstream iLine;
вне обеих петель и помещая каждую строку в поток iLine.str(s);
и очистка потока после внутреннего цикла while (iLine.str(""); iLine.clear();
) вызывает тот же порядок взрыва памяти, а также.
Вопросы, которые возникают:
istringstream
ведет себя так;Спасибо
РЕДАКТИРОВАТЬ: Что касается 1-го ответа, я очищаю память, выделенную массивом позже в коде:
for(long i=0;i<col;i++)
Data[i].clear();
delete []Data;
ПОЛНЫЙ КОМПЛЕКСНО-ГОТОВЫЙ КОД (добавьте заголовки):
int _tmain(int argc, _TCHAR* argv[])
{
ofstream testfile;
testfile.open("testdata.txt");
srand(time(NULL));
for(int i = 1; i<1000000; i++)
{
for(int j=1; j<100; j++)
{
testfile << rand()%100 << " ";
}
testfile << endl;
}
testfile.close();
vector<string> *Data;
clock_t begin = clock();
ifstream file("testdata.txt");
string s;
getline(file,s);
istringstream iss = istringstream(s);
string nums;
int col=0;
while(iss >> nums)
{
col++;
}
cout << "Columns #: " << col << endl;
Data = new vector<string>[col];
string u;
int i = 0;
do
{
istringstream iLine = istringstream(s);
i=0;
while(iLine >> u)
{
Data[i].push_back(u);
i++;
}
}
while(getline(file, s));
cout << "Rows #: " << Data[0].size() << endl;
for(long i=0;i<col;i++)
Data[i].clear();
delete []Data;
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
cout << elapsed_secs << endl;
getchar();
return 0;
}
vector<>
растет память геометрически. Типичным примером является то, что он удваивает емкость всякий раз, когда ему нужно расти. Это может оставить много дополнительного пространства выделенным, но неиспользованным, если ваш цикл заканчивается сразу после такого порога. Вы можете попробовать позвонить shrink_to_fit()
на каждом векторе, когда вы закончите.
Кроме того, память, выделенная распределителями C ++ (или даже просто malloc()
) часто не возвращается в ОС, но остается во внутреннем пуле свободной памяти процесса. это может привести к дальнейшему очевидному росту. И это может привести к результатам shrink_to_fit()
быть невидимым извне процесса.
Наконец, если у вас много маленьких строк («двузначных чисел»), накладные расходы string
объект может быть значительным. Даже если в реализации используется оптимизация с небольшими строками, я предполагаю, что типичная строка использует не менее 16 или 24 байтов (размер, емкость, указатель данных или небольшой строковый буфер) — вероятно, больше на платформе, где size_type
составляет 64 бита. Это много памяти для 3 байтов полезной нагрузки.
Поэтому я предполагаю, что вы видите нормальное поведение vector<>
Я серьезно подозреваю, что это не проблема istringstream (особенно если учесть тот же результат с конструктором iLine вне цикла).
Возможно, это нормальное поведение std :: vector. Чтобы проверить это, как насчет того, чтобы запустить те же строки, но закомментируйте: Data[i].push_back(u);
, Посмотрите, растет ли ваша память таким образом. Если это не так, то вы знаете, где проблема ..
Зависит от вашей библиотеки, vector :: push_back будет увеличивать свою емкость в 1,5 (Microsoft) или 2 (glib) раза каждый раз, когда ему нужно больше места.