objモデルをOpenGLプロジェクトにインポートするために、Wavefront Objパーサークラスを作成しました。私はクラスをデバッグモードでテストしたところ、それは耐え難いほど遅いことがわかった。ストリーム解析アルゴリズムの速度問題
コードは機能していて、合理的に効率的だったことを確認するために、わかりやすく調整しました。
まだ、私のテストファイルをロードすると、およそ330,000行のテキストに実行される12MBのobjファイルが解析に1分以上かかりました。
私はGoogleを持っていましたが、確かに、I wasn't the first person to run into this problemでした。
彼の質問をgamedev.netに投稿したこの男は、単にリリースモードで、Visual Studio IDEの外で許容可能なパフォーマンスを発揮したアルゴリズムを実行しました。これも私のために働いた、私の〜70秒は〜3秒に縮小されました。
私は、アルゴリズムのいくつかのプロファイリングをした、とボトルネックは::はstdへの呼び出しでのgetlineあり、中に以下:
sstream提供ははstd ::にstringstreamで、STOKENがSTDであるsstream >> sToken;
::文字列(スペースがあらかじめ予約されている)
質問
なぜIDEが(でも、リリースモードで)私の構文解析アルゴリズムを実行している時とても信じられないほど遅いです - と私はIDEによって、コードを実行するときに、これをスピードアップするために何かできること(F5があります - プロジェクトを実行する)?これはデバッギングを非常に遅くしています。 IDEからIDEを実行するための実行可能コードにコード/フックを挿入しているのですか、これをキャッシュミスなどに置くことができますか?
最適化
私は、ファイルを2回通過を行うには、パス1に、私はちょうどトークンの種類を数える - 私はスペースを確保することができるように(というよりも、繰り返しの頂点を保存するベクトルを成長させ、法線、texcoords 、この最初のパスコストはほとんど(〜8デバッグモードで秒、または〜IDE外でリリースモードで0.3秒)と効率の節約は巨大であるが、(
sLineBuffer.reserve(100);
sToken.reserve(10);
while(sstream.good())
{
sstream >> sToken;
getline(sstream, sLineBuffer);
if(sToken.compare("f") == 0)
nFaces ++;
else if(sToken.compare("v") == 0)
nVertices ++;
else if(sToken.compare("vn") == 0)
nNormals ++;
else if(sToken.compare("vt") == 0)
nTextures ++;
else if(sToken.compare("g") == 0)
nGroups ++;
}
m_Vertices.reserve(nVertices);
m_Normals.reserve(nNormals);
m_TexCoords.reserve(nTextures);
m_Faces.reserve(nFaces);
m_Groups.reserve(nGroups);
)などに直面していることは〜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();
をまた、可能な場合、アルゴリズムを通じて、私はSTDのためのスペースを確保しようとする::前もって文字列、彼らはキャラクターごとにリサイズされていないよう:
sLineBuffer.reserve(100);
sToken.reserve(10); // etc
おそらくファイルをmmappingすると役立つ可能性があります。 – mfontanini
「IDEで実行する」とは、デバッガの下にあるのでしょうか、Ctrl-F5で起動するのと同じ問題がありますか?また、IDEの外で実行する場合、同じバイナリを使用していますか、どちらが「リリース」ビルドであってもコンパイラオプションに多少の違いが生じる可能性があります。 –
これはおそらくあなたが報告している減速とは関係ありませんが、while(sstream.good())というコードは良い考えではありません。そのように '.good()'や '.eof()'をテストするI/Oループは[悪い習慣]です(http://stackoverflow.com/questions/4324441)。 – Blastfurnace