Страницы

Поиск по вопросам

воскресенье, 29 марта 2020 г.

Оптимизация работы с памятью в С++

#cpp #память


решил написать свой .obj парсер, и столкнулся с небольшой проблемой...

...

std::vector> vertices;

std::string line;
std::ifstream inputStream(objFileName);
while (std::getline(inputStream, line))
{
    if (line.substr(0, 2) == "v ")
    {
        std::istringstream stream(line.substr(2));
        float x, y, z;
        stream >> x;
        stream >> y;
        stream >> z;
        vertices.push_back({ x, y, z, 1.0f });
    }

    ... // Texture coordinate, normals e.t.c.
}


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


Ответы

Ответ 1



В современном С++ всю работу с константными/немодифиуируемыми [под]строками имеет смысл переводить на использование std::string_view. То есть везде, где в вашей программе явно или концептуально выступает const std::string & он должен быть заменен на const std::string_view &. Это относится и к вашему применению substr. Нет никаких причин формировать целый новый std::string объект только ради выделения немодифицируемой подстроки. По уму и std::string::substr должен был бы возвращать std::string_view, а не std::string, но так исторически сложилось и сейчас уже не переделать. В данном случае можно предложить заменить все line.substr(i, j) на std::string_view(line).substr(i, j) Это избавит вас от ненужных промежуточных std::string объектов и сопутствующего выделения памяти. Или уже с самого начала вы могли после получения line сразу сформировать std::string_view line_view = line; и дальше работать исключительно с line_view. Это, однако, не избавит вас от выделения памяти при инициализации std::istringstream и внутри std::istringstream. Здесь бы бы полезен парсер для std::string_view, но готового в стандартной библиотеке нет (кроме sscanf). Сама стандартная библиотека еще толком не перешла на использование std::string_view. Ваше vertices.push_back({ x, y, z, 1.0f }); это тоже потенциально - ненужное копирование. Возможно, что лучше vertices.emplace_back(x, y, z, 1.0); но это уже зависит от свойств Math::Vector4.

Комментариев нет:

Отправить комментарий