C ++ Улучшить файл карты памяти

0

Так что еще раз я встретил препятствие, которое я не могу пройти! Я пытаюсь разобрать, загрузить файл obj для OpenGL!

Я преуспел, но он очень медленный (используется ifstream). Итак, теперь я копирую файл из памяти и разбираюсь там (очень быстро загружается в память!).

Проблема в том, что я не могу понять, как сохранить скорость даже при ее анализе!

Текущий код:

HANDLE file = CreateFile((LPCSTR)loc.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(file == INVALID_HANDLE_VALUE) { /* Error handling code! */ }
HANDLE file2 = CreateFileMapping(file, NULL, PAGE_READONLY, NULL, NULL, (LPCSTR)"CurrentParsingOBJ");
VOID* mappedData = MapViewOfFile(file2, FILE_MAP_READ, 0, 0, NULL);
const char* data = new(mappedData) char[];

int i = 0;
bool v = false, vn = false, vt = false;
while(*(data + i) != '\0')
{
    if(*(data + i) == '\n') { v = false; vn = false; vt = false; ++i; continue; }
    if((*(data + i) == 'v' && *(data + i + 1) == ' ') || v)
    {
        int a = 0;
        int p = 0;
        int pp = 0;
        v = true;

    }
    ++i;
}
//Free Mapped Data!
if(UnmapViewOfFile(mappedData) == NULL) { /* Error handling code! */ }
mappedData = NULL;
data = NULL;

Пока это очень хорошая скорость! Но я не могу понять, как его разобрать и поддерживать скорость! Я пробовал много решений, но все они приводили к неприемлемой скорости!

Вот как я делаю это с ifstream (я хотел бы загрузить ту же структуру OBJData, что и здесь, в версии с отображением памяти!):

std::ifstream stream(loc);
if(stream.is_open())
{
    for(std::string line; std::getline(stream, line);)
    {
        if( StringUtil::StringStartsWith(line, "v " ) )
        {
            Vector3f vec = Vector3f((float)atof((StringUtil::Split(line, ' ')[1])->c_str()), (float)atof((StringUtil::Split(line, ' ')[2])->c_str()), (float)atof((StringUtil::Split(line, ' ')[3])->c_str()));
            d->V.push_back(vec);
        }else if( StringUtil::StringStartsWith(line, "vn " ) )
        {
            Vector3f vec = Vector3f((float)atof((StringUtil::Split(line, ' ')[1])->c_str()), (float)atof((StringUtil::Split(line, ' ')[2])->c_str()), (float)atof((StringUtil::Split(line, ' ')[3])->c_str()));
            d->VN.push_back(vec);
        }else if( StringUtil::StringStartsWith(line, "vt ") )
        {
            Vector3f vec = Vector3f((float)atof((StringUtil::Split(line, ' ')[1])->c_str()), (float)atof((StringUtil::Split(line, ' ')[2])->c_str()), 0.0F);
            d->VT.push_back(vec);
        }else if( StringUtil::StringStartsWith(line, "f ") )
        {
            Vector3f vert = Vector3f( (float)atof(StringUtil::Split( StringUtil::Split(line, ' ')[1]->c_str(), '/' )[0]->c_str()),  (float)atof(StringUtil::Split( StringUtil::Split(line, ' ')[2]->c_str(), '/' )[0]->c_str()),  (float)atof(StringUtil::Split( StringUtil::Split(line, ' ')[3]->c_str(), '/' )[0]->c_str()) );
            Vector3f norms = Vector3f( (float)atof(StringUtil::Split( StringUtil::Split(line, ' ')[1]->c_str(), '/' )[2]->c_str()),  (float)atof(StringUtil::Split( StringUtil::Split(line, ' ')[2]->c_str(), '/' )[2]->c_str()),  (float)atof(StringUtil::Split( StringUtil::Split(line, ' ')[3]->c_str(), '/' )[2]->c_str()) );
            Vector3f textures = Vector3f( (float)atof(StringUtil::Split( StringUtil::Split(line, ' ')[1]->c_str(), '/' )[1]->c_str()),   (float)atof(StringUtil::Split( StringUtil::Split(line, ' ')[2]->c_str(), '/' )[1]->c_str()),   (float)atof(StringUtil::Split( StringUtil::Split(line, ' ')[3]->c_str(), '/' )[1]->c_str()) );
            d->F.push_back(OBJFace(vert, norms, textures));
        }
    }
}else { /* Error handling code! */ }
stream.close();

Вышеприведенная версия занимает waaay до 1 минуты для больших объектов!

Итак, мой вопрос: как бы я разобрал "Memory-mapped Version" в минимальное время! И загрузите ту же структуру OBJData, что и в более медленной версии!

  • 1
    Покажите нам небольшой пример ввода.
  • 0
    В скором времени я опубликую для вас код, который, я надеюсь, объяснит больше, чем мои описания.
Показать ещё 4 комментария
Теги:
performance
parsing
memory
map

1 ответ

-2

Если вы разбираете много и/или больших файлов или если вы разбираете файл в первый раз, то вы, скорее всего, привязаны к вводу/выводу, и может потребоваться предварительная выборка. Например, вы можете запустить параллельный поток, который проходит через файл с отображением памяти, чтобы извлечь его с диска. В С++ 11 (не тестировалось):

std::thread prefetch ([data,size]() {
  volatile char sink = 0;  // Volatile should prevent the compiler from optimizing away.
  for (char* pt = data, end = data + size; pt < end; pt += 1024) sink = *pt;
});
// ... Your parser here ...
prefetch.join();

(Linux имеет флаг MAP_POPULATE для предварительной выборки отображения).

  • 0
    «Использование указателя будет немного быстрее, чем использование индекса»? Добро пожаловать, мистер Пауэрс. Сейчас 2013 год. Вы спите с 1974 года. У нас есть настоящие компиляторы.
  • 0
    @Jerry: я не сплю так долго, но для данного кода индекс действительно так же эффективен, как указатель (протестирован с GCC), спасибо.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню