1

Reason for re-posting:

Originally I got only one reply, that only pointed out that the title was exaggerated. Hence trying again, maybe more people will see this question this time as I really do not know where else to look... I will make sure to delete the original question to avoid duplication, and keep this new one instead. I'm not trying to spam the forum.

Feel free to remove the text above upon editing, I just wanted to explain why I'm re-posting - but it's not really a part of the question.

So, the original question was:

I have a few functions in my program that run extremely slow in Debug mode, in Visual Studio Community, 2015. They are functions to "index" the verts of 3D models.

Normally, I'm prepared for Debug mode to be a little slower, maybe 2 -3 times slower. But...

In Release mode, the program starts and indexes the models in about 2 - 3 seconds. Perfect.

In Debug mode however, it takes over 7 MINUTES for my program to actually respond, to start rendering and take input. It is stuck indexing one model for over seven minutes. During this time the program is completely froze.

The same model loads and indexes in "Release" mode in less than 3 seconds. How is it possible that it takes so unbelievably long in Debug?

Both Debug & Release modes are the standard out of the box modes. I don't recall changing any of the settings in either of them.

Here's the code that's slowing the program down in Debug mode:

// Main Indexer Function
void indexVBO_TBN(
std::vector<glm::vec3> &in_vertices,
std::vector<glm::vec2> &in_uvs,
std::vector<glm::vec3> &in_normals,
std::vector<glm::vec3> &in_tangents,
std::vector<glm::vec3> &in_bitangents,

std::vector<unsigned short> & out_indices,
std::vector<glm::vec3> &out_vertices,
std::vector<glm::vec2> &out_uvs,
std::vector<glm::vec3> &out_normals,
std::vector<glm::vec3> &out_tangents,
std::vector<glm::vec3> &out_bitangents){

int count = 0;

// For each input vertex
for (unsigned int i = 0; i < in_vertices.size(); i++) {

    // Try to find a similar vertex in out_vertices, out_uvs, out_normals, out_tangents & out_bitangents
    unsigned int index;
    bool found = getSimilarVertexIndex(in_vertices[i], in_uvs[i], in_normals[i], out_vertices, out_uvs, out_normals, index);

    if (found) {
        // A similar vertex is already in the VBO, use it instead !
        out_indices.push_back(unsigned short(index));

        // Average the tangents and the bitangents
        out_tangents[index] += in_tangents[i];
        out_bitangents[index] += in_bitangents[i];
    } else {
        // If not, it needs to be added in the output data.
        out_vertices.push_back(in_vertices[i]);
        out_uvs.push_back(in_uvs[i]);
        out_normals.push_back(in_normals[i]);
        out_tangents.push_back(in_tangents[i]);
        out_bitangents.push_back(in_bitangents[i]);
        out_indices.push_back((unsigned short)out_vertices.size() - 1);
    }
    count++;
}
}

And then the 2 little "helper" functions it uses (isNear() and getSimilarVertexIndex()):

// Returns true if v1 can be considered equal to v2
bool is_near(float v1, float v2){
return fabs( v1-v2 ) < 0.01f;
}


bool getSimilarVertexIndex( glm::vec3 &in_vertex, glm::vec2 &in_uv, glm::vec3 &in_normal,
                        std::vector<glm::vec3> &out_vertices, std::vector<glm::vec2> &out_uvs, std::vector<glm::vec3> &out_normals,
                        unsigned int &result){
// Lame linear search
for (unsigned int i = 0; i < out_vertices.size(); i++) {

    if (is_near(in_vertex.x, out_vertices[i].x) &&
        is_near(in_vertex.y, out_vertices[i].y) &&
        is_near(in_vertex.z, out_vertices[i].z) &&
        is_near(in_uv.x, out_uvs[i].x) &&
        is_near(in_uv.y, out_uvs[i].y) &&
        is_near(in_normal.x, out_normals[i].x) &&
        is_near(in_normal.y, out_normals[i].y) &&
        is_near(in_normal.z, out_normals[i].z)
        ) {
        result = i;
        return true;
    }
}
return false;
}

All credit for the functions above goes to: http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/

Could this be a:

  1. Visual Studio Community 2015 issue?
  2. VSC15 Debug Mode issue?
  3. Slow Code? (But it's only slow in Debug?!)
phuclv
  • 37,963
  • 15
  • 156
  • 475
GDN9
  • 329
  • 3
  • 15
  • 4
    It's slow because debug mode turns off the optimiser and enables a bunch of expensive runtime checks, such as out-of-bounds array indexing and memory overrun detection. – Roger Lipscombe Apr 09 '16 at 09:00
  • 5
    The core issue is that you simply have very unrealistic expectations of how fast the code *should* be in a Debug build. The optimizer is crucial to get performant STL collection code, it is turned off. The very nice iterator debugging feature greatly slows down code as well. You can trivially turn that off with _HAS_ITERATOR_DEBUGGING but, well, what would be the point. Simply use smaller datasets to debug your code. – Hans Passant Apr 09 '16 at 09:05
  • No. I was asking why a specific little bit of code was Significantly(!!!) slower (and not the rest of the program). Once the program goes past the mentioned code, it's not at all slow. It's just that one piece of code that runs slow in debug mode. Every other code I have runs fine before, and after executing the "indexing" function. – GDN9 Apr 09 '16 at 11:43
  • To all the other responses (Roger, Hans & Ice) especially Ice, thanks guys I'll be looking into it this afternoon! – GDN9 Apr 09 '16 at 11:45
  • I agree it's odd: 100x slow down is unusual, definitely worth investigating. How many iterations (how many time around the main loop)? What if you enable optimisation in debug mode? – david.pfx Apr 09 '16 at 14:22
  • Hey David, good idea, I forgot to post that info :-P The indexer function runs 46410 times for the second model (it's quite a high poly one) - the other models are very low poly and they "index" in just about the same length of time in Debug as in Release mode, but the one high poly mesh I have has 46410 un-indexed vertices and it takes the program over 7 minutes to do that one mesh, but only in Debug. Also, if I do enable Debug optimization (Maximize speed) and set "runtime check" to "default" it indexes in about 3 - 4 seconds (just a very little bit longer than release mode) – GDN9 Apr 09 '16 at 15:04

1 Answers1

5

There are multiple things that will/might be optimized:

  1. iterating a vector with indices [] is slower than using iterators; in debug, this certainly is not optimized away but in release it might
  2. additionally, accessing a vector via [] is slow because of runtime checks and debugging features when being in debug mode; this can be fairly easily seen when you go to the implementation of operator[]
  3. push_back and size might also have some additional checks than fall away when using release mode

So, my main guess would be that you use [] too much. It might be even faster in release when you change the iteration by means of using real iterators. So, instead of:

for (unsigned int i = 0; i < in_vertices.size(); i++) {

use:

for(auto& vertex : in_vertices)

This indirectly uses iterators. You could also explicitly write:

   for(auto vertexIt = in_vertices.begin(); vertexIt != in_vertices.end(); ++vertexIt)
   {
      auto& vertex = *vertexIt;

Obviously, this is longer code that seems less readable and has no practical advantage, unless you need the iterator for some other functions.

IceFire
  • 4,016
  • 2
  • 31
  • 51
  • Thanks ever so much for the help & extensive explanation Ice, will be investigating this afternoon! :) – GDN9 Apr 09 '16 at 11:50
  • Things that optimize away in (except in debug builds) aren't real problems, unless you have some real-time requirement for a debug build to be testable (e.g. a game or some video/audio stuff). Range-for loops are usually good style, so use them for that reason, but generally don't spend time changing your code *just* to optimize debug builds. (But if you do want to do that for some reason, `register auto &vertex` could help; the `register` [keyword does have an effect in gcc/clang `-O0`](https://stackoverflow.com/q/53366394)) – Peter Cordes Aug 12 '22 at 02:17