-3

Consider the following program. Why is move slower than copy? I thought that move semantics sped things up considerably when returning locals as rvalues from functions. Can you tell me why moving a large vector is slower than copying it. The benchmark for returning a shared_ptr is provided as a base case.

#include <iostream>
#include <vector>
#include <string>
#include <chrono>
using namespace std;

vector<int> getStringByCopy()
{
   vector<int> v;
   for (int x = 0; x< 15000000;x++)  v.push_back(x);
   return v;
}

vector<int>&& getStringByMove()
{
  vector<int> v;
  for (int x = 0; x< 15000000;x++)   v.push_back(x);
  return move(v);
}

shared_ptr<vector<int>> getStringByPointer()
{
   shared_ptr<vector<int>> v = make_shared<vector<int>>();
   for (int x = 0; x< 15000000;x++)   v->push_back(x);
   return v;
}
int main(int argc, const char * argv[]) {
   // insert code here...

   chrono::system_clock::time_point begin = chrono::system_clock::now();

   vector<int> v = getStringByCopy();

   chrono::system_clock::time_point end = chrono::system_clock::now();
   cout << v[0] << "copy took " << chrono::duration_cast<chrono::microseconds>(end - begin).count() << endl;;

   begin = chrono::system_clock::now();

   vector<int>&& m = getStringByMove();

   end = chrono::system_clock::now();
   cout << m[0] << "move took " << chrono::duration_cast<chrono::microseconds>(end - begin).count() << endl;;

   begin = chrono::system_clock::now();

   shared_ptr<vector<int>> sp = getStringByPointer();

   end = chrono::system_clock::now();
   cout << (*sp)[0] << "pointer took " << chrono::duration_cast<chrono::microseconds>(end - begin).count() << endl;

   return 0;
}

The output is:

0copy took 437043
0move took 462803
0pointer took 394549  
R Sahu
  • 204,454
  • 14
  • 159
  • 270
bc888
  • 141
  • 14
  • 1
    Probably because your benchmark is flawed. You don't have optimizations turned on (and if you did, the optimizer would effectively remove most of your code). You aren't doing a proper warmup. You aren't averaging many runs. The allocations of the first test might be done faster than the second test (the OS could pre-allocate some storage which the first test uses, but the second test needs more than what's available), and you're including those times in the test. etc. – Cornstalks Nov 13 '15 at 06:41
  • Possible duplicate of [Move-assignment slower than copy-assignment -- bug, feature, or unspecified?](http://stackoverflow.com/questions/25104021/move-assignment-slower-than-copy-assignment-bug-feature-or-unspecified) – Rahul Tripathi Nov 13 '15 at 06:42
  • 3
    This benchmark is worthless; your code has undefined behaviour. Make code correct, then optimise for speed. – Mankarse Nov 13 '15 at 06:42
  • getStringByMove is clearly incorrect. Thats all I could find in first 3 seconds. :) – Arunmu Nov 13 '15 at 06:45
  • What you are really timing is reallocation of vector. Try fixing its size before running. Also how many runs are you averaging across? Operating system vagaries may be getting in there. – graham.reeds Nov 13 '15 at 06:45
  • 2
    UB, that's ungood for benchmarking. – Cheers and hth. - Alf Nov 13 '15 at 06:47
  • 3
    Voted to close because it's meaningless to ask about the particular timing results of Undefined Behavior. – Cheers and hth. - Alf Nov 13 '15 at 06:48
  • `getStringByMove()` returns reference to an automatic object (object is destroyed before the function returns) . Also it doesn't attempt to move anything. `std::move` and `&&` don't mean "move" per se. – M.M Nov 13 '15 at 07:06
  • Just to follow this up - if all existing issues with the code are ignored, if the code is run in debug mode, std::move will be slower with a trivial type, unless the compiler has made the optimisation to change std::move to a cast rather than a function call (only GCC does this at time of writing). See: https://www.youtube.com/watch?v=ffFT-gIPCRE – metamorphosis Aug 31 '22 at 23:33

1 Answers1

1

Your method that is supposed to return per copy already return per move. If you return anything that were allocated on the stack per value in a method and return it, then you get a automatic move.

Vincent
  • 156
  • 1
  • 9
  • Assuming that the object has a move constructor (which vector does). also, copy-elision probably occurs – M.M Nov 13 '15 at 07:09