2013-05-22 1 views
1

Я пишу приложение, в котором я читаю значения из файла csv. Каждая строка разделяется, где запятая хранится в векторе. Каждая строка имеет 4 значения. Затем я сохраняю каждое значение другому вектору. Файл csv имеет 5.795.857 строк. Поэтому в моей структуре я хочу хранить значения 4 * 5.795.857. Проблема заключается в том, что приложение подавляет. Как я вижу, с отладчиком я раздавил примерно на линии 405 000. Я знаю, что мой компьютер немного стар, но я думаю, что он должен иметь возможность хранить это количество значений. Я запускаю Qt5 на WindowsXP 32bit, и у меня 1GB RAM.Проблемы с памятью с Qt5

Я новичок в программировании на Qt и C++, но как разработчик Java, когда у меня возникают такие проблемы, я увеличиваю размер кучи. Вы думаете, что это моя проблема? Если да, то как я могу увеличить размер кучи в Qt5?

Это мой код, который читает файл и сохраняет его в структуре данных

std::vector < std::vector < QString> > Server::loadCsvFile(const char* path) 
{ 
    vector <QString> temp; 
    vector <vector <QString> > dataFlow; 
    string dataString; 
    QString row; 
    ifstream dataFile(path); 

    int stopCounter = 0; 

    //while((dataFile.good()) && (stopCounter < 1095)) 
    while (dataFile.good()) 
    { 
    stopCounter++; 
    getline(dataFile, dataString); 
    row = QString::fromStdString(dataString); 
    //cout << "counter: " << stopCounter << "\n"; 
    QStringList rowList = row.split(","); 

    for( int i=0; i < rowList.size(); i++) 
    { 
     temp.push_back(rowList.at(i)); 
    } 

    dataFlow.push_back(temp); 
    temp.clear(); 
    rowList.clear(); 
    } 

    dataFile.close(); 
    dataFlow.pop_back(); 

    return dataFlow; 
} 

До сих пор я сделал некоторые изменения, чтобы это не исправляет мою проблему, но ничего. Вот как это выглядит мой код знает:

std::vector <QStringList> Server::loadCsvFile2(const char* path) 
{ 
    std::vector <QStringList> dataFlow; 
    QFile file(path); 
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) 
     throw std::runtime_error("Can't open the file " + 
           std::string(path)); 
    QTextStream in(&file); 
    int counter = 0; 
    while (!in.atEnd()) 
    { 
     counter++; 
     dataFlow.emplace_back(in.readLine().split(",")); 
     cout << counter << "\n"; 
    } 
    return dataFlow; 
} 
+0

Какова средняя длина (приблизительно) каждой строки вашего CSV-файла? Строки 4 * 5M = 20M - это много данных, если каждая строка содержит около 500 символов, вы потребляете весь свой Gb около 405000-го элемента. – Fabien

+0

Это пример первой строки: 20121215,4000039_14,9,24. Остальная часть линии похожа на эту – salvador

+0

И чем вы их храните? a 'vector '? Имеет ли Qt что-то общее с этой частью кода? – Fabien

ответ

0

В принципе, std::vector состоит из трех элементов:

  • размера
  • массив элементов
  • емкость

Емкость - это количество элементов, которые вектор может удерживать в текущий момент, и это фактический размер (в ОЗУ) y наш массив. Размер - это количество элементов, которые вы действительно имеете в своем векторе. Например, когда вы создаете пустой vector<int>, его размер равен 0, его емкость составляет 10 (или что-то еще, я не знаю), и массив потребляет 10 * sizeof(int). Если вы указали значение push_back, размер равен 1, но емкость или фактический размер массива не изменились.

Но когда у вас есть 10 элементов в вашем векторе и попытаться добавить одно, что-то происходит: фактический массив заполнен (vec.size() == vec.capacity()), поэтому алгоритм должен расширить эту способность:

  • удвоенное значение мощности ,
  • выделить новый массив, фактический размер которого является новой мощностью; Другими словами, выделить 20 * sizeof(int) байт,
  • скопировать содержимое старого массива в новый массив,
  • свободной памяти, потребляемую старого массива,
  • теперь добавить пункт, как обычно, так как есть зал.

Конечно, теперь вы можете добавить до 20 пунктов, а добавление 21 сделает алгоритм выделения на 40 пунктов, и добавление 41-ый сделает его выделить 80 и т.д.

Как правило, вы не заботятся об этих внутренних деталях. Но когда вы добавляете много-много предметов в вектор, все становится проблематичным. Чем больше вектор растет, тем больше новых распределений и копий занимает время и потребляет ОЗУ. В вашей ситуации, я подозреваю, что ваша 405 001-я строка заставляет алгоритм выделять 810 000 элементов и копировать с первого на второй, и поскольку операционная система работает очень низко, ваша ОС записывает части этого диска, то есть dead slow.

Вы хотите, чтобы начальная емкость массива была достаточно большой, чтобы уменьшить появление перераспределений. Что вы можете сделать, это вызвать метод reserve и дать ему достаточно большое количество, чтобы избежать слишком большого количества ассигнований. Однако, боюсь, у вас может не хватить ОЗУ для достижения этого процесса.

+0

приятный разброс относительно распределения памяти векторов. Я использовал метод reserver, но ничего не изменилось. Также я делаю некоторые вычисления: 4 * 5.795.857 = 23183428 lines // если каждый элемент имеет 4 символа: 23183428 * 1 (должен быть один байт на символ) * 4 = 92733712 байта // 92733712/1024 = 90560 КБ // 181120.5/1024 = 88.4375 MB // поэтому, если я прав, это не должно быть проблемой памяти (извините за формат, который я не смог добавить разрывы строк) – salvador