#include <stdio.h>
#include <time.h>
#include "Receivers.hpp"
#include "Invoker.hpp"
#include "FastDelegate.h"
#include "srutil/delegate/delegate.hpp"
#include <fd/delegate.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
using namespace fastdelegate;
using namespace srutil;
extern int Zero;
template <typename T>
T prevent_optimization(T & d)
{
return *(&d + Zero);
}
template <class TInvoker, class TDelegate>
int measurement(TInvoker invoker, TDelegate const & d, bool invoke_or_copy)
{
#ifdef _DEBUG
const int iteration_count = 1000000;
#else
const int iteration_count = 10000000;
#endif
const int delegates_count = 10;
TDelegate delegates[delegates_count];
for (TDelegate *j = delegates; j != delegates + delegates_count; ++j)
*j = prevent_optimization(d);
clock_t before = clock();
if(invoke_or_copy)
{ // invocation test
for (int i = 0; i != iteration_count / delegates_count; ++i)
{
for (TDelegate *j = delegates; j != delegates + delegates_count; ++j)
invoker(*j);
}
}
else
{ // copy test
for (int k = 0; k != iteration_count / delegates_count; ++k)
{
for (TDelegate *j = delegates; j != delegates + delegates_count; ++j)
*j = prevent_optimization(d);
}
}
clock_t after = clock();
return (int)(after - before);
}
template<class TInvoker, class TFastDelegate, class TSRDelegate, class TJDelegate, class TBF, typename TFxn, typename T>
void compare_delegates(int method_id, int receiver_id,
TInvoker invoker, TFastDelegate dd, TSRDelegate sd, TJDelegate jd, TBF bf, TFxn, T *, bool invoke_or_copy)
{
printf("Test %d.%d: %s, %s: \n", method_id, receiver_id, typeid( T ).name(), typeid( TFxn ).name() );
printf("...DFD...");
int dd_time = measurement(invoker, dd, invoke_or_copy);
printf("...SFD...");
int sd_time = measurement(invoker, sd, invoke_or_copy);
printf("...JFD...");
int jd_time = measurement(invoker, jd, invoke_or_copy);
printf("...BF...");
int bf_time = measurement(invoker, bf, invoke_or_copy);
printf("\n");
double ddbf_rate = dd_time != 0 ? (double)bf_time / dd_time : -1.0;
double sdbf_rate = sd_time != 0 ? (double)bf_time / sd_time : -1.0;
double jdbf_rate = jd_time != 0 ? (double)bf_time / jd_time : -1.0;
printf("DFD: %5d / BF: %5d\t = %5.3f\n", dd_time, bf_time, ddbf_rate);
printf("SFD: %5d / BF: %5d\t = %5.3f\n", sd_time, bf_time, sdbf_rate);
printf("JFD: %5d / BF: %5d\t = %5.3f\n", jd_time, bf_time, jdbf_rate);
printf("\n");
}
#define DO_BANCHMARK_STATIC_0(METHOD_ID, RETURN_TYPE, INVOKE_OR_COPY) compare_delegates(METHOD_ID, 1, \
Invoker0<RETURN_TYPE>(), \
FastDelegate0<RETURN_TYPE>(Receiver1::method##METHOD_ID), \
delegate0<RETURN_TYPE>::from_function<Receiver1::method##METHOD_ID>(), \
fd::delegate0<RETURN_TYPE>(Receiver1::method##METHOD_ID), \
boost::function0<RETURN_TYPE>(Receiver1::method##METHOD_ID), \
Receiver1::method##METHOD_ID, \
(void *)0\
, INVOKE_OR_COPY \
);
#define DO_BANCHMARK_0_IMPL(METHOD_ID,RECEIVER_NUM,RETURN_TYPE, INVOKE_OR_COPY) compare_delegates(METHOD_ID, RECEIVER_NUM, \
Invoker0<RETURN_TYPE>(), \
FastDelegate0<RETURN_TYPE>(&r##RECEIVER_NUM, &Receiver##RECEIVER_NUM::method##METHOD_ID), \
delegate0<RETURN_TYPE>::from_method<Receiver1,&Receiver##RECEIVER_NUM::method##METHOD_ID>(&r##RECEIVER_NUM), \
fd::delegate0<RETURN_TYPE>(&Receiver##RECEIVER_NUM::method##METHOD_ID, &r##RECEIVER_NUM), \
boost::function0<RETURN_TYPE>(boost::bind(&Receiver##RECEIVER_NUM::method##METHOD_ID, &r##RECEIVER_NUM)), \
&Receiver##RECEIVER_NUM::method##METHOD_ID, \
(Receiver##RECEIVER_NUM *)0 \
, INVOKE_OR_COPY \
);
#define DO_BANCHMARK_0(METHOD_ID,RETURN_TYPE, INVOKE_OR_COPY) \
DO_BANCHMARK_0_IMPL(METHOD_ID,1,RETURN_TYPE, INVOKE_OR_COPY) \
DO_BANCHMARK_0_IMPL(METHOD_ID,2,RETURN_TYPE, INVOKE_OR_COPY) \
DO_BANCHMARK_0_IMPL(METHOD_ID,3,RETURN_TYPE, INVOKE_OR_COPY)
#define DO_BANCHMARK_1_IMPL(METHOD_ID,RECEIVER_NUM,RETURN_TYPE,ARG1, INVOKE_OR_COPY) compare_delegates(METHOD_ID, RECEIVER_NUM, \
Invoker1<RETURN_TYPE,ARG1>(), \
FastDelegate1<ARG1,RETURN_TYPE>(&r##RECEIVER_NUM, &Receiver##RECEIVER_NUM::method##METHOD_ID), \
delegate1<RETURN_TYPE,ARG1>::from_method<Receiver1,&Receiver##RECEIVER_NUM::method##METHOD_ID>(&r##RECEIVER_NUM), \
fd::delegate<RETURN_TYPE (ARG1)>(&Receiver##RECEIVER_NUM::method##METHOD_ID, &r##RECEIVER_NUM), \
boost::function1<RETURN_TYPE,ARG1>(boost::bind(&Receiver##RECEIVER_NUM::method##METHOD_ID, &r##RECEIVER_NUM,_1)), \
&Receiver##RECEIVER_NUM::method##METHOD_ID, \
(Receiver##RECEIVER_NUM *)0 \
, INVOKE_OR_COPY \
);
#define DO_BANCHMARK_1(METHOD_ID,RETURN_TYPE, ARG1, INVOKE_OR_COPY) \
DO_BANCHMARK_1_IMPL(METHOD_ID,1,RETURN_TYPE,ARG1, INVOKE_OR_COPY) \
DO_BANCHMARK_1_IMPL(METHOD_ID,2,RETURN_TYPE,ARG1, INVOKE_OR_COPY) \
DO_BANCHMARK_1_IMPL(METHOD_ID,3,RETURN_TYPE,ARG1, INVOKE_OR_COPY)
#define DO_BANCHMARK_2_IMPL(METHOD_ID,RECEIVER_NUM,RETURN_TYPE,ARG1,ARG2, INVOKE_OR_COPY) compare_delegates(METHOD_ID, RECEIVER_NUM, \
Invoker2<RETURN_TYPE,ARG1,ARG2>(), \
FastDelegate2<ARG1,ARG2,RETURN_TYPE>(&r##RECEIVER_NUM, &Receiver##RECEIVER_NUM::method##METHOD_ID), \
delegate2<RETURN_TYPE,ARG1,ARG2>::from_method<Receiver1,&Receiver##RECEIVER_NUM::method##METHOD_ID>(&r##RECEIVER_NUM), \
fd::delegate<RETURN_TYPE (ARG1,ARG2)>(&Receiver##RECEIVER_NUM::method##METHOD_ID,&r##RECEIVER_NUM), \
boost::function2<RETURN_TYPE,ARG1,ARG2>(boost::bind(&Receiver##RECEIVER_NUM::method##METHOD_ID,&r##RECEIVER_NUM,_1,_2)), \
&Receiver##RECEIVER_NUM::method##METHOD_ID, \
(Receiver##RECEIVER_NUM *)0\
, INVOKE_OR_COPY \
);
#define DO_BANCHMARK_2(METHOD_ID,RETURN_TYPE,ARG1,ARG2, INVOKE_OR_COPY) \
DO_BANCHMARK_2_IMPL(METHOD_ID,1,RETURN_TYPE,ARG1,ARG2, INVOKE_OR_COPY) \
DO_BANCHMARK_2_IMPL(METHOD_ID,2,RETURN_TYPE,ARG1,ARG2, INVOKE_OR_COPY) \
DO_BANCHMARK_2_IMPL(METHOD_ID,3,RETURN_TYPE,ARG1,ARG2, INVOKE_OR_COPY)
#define DO_BANCHMARK_3_IMPL(METHOD_ID,RECEIVER_NUM,RETURN_TYPE,ARG1,ARG2,ARG3, INVOKE_OR_COPY) compare_delegates(METHOD_ID, RECEIVER_NUM, \
Invoker3<RETURN_TYPE,ARG1,ARG2,ARG3>(), \
FastDelegate3<ARG1,ARG2,ARG3,RETURN_TYPE>(&r##RECEIVER_NUM, &Receiver##RECEIVER_NUM::method##METHOD_ID), \
delegate3<RETURN_TYPE,ARG1,ARG2,ARG3>::from_method<Receiver1,&Receiver##RECEIVER_NUM::method##METHOD_ID>(&r##RECEIVER_NUM), \
fd::delegate<RETURN_TYPE (ARG1,ARG2,ARG3)>(&Receiver##RECEIVER_NUM::method##METHOD_ID,&r##RECEIVER_NUM), \
boost::function3<RETURN_TYPE,ARG1,ARG2,ARG3>(boost::bind(&Receiver##RECEIVER_NUM::method##METHOD_ID,&r##RECEIVER_NUM,_1,_2,_3)), \
&Receiver##RECEIVER_NUM::method##METHOD_ID, \
(Receiver##RECEIVER_NUM *)0\
, INVOKE_OR_COPY \
);
#define DO_BANCHMARK_3(METHOD_ID,RETURN_TYPE,ARG1,ARG2,ARG3, INVOKE_OR_COPY) \
DO_BANCHMARK_3_IMPL(METHOD_ID,1,RETURN_TYPE,ARG1,ARG2,ARG3, INVOKE_OR_COPY) \
DO_BANCHMARK_3_IMPL(METHOD_ID,2,RETURN_TYPE,ARG1,ARG2,ARG3, INVOKE_OR_COPY) \
DO_BANCHMARK_3_IMPL(METHOD_ID,3,RETURN_TYPE,ARG1,ARG2,ARG3, INVOKE_OR_COPY)
#include <iostream>
int main()
{
Receiver1 r1;
Receiver2 r2;
Receiver3 r3;
int user_sel = 0;
do
{
std::cout << "Types 1 [Enter] for Invocation Speed Benchmark." << std::endl;
std::cout << "Types 2 [Enter] for Copy Speed Benchmark." << std::endl;
std::cin >> user_sel;
if( std::cin.fail() )
{
std::cin.clear();
std::string flush;
std::cin >> flush;
}
} while(1 != user_sel && 2 != user_sel);
bool invoke_or_copy = 1 == user_sel;
std::cout << (invoke_or_copy ? "[ Invocation Speed Benchmark ]" : "[ Copy Speed Benchmark ]") << std::endl;
std::cout << std::endl;
DO_BANCHMARK_STATIC_0(1, void, invoke_or_copy)
DO_BANCHMARK_STATIC_0(2, void, invoke_or_copy)
DO_BANCHMARK_STATIC_0(3, BigArg, invoke_or_copy)
DO_BANCHMARK_STATIC_0(4, BigArg, invoke_or_copy)
DO_BANCHMARK_0(5, void, invoke_or_copy)
if( invoke_or_copy )
{
DO_BANCHMARK_0(6, void, invoke_or_copy)
DO_BANCHMARK_0(7, BigArg, invoke_or_copy)
DO_BANCHMARK_0(8, BigArg, invoke_or_copy)
DO_BANCHMARK_1(9, void, BigArg, invoke_or_copy)
DO_BANCHMARK_1(10, void, BigArg, invoke_or_copy)
DO_BANCHMARK_1(11, BigArg, BigArg, invoke_or_copy)
DO_BANCHMARK_1(12, BigArg, BigArg, invoke_or_copy)
DO_BANCHMARK_2(13, void, BigArg, BigArg, invoke_or_copy)
DO_BANCHMARK_2(14, void, BigArg, BigArg, invoke_or_copy)
DO_BANCHMARK_2(15, BigArg, BigArg, BigArg, invoke_or_copy)
DO_BANCHMARK_2(16, BigArg, BigArg, BigArg, invoke_or_copy)
DO_BANCHMARK_0(17, void, invoke_or_copy)
DO_BANCHMARK_0(18, void, invoke_or_copy)
DO_BANCHMARK_0(19, BigArg, invoke_or_copy)
DO_BANCHMARK_0(20, BigArg, invoke_or_copy)
DO_BANCHMARK_1(21, void, BigArg, invoke_or_copy)
DO_BANCHMARK_1(22, void, BigArg, invoke_or_copy)
DO_BANCHMARK_1(23, BigArg, BigArg, invoke_or_copy)
DO_BANCHMARK_1(24, BigArg, BigArg, invoke_or_copy)
DO_BANCHMARK_2(25, void, BigArg, BigArg, invoke_or_copy)
DO_BANCHMARK_2(26, void, BigArg, BigArg, invoke_or_copy)
DO_BANCHMARK_2(27, BigArg, BigArg, BigArg, invoke_or_copy)
DO_BANCHMARK_2(28, BigArg, BigArg, BigArg, invoke_or_copy)
DO_BANCHMARK_3(29, void, void*, int, long, invoke_or_copy)
DO_BANCHMARK_3(30, void, void*, int, long, invoke_or_copy)
DO_BANCHMARK_3(31, bool, void*, int, long, invoke_or_copy)
DO_BANCHMARK_3(32, bool, void*, int, long, invoke_or_copy)
DO_BANCHMARK_3(33, void, void*, int, long, invoke_or_copy)
DO_BANCHMARK_3(34, void, void*, int, long, invoke_or_copy)
DO_BANCHMARK_3(35, bool, void*, int, long, invoke_or_copy)
DO_BANCHMARK_3(36, bool, void*, int, long, invoke_or_copy)
}
return 0;
}
int Zero = 0;