C++改进内存映射obj文件
C++ Improve memory-map obj file
所以我又遇到了一个无法通过的障碍!我正在尝试解析,为OpenGL加载一个obj文件!
我已经成功了,但速度很慢(使用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) != ' ')
{
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();
对于较大的对象,上述版本需要长达1分钟的时间!
我的问题是:如何在最短的时间内解析"内存映射版本"!并加载与较慢版本中相同的OBJData结构
如果您正在解析大量和/或大型文件,或者如果您是第一次解析文件,那么您很可能是I/O绑定的,预取可能会有所帮助。例如,您可能想要启动一个并行线程来遍历内存映射文件,以便从磁盘中获取该文件。在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标志)。
相关文章:
- 如何在.obj文件上运行IlDasm?
- 在 opengl 中渲染 obj 文件时出现黑窗口
- 使用 Boost.Spirit 解析具有混合数据类型的 OBJ 文件?
- 正在读取 obj 文件!(指数)
- OBJ 文件C++与 ubuntu 问题
- 移植DXUT SDKMesh以导入OBJ文件,在哪里添加纹理坐标和索引
- 将多个网格放入单个波前 OBJ 文件中
- Python 脚本到 c .obj 文件
- CMake:如何在包含的标头更改时自动重建 .obj 文件
- 如何读取 .obj 文件?
- 合并 c++ obj 文件以进行 C 链接
- 我无法在 Flutter 桌面嵌入项目(在 Visual Studio 上)中创建 obj 文件
- 如何在没有CRT的情况下链接OBJ文件
- GCC.obj文件输出不具有确定性(.debug_info,PROGPITS部分)
- 将 Obj 文件导入 vtk
- Visual Studio C++ Copy obj 文件而不是编译
- 在C/C (JIT)中,在运行时加载并链接OBJ文件
- 尝试加载DirectX 11中的obj文件时,向量下标
- 用Assimp导入OBJ文件
- 错误LNK2005结构已在.obj文件中定义