#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned long long i64u;
// Benchmark ----------------------------------------------------------------
#ifdef _MSC_VER
#include <intrin.h>
#else
#define CHAR_BIT 8
inline unsigned long long __rdtsc()
{
i64u tick;
__asm volatile ( ".byte 0x0f, 0x31" : "=A" ( tick ) );
return tick;
}
#endif
#define _min( a, b ) ( (a) < (b)? (a): (b) )
#define _max( a, b ) ( (a) > (b)? (a): (b) )
#define update_min( a, b ) ( (a) = _min( (a), (b) ) )
#define update_max( a, b ) ( (a) = _max( (a), (b) ) )
//---------------------------------------------------------------------------
class SOME_RUNNER
{
private:
const char* function_name;
i64u elapsed;
protected:
i64u sum;
public:
SOME_RUNNER( const char* function_name )
: function_name( function_name ) { init(); }
virtual ~SOME_RUNNER() {};
virtual void init()
{
sum = 0;
elapsed = -1;
}
virtual void run() = 0;
void check()
{
i64u begin = __rdtsc();
run();
i64u duration = __rdtsc() - begin;
update_min( elapsed, duration );
}
const char* set_length( const char* str, const size_t size )
{
static char temp[80];
size_t index;
for( index = 0; str[index]; ++index ) temp[index] = str[index];
for( ; index < size; ++index ) temp[index] = ' ';
temp[index] = 0;
return temp;
}
const char* report()
{
static char temp[80];
sprintf( temp, "[llu] %s llu clocks", sum,
set_length( function_name, 20 ), elapsed );
return temp;
}
const i64u elapsed_clocks(){ return elapsed; }
const char* name(){ return function_name; }
};
//---------------------------------------------------------------------------
#include <vector>
template < size_t LOOP_COUNT >
class BENCH
{
private:
std::vector< SOME_RUNNER* > runner_list;
public:
/*con*/ BENCH() {};
/*des*/ ~BENCH() {};
void add( SOME_RUNNER* runner )
{
runner_list.push_back( runner );
}
void run()
{
printf( "< %d bits > %d trials", sizeof( size_t ) * CHAR_BIT, LOOP_COUNT );
puts( "" );
puts( "-------------------------------------------------------------" );
puts( "| CHECKER | Function name | minimum clocks |" );
puts( "-------------------------------------------------------------" );
i64u min = -1;
i64u max = 0;
size_t min_index = 0;
size_t max_index = 0;
for( size_t test_case = 0; test_case < runner_list.size(); ++test_case )
{
runner_list[test_case]->init();
for( size_t test_count = 0; test_count < LOOP_COUNT; ++ test_count )
runner_list[test_case]->check();
puts( runner_list[test_case]->report() );
if( min > runner_list[test_case]->elapsed_clocks() )
{
min_index = test_case;
min = runner_list[test_case]->elapsed_clocks();
}
if( max < runner_list[test_case]->elapsed_clocks() )
{
max_index = test_case;
max = runner_list[test_case]->elapsed_clocks();
}
}
puts( "-------------------------------------------------------------" );
printf( "Winner is %s ( %.2f times faster than looser )",
runner_list[min_index]->name(),
float( runner_list[max_index]->elapsed_clocks() ) /
runner_list[min_index]->elapsed_clocks() );
puts( "" );
}
};
//---------------------------------------------------------------------------
#define DEFINE_FUNCTION(return_type, function, ...)
(SOME_RUNNER*)new RUNNER<return_type>( std::bind(function, __VA_ARGS__), #function )
//---------------------------------------------------------------------------
#include <functional>
template< typename RET_TYPE >
class RUNNER : public SOME_RUNNER
{
public:
/*con*/ RUNNER( std::function< RET_TYPE() > function,
const char* function_name )
: test( function ), SOME_RUNNER( function_name ) {}
void run()
{
sum += (i64u)test();
}
std::function< RET_TYPE() > test;
};
template< >
class RUNNER< void > : public SOME_RUNNER
{
public:
/*con*/ RUNNER( std::function< void() > function,
const char* function_name )
: test( function ), SOME_RUNNER( function_name ) {}
void run()
{
sum++;
test();
}
std::function< void() > test;
};
//---------------------------------------------------------------------------
// 수정해서 사용해야 하는 부분에 진하게 표시해 둡니다.
size_t strlen_boost( const char* s );
size_t strlen_hybrid( const char* s );
int main()
{
#define STRING_LENGTH 1000000
char* test_string = new char[STRING_LENGTH + 1];
for( int i = 0; i < STRING_LENGTH; ++i )
{
test_string[i] = rand() % 127 + 1;
// test_string[i] = rand() % 255 + 1;
}
test_string[STRING_LENGTH] = 0;
BENCH< 1000 > bench;
bench.add( DEFINE_FUNCTION( size_t, strlen, test_string ) );
bench.add( DEFINE_FUNCTION( size_t, strlen_boost, test_string ) );
bench.add( DEFINE_FUNCTION( size_t, strlen_hybrid, test_string ) );
bench.run();
getchar();
return 0;
}
//---------------------------------------------------------------------------
delete 따윈 귀찮아서 안함유~
프갤질은 컴으로 해야하나부다...