Created
October 4, 2012 10:23
-
-
Save martinmoene/3832753 to your computer and use it in GitHub Desktop.
Variations on Performance test of X& operator=(X?)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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