2013-11-22 2 views
0

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

У меня это получилось, но он очень медленный (используется 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, как здесь, в памяти, отображенные версии Aswell!):

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 минута для больших объектов!

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

+1

Покажите нам небольшой пример ввода. –

+0

Я выложу код для вас, чтобы посмотреть в ближайшее время, что, надеюсь, объяснит больше, чем мои описания. – GMasucci

+0

Что вы можете сделать, так это избежать копирования и выделения строк. Вы можете анализировать непосредственно из сопоставленной памяти. Это было бы сложнее, но быстрее. – zch

ответ

-1

Если вы разбираете много и/или большие файлы или если вы разбираете файл в первый раз, то вы, скорее всего, связаны с вводом-выводом и предварительной выборкой. Например, вы можете запустить параллельный поток, который проходит через файл с отображением памяти, чтобы извлечь его с диска. В C++ 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 flag для упреждения отображения).

+0

«Использование указателя будет немного быстрее, чем использование индекса»? Приветствую вас, мистер Пауэрс. Сейчас 2013. Вы спали с 1974 года. Сейчас у нас настоящие компиляторы. –

+0

@Jerry: Я не спал так долго, но для данного кода индекс действительно так же эффективен, как и указатель (проверенный с помощью GCC), спасибо. – ArtemGr

+0

Несомненно. Ваш ответ определенно улучшился. –

Смежные вопросы