0

I have a situation where profiling has shown that a large structure is taking a significant time to be copied:

std::vector<LargeStruct> allOutputs;
std::vector<LargeStruct> thisOutput(getResultOfOperation());    

// catenate results to allOutputs
std::copy(thisOutput.begin(), thisOutput.end(), std::back_inserter(allOutputs));

My first instinct was to try changing copy to move:

std::move(thisOutput.begin(), thisOutput.end(), std::back_inserter(allOutputs));

However this didn't yield any performance increase, presumably because one of the members of LargeStruct doesn't have a move constructor/assignment operator.

The question is: how can I diagnose this to find out which member is causing the problem?

EDIT:

Does std::is_move_constructible help in this case? It sounds from this post that it doesn't

Community
  • 1
  • 1
the_mandrill
  • 29,792
  • 6
  • 64
  • 93
  • 1
    Use a profiler? That said, is this structure really so big that one cannot tell which members are more likely right away? – R. Martinho Fernandes Feb 11 '14 at 13:05
  • Already using the profiler, but it's showing a large amount of time in the copy constructor, which doesn't help identify why. The structure itself isn't big, but it contains arrays of other structs, which may contain further structs – the_mandrill Feb 11 '14 at 13:08
  • Have you confirmed the type has a `&&` constructor or not? – Yakk - Adam Nevraumont Feb 11 '14 at 15:50
  • It doesn't, but I thought the compiler will generate one automatically if possible. Problem is that you can't step into it in the debugger or detect whether one was actually generated. – the_mandrill Feb 11 '14 at 16:05

1 Answers1

1

You can probably get the compiler to give you a useful diagnostic by forcing the type to be move only. If you suppress the copy constructor, the compiler will have to use the move constructor, and if it can't generate it, it will probably tell you why. You can suppress the copy constructor by either explicitly suppressing the copy operations:

struct LargeStruct {
    LargeStruct(LargeStruct const &) = delete;
    LargeStruct &operator=(LargeStruct const &) = delete;
    // ...
};

Or you could add a move-only member to your class:

struct LargeStruct {
    unique_ptr<char> dummy;
    // ...
};

Either of these should force LargeStruct to be a move-only type and produce a diagnostic if the move operations can't be generated. If the error messages aren't informative, you could try the same test on each (nonstatic) data member of LargeStruct to find out which is/are copy-only.

Adam H. Peterson
  • 4,511
  • 20
  • 28