Skip to content

Instantly share code, notes, and snippets.

@NatalieWolfe
Last active February 22, 2022 18:53
Show Gist options
  • Save NatalieWolfe/7591946 to your computer and use it in GitHub Desktop.
Save NatalieWolfe/7591946 to your computer and use it in GitHub Desktop.
Testing various methods of passing functions around.
#include <chrono>
#include <cstdio>
#include <functional>
#include <iostream>
#include <string>
#include "test.h"
const int ITERATIONS = 1000000000; // 1 billion
using std::chrono::milliseconds;
typedef std::function< int(int,int) > Func;
class Timer {
public:
typedef std::chrono::high_resolution_clock clock;
typedef clock::rep rep;
typedef clock::duration duration;
typedef clock::time_point time_point;
time_point m_start;
duration m_duration;
public:
Timer( void ){}
~Timer( void ){}
void start( void ){
m_start = clock::now();
}
void stop( void ){
m_duration += clock::now() - m_start;
}
void reset( void ){
m_duration = duration::zero();
}
template< typename Duration >
rep getDurationIn( void ) const {
return std::chrono::duration_cast< Duration >( m_duration ).count();
}
};
void printTime( const std::string& function, Timer& timer ){
std::printf( "%-60s %6lldms.\n", function.c_str(), timer.getDurationIn< milliseconds >() );
}
#define TEST_LOOP( _timer, _func ) \
_timer.start(); \
for( int i = 0; i < ITERATIONS; ++i ){ \
_func( i, ITERATIONS - i ); \
} \
_timer.stop(); \
printTime( #_func, _timer ); \
_timer.reset();
void directTests( void ){
Timer timer;
Test tester;
std::cout << " --- Direct Call Tests --- " << std::endl;
TEST_LOOP( timer, testInline );
TEST_LOOP( timer, testExternal );
TEST_LOOP( timer, tester.testInlineMember );
TEST_LOOP( timer, tester.testExternalMember );
}
void pointerTests( void ){
Timer timer;
Test tester;
std::cout << " --- Pointer Call Tests --- " << std::endl;
TEST_LOOP( timer, (&testInline) );
TEST_LOOP( timer, (&testExternal) );
TEST_LOOP( timer, (tester.*(&Test::testInlineMember)) );
TEST_LOOP( timer, (tester.*(&Test::testExternalMember)) );
}
void stdFunctionTests( void ){
Timer timer;
Test tester;
std::cout << " --- std::function Call Tests --- " << std::endl;
Func funcTestInline = std::bind( &testInline, std::placeholders::_1, std::placeholders::_2 );
TEST_LOOP( timer, funcTestInline );
Func funcTestExternal = std::bind( &testExternal, std::placeholders::_1, std::placeholders::_2 );
TEST_LOOP( timer, funcTestExternal );
Func funcTestInlineMember = std::bind( &Test::testInlineMember, &tester, std::placeholders::_1, std::placeholders::_2 );
TEST_LOOP( timer, funcTestInlineMember );
Func funcTestExternalMember = std::bind( &Test::testExternalMember, &tester, std::placeholders::_1, std::placeholders::_2 );
TEST_LOOP( timer, funcTestExternalMember );
}
void lambdaTest( void ){
Timer timer;
Test tester;
std::cout << " --- Lambda Call Tests --- " << std::endl;
TEST_LOOP( timer, [&]( int a, int b ){ testInline( a, b ); } );
TEST_LOOP( timer, [&]( int a, int b ){ testExternal( a, b ); } );
TEST_LOOP( timer, [&]( int a, int b ){ tester.testInlineMember( a, b ); } );
TEST_LOOP( timer, [&]( int a, int b ){ tester.testExternalMember( a, b ); } );
}
int main( void ){
directTests();
pointerTests();
stdFunctionTests();
lambdaTest();
return 0;
}
natalie@WorkBook:funcSpeed$ g++ -std=c++11 test.cpp main.cpp -o funcSpeed && ./funcSpeed
--- Direct Call Tests ---
testInline 9317ms.
testExternal 9433ms.
tester.testInlineMember 9252ms.
tester.testExternalMember 9328ms.
--- Pointer Call Tests ---
(&testInline) 9401ms.
(&testExternal) 9642ms.
(tester.*(&Test::testInlineMember)) 9515ms.
(tester.*(&Test::testExternalMember)) 9382ms.
--- std::function Call Tests ---
funcTestInline 134101ms.
funcTestExternal 134797ms.
funcTestInlineMember 153735ms.
funcTestExternalMember 154390ms.
--- Lambda Call Tests ---
[&]( int a, int b ){ testInline( a, b ); } 10586ms.
[&]( int a, int b ){ testExternal( a, b ); } 10441ms.
[&]( int a, int b ){ tester.testInlineMember( a, b ); } 10996ms.
[&]( int a, int b ){ tester.testExternalMember( a, b ); } 11231ms.
natalie@WorkBook:funcSpeed$ g++ -std=c++11 -O3 test.cpp main.cpp -o funcSpeed && ./funcSpeed
--- Direct Call Tests ---
testInline 7693ms.
testExternal 8297ms.
tester.testInlineMember 7790ms.
tester.testExternalMember 7986ms.
--- Pointer Call Tests ---
(&testInline) 7617ms.
(&testExternal) 8031ms.
(tester.*(&Test::testInlineMember)) 7752ms.
(tester.*(&Test::testExternalMember)) 8119ms.
--- std::function Call Tests ---
funcTestInline 9866ms.
funcTestExternal 10128ms.
funcTestInlineMember 8346ms.
funcTestExternalMember 8331ms.
--- Lambda Call Tests ---
[&]( int a, int b ){ testInline( a, b ); } 7793ms.
[&]( int a, int b ){ testExternal( a, b ); } 8211ms.
[&]( int a, int b ){ tester.testInlineMember( a, b ); } 7957ms.
[&]( int a, int b ){ tester.testExternalMember( a, b ); } 7920ms.
#include "test.h"
int testExternal( int a, int b ){ TEST_BODY }
int Test::testExternalMember( int a, int b ){ TEST_BODY }
#pragma once
#include <cmath>
#define TEST_BODY \
int c = a * b; \
c *= a; \
double root = std::sqrt( (double)c ); \
return (int)root;
inline int testInline( int a, int b ){ TEST_BODY }
int testExternal( int a, int b );
class Test {
public:
int testInlineMember( int a, int b ){ TEST_BODY }
int testExternalMember( int a, int b );
}; // end class Test
@panovr
Copy link

panovr commented Sep 5, 2014

PS D:\Project\Algorithm\x64\Debug> .\DemystifyingCPPLambda.exe
--- Direct Call Tests ---
testInline 52372ms.
testExternal 52682ms.
tester.testInlineMember 54750ms.
tester.testExternalMember 52078ms.
--- Pointer Call Tests ---
(&testInline) 52115ms.
(&testExternal) 52568ms.
(tester.(&Test::testInlineMember)) 58176ms.
(tester.
(&Test::testExternalMember)) 52250ms.
--- std::function Call Tests ---
funcTestInline 104340ms.
funcTestExternal 104107ms.
funcTestInlineMember 249855ms.
funcTestExternalMember 246658ms.
--- Lambda Call Tests ---
[](int a, int b){ testInline(a, b); } 62448ms.
[](int a, int b){ testExternal(a, b); } 61446ms.
[&tester](int a, int b){ tester.testInlineMember(a, b); } 65371ms.
[&tester](int a, int b){ tester.testExternalMember(a, b); } 65389ms.

PS D:\Project\Algorithm\x64\Release> .\DemystifyingCPPLambda.exe
--- Direct Call Tests ---
testInline 0ms.
testExternal 0ms.
tester.testInlineMember 0ms.
tester.testExternalMember 0ms.
--- Pointer Call Tests ---
(&testInline) 0ms.
(&testExternal) 0ms.
(tester.(&Test::testInlineMember)) 0ms.
(tester.
(&Test::testExternalMember)) 0ms.
--- std::function Call Tests ---
funcTestInline 39927ms.
funcTestExternal 33924ms.
funcTestInlineMember 33837ms.
funcTestExternalMember 33877ms.
--- Lambda Call Tests ---
[](int a, int b){ testInline(a, b); } 0ms.
[](int a, int b){ testExternal(a, b); } 0ms.
[&tester](int a, int b){ tester.testInlineMember(a, b); } 0ms.
[&tester](int a, int b){ tester.testExternalMember(a, b); } 0ms.

OS: Windows 7 64bit
Compiler: Visual Studio 2013

It is strange that why some time durations are 0ms in release mode?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment