0

According to this article, using std::move avoids copy,thus improve function performance. I have tested in linux with vscode + gcc9.4, the results not comply with what the article said.

#include <iostream>
#include <chrono>

template <typename T> 
void swap1(T& a, T& b)
{
    T tmp(a);   // now we have two copies of a
    a = b;      // now we have two copies of b
    b = tmp;    // now we have two copies of tmp (aka a)
}

template <typename T> 
void swap2(T& a, T& b)
{
    T tmp(std::move(a));
    a = std::move(b);   
    b = std::move(tmp);
}

int main()
{
  int a = 10;
  int b = 20;

  int num = 100000;
  const auto& time_t1 = std::chrono::steady_clock::now();
  for(int i = 0; i < num; i++){
     swap1(a,b);
  }

  const auto& time_t2 = std::chrono::steady_clock::now();
  double time_lf = (time_t2 - time_t1).count() / 1000000.0;
  std::cout<<"time_lf: "<<time_lf<<std::endl;


  const auto& time_t3 = std::chrono::steady_clock::now();
  for(int i = 0; i < num; i++){
     swap2(a,b);
  }

  const auto& time_t4 = std::chrono::steady_clock::now();
  double time_move = (time_t4 - time_t3).count() / 1000000.0;
  std::cout<<"time_move: "<<time_move<<std::endl;

   return 0;
}

outputs are:

time_lf: 0.177079
time_move: 0.384381

why using std::move doesn't improve performance of function swap();

Marek R
  • 32,568
  • 6
  • 55
  • 140
hitbuyi
  • 11
  • 4
  • Compilers are very good at spotting ways to optimize your code. Look at the assembly output of your two swap functions and see how many copies are actually made. – Adrian Mole Jul 27 '22 at 02:27
  • 1
    That article says "Copying can be expensive." It doesn't say that copying is always expensive. Copying integers is not expensive. (As AdrianMole says, it doesn't even always happen.) Copy strings or vectors is expensive. Move semantics save copying overhead, which improves performance on objects for which copying is expensive. – rici Jul 27 '22 at 02:27
  • 1
    Maybe I'm missing something here, but I'm curious to know what's wrong with using `std::swap`. – paddy Jul 27 '22 at 02:31
  • @paddy They're probably doing it manually to have a "more visible" comparison of the two ways to swap. – Mona the Monad Jul 27 '22 at 03:06
  • Also, if you cannot or don't know how to get assembly output, Adrian is implying that `std::move` on something like an integer doesn't actually do anything special. It almost certainly ends up being a plain copy. If moving an integer actually meant making the original value 0 or something, that'd be a case of `std::move` being worse than a regular copy. – Mona the Monad Jul 27 '22 at 03:13
  • You want to see advantage of move schematics on `int` type? `int` move is equivalent to copy so your test is useless. You need something heavy, like none empty `std::vector` (preferably of heavy objects) to see any gain. For that reason voting to close as "not reproducible or caused by typo" (not perfect match for a reason, but close enough). – Marek R Jul 27 '22 at 15:53
  • 1
    See [`std::move()` doesn't actually move anything](https://stackoverflow.com/a/27026280/12002570) – Jason Jul 27 '22 at 16:03

1 Answers1

1

std::move doesn't do anything itself, it only gives the compiler permission to use move semantic when it can.

That means for objects the move constructor or move assignment operator is invoked instead of the copy constructor or copy assignment operator. But fundamental types are not classes that have a move constructor or move assignment operator.

Move semantic on the lowest level only makes sense if you have a pointer. Instead of copying what the pointer points to you can copy the address and thereby "move" the data. You are moving the ownership of the pointed to data from one object to the other.

So for swap to be faster you need to use it on classes that internally use pointers and provide move construction and move assignment operator. For example std::string or std::vector. Classes like std::array that don't use pointers don't benefit from swap either.

For your case of swapping int the swap1 and swap2 function will have identical code.

PS: Your testcase is also totally flawed. The compiler can easily see that swap exchanges a and b so it only has to do that once if the count is odd and nothing if it's even: https://godbolt.org/z/Ef3eveMTn If you compile your code you will see the test loops disappear completely since num is even.

Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42