Skip to content

Instantly share code, notes, and snippets.

@martinmoene
Created October 4, 2012 10:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martinmoene/3832753 to your computer and use it in GitHub Desktop.
Save martinmoene/3832753 to your computer and use it in GitHub Desktop.
Variations on Performance test of X& operator=(X?)
/*
* TestOpAssign-variations-variations.cpp
*
* Created by Martin on 4 October 2012.
* Copyright 2012 Universiteit Leiden. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
// GCC: g++ -O2 -Wall -o TestOpAssign-variations.exe TestOpAssign-variations.cpp && TestOpAssign-variations
// VC2010: cl -O2 -W3 -nologo -EHsc TestOpAssign-variations.cpp && TestOpAssign-variations
// VC6: cl -O2 -W3 -DUSE_VOLATILE_MEMBER_DATA -nologo -EHsc -FAsc TestOpAssign-variations.cpp && TestOpAssign-variations
// VC6: cl -O2 -W3 -DTURN_OFF_LOOP_OPT -nologo -EHsc -FAsc TestOpAssign-variations.cpp && TestOpAssign-variations
// VC6: cl -Ob1 -W3 -nologo -EHsc -FAsc TestOpAssign-variations.cpp && TestOpAssign-variations
// -D-USE_VOLATILE_MEMBER_DATA
// -D-DTURN_OFF_LOOP_OPT
#include <iomanip>
#include <iostream>
#include <string>
#include <time.h>
#include <cstdlib> // for std::strtol()
template < typename T >
class Conventional
{
public:
typedef T value_type;
typedef Conventional<T> class_type;
Conventional( value_type const x = value_type() ) : v( x ) {}
Conventional( class_type const & other ) : v( other.v ) {}
// Conventional( class_type const volatile & other ) : v( other.v ) {}
class_type /*volatile*/ & operator=( class_type const /*volatile*/ & other ) /*volatile*/
{
v = other.v;
return *this;
}
#ifdef USE_VOLATILE_MEMBER_DATA
T volatile v;
#else
T v;
#endif
};
template < typename T >
class CopySwap
{
public:
typedef T value_type;
typedef CopySwap<T> class_type;
CopySwap( value_type const x = value_type() ) : v( x ) {}
CopySwap( class_type const & other ) : v( other.v ) {}
class_type & operator=( class_type other )
{
swap( *this, other );
return *this;
}
friend void swap( class_type & first, class_type & second )
{
using std::swap;
swap( first.v, second.v );
}
#ifdef USE_VOLATILE_MEMBER_DATA
T volatile v;
#else
T v;
#endif
};
#define ASSIGN( x, y ) \
x = y; \
x = y; \
x = y; \
x = y; \
x = y; \
x = y; \
x = y; \
x = y; \
x = y; \
x = y;
const int mega = 1000000;
const int count_ms = 200 * CLOCKS_PER_SEC / 1000;
/*
* Turn on loop, common subexpression and register optimizations.
* - /Og
* - #pragma optimize("g"[,on|off])
*/
#ifdef TURN_OFF_LOOP_OPT
# pragma optimize("g", off)
#endif
template < typename X, typename Y >
int do_work_for( X & a, Y & b )
{
const clock_t te = clock() + count_ms;
int i = 0;
while ( clock() < te )
{
for( int j = 0; j < mega; ++j )
{
ASSIGN( a, b );
}
++i;
}
return i;
}
template < typename X, typename Y >
int do_work_while( X & a, Y & b )
{
const clock_t te = clock() + count_ms;
int i = 0;
while ( clock() < te )
{
int j = mega;
while( j > 0 )
{
ASSIGN( a, b );
--j;
}
++i;
}
return i;
}
template < typename X, typename Y >
int do_work_do_while( X & a, Y & b )
{
const clock_t te = clock() + count_ms;
int i = 0;
while ( clock() < te )
{
int j = mega;
do
{
ASSIGN( a, b );
--j;
}
while( j > 0 );
++i;
}
return i;
}
template < typename X, typename Y >
int do_work_goto( X & a, Y & b )
{
const clock_t te = clock() + count_ms;
int i = 0;
while ( clock() < te )
{
int j = mega;
top:
ASSIGN( a, b );
--j;
if ( j > 0 )
goto top;
++i;
}
return i;
}
template < typename X, typename Y >
int do_work_volatile( X & a, Y & b )
{
const clock_t te = clock() + count_ms;
int i = 0;
while ( clock() < te )
{
for( int j = 0; j < mega; ++j )
{
volatile int x=0; x;
ASSIGN( a, b );
}
++i;
}
return i;
}
inline const std::string to_string( const long x, const int base = 10 )
{
char buf[65];
return _ltoa( x, buf, base );
}
std::string compiler_name()
{
#if defined( _MSC_VER )
return "MS VC " + to_string(_MSC_VER / 100 - 6) + "." + to_string(_MSC_VER % 100) ;
#elif defined( __GNUC__ )
return "GCC " + to_string(__GNUC__) + "." + to_string(__GNUC_MINOR__) + "." + to_string(__GNUC_PATCHLEVEL__) ;
// return std::string("GCC") + " " + to_string(__GNUC__) + "." + to_string(__GNUC_MINOR__) + "." + to_string(__GNUC_PATCHLEVEL__) ;
#endif
return "Unknown";
}
int main()
{
const double cps = CLOCKS_PER_SEC;
std::cout <<
"\nPerformance test of X& operator=(X?)." <<
"\n"
"\nCompiler: " << compiler_name() << std::endl;
clock_t t0 = 0;
clock_t t1 = 0;
int k = 0;
t0 = clock();
{
double a;
double b = 1.23;
k = do_work_for( a, b );
}
t1 = clock();
std::cout << std::setprecision(2) <<
"\tdouble - for: " << 1e2 * ((t1-t0)/cps)/k << " ns" << std::endl;
t0 = clock();
{
Conventional<double> a;
Conventional<double> b;
k = do_work_for( a, b );
}
t1 = clock();
std::cout << std::setprecision(2) <<
"\tConventional - for: " << 1e2 * ((t1-t0)/cps)/k << " ns" << std::endl;
t0 = clock();
{
Conventional<double> a;
Conventional<double> b;
k = do_work_while( a, b );
}
t1 = clock();
std::cout << std::setprecision(2) <<
"\tConventional - while: " << 1e2 * ((t1-t0)/cps)/k << " ns" << std::endl;
t0 = clock();
{
Conventional<double> a;
Conventional<double> b;
k = do_work_do_while( a, b );
}
t1 = clock();
std::cout << std::setprecision(2) <<
"\tConventional - do-while: " << 1e2 * ((t1-t0)/cps)/k << " ns" << std::endl;
t0 = clock();
{
Conventional<double> a;
Conventional<double> b;
k = do_work_goto( a, b );
}
t1 = clock();
std::cout << std::setprecision(2) <<
"\tConventional - goto: " << 1e2 * ((t1-t0)/cps)/k << " ns" << std::endl;
t0 = clock();
{
Conventional<double> a;
Conventional<double> b;
k = do_work_volatile( a, b );
}
t1 = clock();
std::cout << std::setprecision(2) <<
"\tConventional - volatile: " << 1e2 * ((t1-t0)/cps)/k << " ns" << std::endl;
t0 = clock();
{
CopySwap<double> a;
CopySwap<double> b;
k = do_work_for( a, b );
}
t1 = clock();
std::cout << std::setprecision(2) <<
"\tCopy-swap: " << 1e2 * ((t1-t0)/cps)/k << " ns" <<
std::endl;
return 0; // VC6
}
/*
* end of file
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment