C++ 流解析算法的速度问题

C++ 流解析算法的速度问题,c++,visual-studio-2010,optimization,C++,Visual Studio 2010,Optimization,我已经编写了一个波阵面Obj解析器类,用于将Obj模型导入到我的OpenGL项目中。我在调试模式下测试了这个类,发现它的速度太慢了 代码是有效的,我做了一些明显的调整,以确保它尽可能的高效 尽管如此,加载我的测试文件,一个12mb的obj文件,它运行到大约330000行文本,需要花费一分钟来解析 沮丧的是,我有一个谷歌,果然 这个在gamedev.net上发布查询的家伙只是在Visual Studio IDE和whammo之外的发布模式下运行他的算法,性能可以接受。这也适用于我,我的~70秒缩短

我已经编写了一个波阵面Obj解析器类,用于将Obj模型导入到我的OpenGL项目中。我在调试模式下测试了这个类,发现它的速度太慢了

代码是有效的,我做了一些明显的调整,以确保它尽可能的高效

尽管如此,加载我的测试文件,一个12mb的obj文件,它运行到大约330000行文本,需要花费一分钟来解析

沮丧的是,我有一个谷歌,果然

这个在gamedev.net上发布查询的家伙只是在Visual Studio IDE和whammo之外的发布模式下运行他的算法,性能可以接受。这也适用于我,我的~70秒缩短为~3秒

我对算法进行了一些分析,瓶颈出现在对std::getline的调用中,如下所示:

sstream >> sToken;
其中,sstream是std::stringstream,sToken是std::string(预留空间)

问题

为什么IDE在运行我的解析算法(即使在发布模式下)时速度如此之慢令人难以置信?在通过IDE运行代码时,我能做些什么来加快速度(F5-运行项目)?这使得调试速度慢得不可思议。IDE是将代码/钩子注入到可执行文件中以便在IDE中运行,还是可以将其归因于缓存未命中或其他原因

优化

我对文件进行了两次遍历,在第一次遍历时,我只计算令牌类型,这样我就可以保留空间(而不是迭代地增加存储顶点、法线、texcoords、面等的向量)

第一次通过的成本很低(在调试模式下约为8秒,在IDE之外的发布模式下约为0.3秒),并且节省了大量的效率(将解析时间从调试模式下的约180秒减少到约60秒)

我还将整个文件读入一个stringstream,以便将磁盘访问排除在等式之外:

// Read entire file from disk into memory
fstream stream;
stringstream sstream;
stream.open( m_sFilename.c_str(), std::ios::in );
sstream << stream.rdbuf();
stream.close();

STL是以这样一种方式编写的,以便期望编译器对许多小函数进行大量的内联。尽管调试器允许您进入所有精彩的抽象层,但在调试模式下,您需要为此付出高昂的代价,因为它不能内联任何内容


通常我不会给出以下建议,但在解析OBJ文件的上下文中,我建议扔掉STL并依赖老式的
fscanf
语句。在调试过程中,您会发现一个显著的改进,甚至在发布模式中,速度也有明显的提高。

这个问题原来是对VisualStudioIDE操作方式的误解

无论您是在调试还是发布版本中,按F5都会在调试模式下运行

我了解了Ctrl+F5是如何将调试器从等式中去掉的(但只有在运行发布版本时,这样做时才会看到速度提高)


我还了解到,在这种情况下,stdio可能是一个更好的解决方案。我将不得不重写我的算法,按照建议使用fscanf,并在这里报告我的发现,尽管我对这个想法感到畏缩。

也许映射文件会有所帮助。通过“在IDE中运行它”,你的意思是在调试器下运行,还是用Ctrl-F5启动它也有同样的问题?此外,当您在IDE之外运行时,您是使用相同的二进制文件还是使用不同的版本,即使两者都是“发布”版本,编译器选项也可能存在一些差异?这可能与您报告的速度减慢无关,但是代码
while(sstream.good())
不是一个好主意。以这种方式测试
.good()
.eof()
的I/O循环是一个错误。当然它很慢,这是一个调试构建。在调试版本中转储一个大数据集,用一个小数据集进行测试,依靠发布版本来处理一个大数据集是没有意义的。blastfurne-.good()在用代码分析算法时不会成为瓶颈。你能解释一下为什么你认为这是个坏主意吗?哦,刚刚找到你的链接,别担心STL提示很有趣,尽管不得不用stdio库重写让我呻吟!计算代币以保留向量大小可以显著提高速度。这意味着它们不必随着增长而调整大小。结果不言而喻,在这一点上,我不同意你的观点。如果我删除第一个过程,第二个过程需要三倍的时间。如果删除第一个过程,在发布构建期间是否需要三倍的时间?你说在调试构建过程中花费的时间是原来的3倍。是的,在发布构建过程中仍然需要更长的时间。我会编辑我的答案,谢谢你教我一些新东西!
// Read entire file from disk into memory
fstream stream;
stringstream sstream;
stream.open( m_sFilename.c_str(), std::ios::in );
sstream << stream.rdbuf();
stream.close();
sLineBuffer.reserve( 100 );
sToken.reserve(10);  // etc