[SOLVED] c++ 11, Moving slower than copying?!?
-
Hi all, some days ago I've started testing some of the c++11 features, in order to have a better understanding of the language. One of this test was benchmarking the execution of a piece of code that use std::move instead of copy, both by filling a vector without memory reserved, so vector must call move to move its elements, and the other to copy object; What i've see is that moving vectors is extremely efficient instead of copying it, instead for my class is a bit slower.. Searching on Internet one possibility is that the code is optimized by the compiler using copying elision, that is seems more efficient.. So my question is how i can benchmark better the code? There is something wrong with my move constructor? Why in my test moving is slower??
@//System
#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <QTime>//user
using namespace std;
class Constructors
{
public:
//Cnstructors
Constructors() : m_TestMember{0}{} // Empty Constructor
Constructors(int value)
{
m_TestMember = value +5;
m_TestMember1 = m_TestMember + 5;
m_TestMember2 = m_TestMember1 + 5;
m_TestMember3 = m_TestMember2 + 5;
m_TestMember4 = m_TestMember3 + 5;
} //Constructor
~Constructors()
{
// std::cout<<"destructing object..."<<std::endl;
} //Destructor
Constructors(const Constructors &c)
{
m_TestMember = c.m_TestMember;
m_TestMember1 = c.m_TestMember1;
m_TestMember2 = c.m_TestMember2;
m_TestMember3 = c.m_TestMember3;
m_TestMember4 = c.m_TestMember4;
// std::cout<<"Copying constructor..."<<std::endl;
} //Copy ConstructorConstructors & operator=(Constructors &c)
{
m_TestMember = c.m_TestMember;
m_TestMember1 = c.m_TestMember1;
m_TestMember2 = c.m_TestMember2;
m_TestMember3 = c.m_TestMember3;
m_TestMember4 = c.m_TestMember4;
std::cout<<"Copying constructor..."<<std::endl;
}Constructors(Constructors &&c)
{
this->m_TestMember = c.m_TestMember;
this->m_TestMember1 = c.m_TestMember1;
this->m_TestMember2 = c.m_TestMember2;
this->m_TestMember3 = c.m_TestMember3;
this->m_TestMember4 = c.m_TestMember4;c.m_TestMember = 0; c.m_TestMember1 = 0; c.m_TestMember2 = 0; c.m_TestMember3 = 0; c.m_TestMember4 = 0; // std::cout<<"Moving constructor..."<<std::endl;
} //Move Constructor
Constructors & operator=(Constructors &&c)
{
m_TestMember = std::move(c.m_TestMember);
m_TestMember1 = std::move(c.m_TestMember1);
m_TestMember2 = std::move(c.m_TestMember2);
m_TestMember3 = std::move(c.m_TestMember3);
m_TestMember4 = std::move(c.m_TestMember4);c.m_TestMember = 0; c.m_TestMember1 = 0; c.m_TestMember2 = 0; c.m_TestMember3 = 0; c.m_TestMember4 = 0; // std::cout<<"Moving assignment..."<<std::endl; return *this;
}
private:
int m_TestMember;
int m_TestMember1;
int m_TestMember2;
int m_TestMember3;
int m_TestMember4;
};
class ConstructorsB
{
public:
//Cnstructors
ConstructorsB() : m_TestMember{0}{} // Empty Constructor
ConstructorsB(int value)
{
m_TestMember = value +5;
m_TestMember1 = m_TestMember + 5;
m_TestMember2 = m_TestMember1 + 5;
m_TestMember3 = m_TestMember3 + 5;
m_TestMember4 = m_TestMember3 + 5;
} //Constructor
~ConstructorsB() {
// std::cout<<"destructing object..."<<std::endl;
} //Destructor
ConstructorsB(const ConstructorsB &c)
{
m_TestMember = c.m_TestMember;
m_TestMember1 = c.m_TestMember1;
m_TestMember2 = c.m_TestMember2;
m_TestMember3 = c.m_TestMember3;
m_TestMember4 = c.m_TestMember4;
// std::cout<<"Copying constructor..."<<std::endl;
} //Copy Constructorprivate:
int m_TestMember;
int m_TestMember1;
int m_TestMember2;
int m_TestMember3;
int m_TestMember4;
};//! moving bendhmark, return number of millsec elapsed
//! Note: Moving it's much more faster when assign object or initialize them
//! instead of move in vector !
float scopedMovingBenchmark(bool reserving, const int &elements)
{
QTime timer;vector<Constructors> constructorVector;
vector<Constructors> constructorVector2;//! reserving half the time of execution..
//! it avoid continuos moving, destructing
if(reserving)
constructorVector.reserve(elements);Constructors testClass{10};
timer.start();
for(int i{0}; i != elements; i++)
constructorVector.push_back(testClass);
// int a{std::move(10)};// constructorVector2 = std::move(constructorVector);
return timer.elapsed()/1000.0f;
}//! copying bendhmark, return number of millsec elapsed
float scopedCopyingBenchmark(bool reserving, const int &elements)
{
QTime timer;vector<ConstructorsB> constructorVector;
vector<ConstructorsB> constructorVector2{};//! reserving half the time of execution..
//! it avoid continuos moving, destructing and copying
if(reserving)
constructorVector.reserve(elements);ConstructorsB testClass{10};
timer.start();
for(int i{0}; i != elements; i++)
constructorVector.push_back(testClass);
// int a = int {10};// constructorVector2 = constructorVector;
return timer.elapsed()/1000.0f;
}int main()
{
const int elements{1000000};
const bool reserve{false};float movingMedia{0.0f}; float copyingMedia{0.0f}; for(int i{0}; i!=5; i++) movingMedia += scopedMovingBenchmark(reserve ,elements); for(int i{0}; i!=5; i++) copyingMedia += scopedCopyingBenchmark(reserve ,elements); movingMedia /= 5.0f; copyingMedia /= 5.0f; std::cout<<"moving time: "<<movingMedia<<endl; std::cout<<"copying time: "<<copyingMedia<<endl; std::cout<<"delta: "<<movingMedia - copyingMedia<<endl;
return 0;
}@
-
interresting, experiment with bigger iteration value:
@int main( int argc, char **argv )
{
const int elements{1000000};
const bool reserve{false};float movingMedia{0.0f}; float copyingMedia{0.0f};
double factor = 5;
if ( argc > 1 )
factor = atof( argv[1] );for(int i{0}; i < factor; i++) movingMedia += scopedMovingBenchmark(reserve ,elements); for(int i{0}; i < factor; i++) copyingMedia += scopedCopyingBenchmark(reserve ,elements); movingMedia /= factor; copyingMedia /= factor;
...
@ -
I think i found the problem: basically moving is made for heap allocated memory, so when copying it avoid continuous memory allocation. So modifying the variable m_TestMember to a pointer type and consequently all the related moving copying constructor, the code is more faster.