c++ Чтение строк файла в вектор‹строку›

Я сделал этот метод для чтения из файла и поместил его в вектор строк;

std::vector<std::string> read_file_lines1(const char* filepath){
    std::vector<std::string> file;
    std::ifstream input(filepath);
    Timer timer;
    float time = 0;
    std::string line;
    int i = 0;
    while (getline(input, line)){
        timer.reset();
        file.push_back(line);
        time += timer.elapsed();
        if (i == 10000)
            std::cout << "10000 done" << std::endl;
        i = ((i + 1) % 10001);
    }
    std::cout << time << std::endl;;
    return file;
}

Но производительность, на мой взгляд, была очень плохой (200 тысяч строк за ~22 секунды).

с небольшим изменением, делающим его vector<string*> (используя file.push_back(new std::string(line)) вызовы pushback увеличились с ~ 16 секунд до ~ 1,2 секунды, что было огромным улучшением (все еще отстает от моих целей), и у него есть небольшой Недостаток: использование памяти; если я хочу очистить память, используемую здесь, мне нужно будет не забыть сделать цикл для очистки каждой строки *

Теперь весь метод занимает 6 ~ секунд, ~ 5 из них в основном используются в строке в методе «getline», и мне очень хотелось бы знать, как его оптимизировать или сделать альтернативу.

PS: я делаю это, загружая 3D-модель, используя ту же модель в Java, требуется ~ 0,8 секунды, чтобы прочитать все И ФИЛЬТР (помещая «каждую строку в» массив вершин/текстур... и затем помещая их в индекс порядок), поэтому я очень разочарован, если мне потребуется столько времени, чтобы прочитать каждую строку из файла на С++ (используя режим отладки как в java/С++, что, вероятно, делает его довольно плохим тестом, но я все еще очень разочарован) ;


person Pedro David    schedule 11.08.2015    source источник
comment
используя режим отладки — Какой смысл сравнивать неоптимизированный код?   -  person Benjamin Lindley    schedule 11.08.2015
comment
Не могли бы вы указать мне, где мой код не оптимизирован? Это было то, что я хотел, так как я недоволен редактированием производительности: извините, я не видел использование режима отладки. Я знаю, что это не лучший (даже не хороший) способ сделать это, но я просто сравнивал его со своим опытом работы с Java.   -  person Pedro David    schedule 11.08.2015
comment
использование режима отладки приводит к неоптимизированному коду.   -  person Benjamin Lindley    schedule 11.08.2015
comment
Какая версия С++? Здесь может очень помочь семантика перемещения.   -  person sbabbi    schedule 11.08.2015
comment
Он имеет в виду, что вместо этого вы должны протестировать построенную программу в режиме выпуска.   -  person jaggedSpire    schedule 11.08.2015
comment
использование режима отладки означает Пожалуйста, не заставляйте этот код работать быстро!.   -  person Bo Persson    schedule 12.08.2015
comment
Ваш компилятор C++ и ваш компилятор Java написаны разными командами с разными представлениями о том, что следует добавить в код, чтобы упростить отладку. Не говоря уже о различиях между самими языками. Ваше сравнение между этими двумя вещами не очень полезно.   -  person Benjamin Lindley    schedule 12.08.2015
comment
Эта печать в cout также займет некоторое время.   -  person Daniel Jour    schedule 12.08.2015
comment
Я знаю, что это плохой тест, сравнивающий компилятор отладки С++ с компилятором Java, я просто был очень разочарован производительностью и хотел знать, есть ли у кого-то лучший/быстрый способ сделать это или я делаю что-то действительно неправильно   -  person Pedro David    schedule 12.08.2015
comment
код отладки может быть в сто раз медленнее, чем релиз, вы также можете добавить вызовы сна в свой код, чтобы вы могли еще больше разочароваться в производительности.   -  person ISanych    schedule 12.08.2015
comment
Я действительно не знаю, как проверить версию, но __cplusplus возвращает 199711L, так что С++ 98? (должен ли я изменить это? как?)   -  person Pedro David    schedule 12.08.2015
comment
Возможный дубликат строки чтения из текстового файла и поместить строки в вектор?   -  person TheArchitect    schedule 15.05.2017


Ответы (1)


Основная причина, почему это медленно, заключается в том, что вам нужно перераспределять память и перемещать все строки в новое место каждый раз, когда достигается емкость вектора. Используйте std::deque вместо вектора, deque не перераспределяет память, она добавляет новые куски. Или вы можете предварительно выделить вектор с помощью метода reserve, чтобы избежать перераспределения.

Кроме того, код отладки С++ может быть намного медленнее, чем выпуск, особенно с большим количеством шаблонов и/или встроенного кода - вам действительно нужно измерить производительность выпуска, и вам нужно использовать таймер только один раз для всего цикла, поскольку я подозреваю, что в режиме выпуска вы будете тратить много времени на код таймера.

Еще одна небольшая оптимизация. вместо

    if (i == 10000)
        std::cout << "10000 done" << std::endl;
    i = ((i + 1) % 10001);

использовать:

    if (i == 10000)
    {
        std::cout << "10000 done" << std::endl;
        i = 0;
    }
    ++i;
person ISanych    schedule 11.08.2015
comment
Большое спасибо. Я уже тестировал без cout и разница была незначительна. Попробую деку. Я попробовал резерв(), но обычно это делало его еще медленнее (не знаю почему). Кроме того, несмотря на то, что все еще не доволен производительностью push_back, теперь гораздо лучше выдвигаются указатели, чем строки. Сейчас меня больше всего беспокоит вызов getLine(), который занимает почти 5 секунд, в основном из-за того, как он добавляет строку (большая часть времени тратится на вызовы string+=, поэтому я хотел знать, есть ли лучшая альтернатива - person Pedro David; 12.08.2015
comment
тестирование производительности отладочной версии не имеет смысла, сначала попробуйте релизную версию. в вашем коде нет проблем с cout, так как вы не делаете это часто, но работа таймера вне цикла поможет повысить производительность (опять же, в версии выпуска). указатели помогают со скоростью, потому что перемещать указатели намного быстрее, но вы можете вообще избавиться от перемещения. - person ISanych; 12.08.2015
comment
Можно ли вообще отказаться от движения? Не могли бы вы немного расширить это? - person Pedro David; 12.08.2015
comment
std::deque не перераспределяет память при push_back - когда не осталось зарезервированного места, выделяется новый кусок памяти, память не является непрерывной, но в большинстве случаев это нормально. просто замените вектор на deque, и все остальное должно работать точно так же. - person ISanych; 12.08.2015
comment
deque помог тем более, что большое спасибо. getline по-прежнему занимает много времени в отладке (~ 5 секунд), поэтому я хотел бы знать, есть ли лучший вариант, но в выпуске весь процесс теперь занимает полсекунды, так что все выглядит нормально. Кроме того, с deque я использую ‹string› вместо ‹string*›, потому что производительность примерно такая же, но мне не нужно помнить об очистке памяти после того, что действительно круто - person Pedro David; 12.08.2015