It's just like pok    version4


어차피 io는 느린걸

 | 

C의 printf 계열보다 C++ 의 cout 등의 io 계열이 많이 느리다는건 익히 알려진 문제이다. 그런데 printf계열은 가변인자를 사용하여 printf와 비슷한 함수를 직접만드려면 어쩔수없이 va_list 계열의 매크로를 건드려야한다.

게다가 printf 계열은 버퍼오퍼플로를 막기위해 많은 변종들이 생겨나서 어떤게 표준인지 했갈리기도 한다. c99 표준이라고 알고 있는 snprintf는 Visual Studio 2008에서 조차 지원하지 않는다.

이런거 저런거 다 따져보면 차라리 C++ 계열의 io를 사용하는게 낫겠다는 생각이 들었다. 가변인자를 오버로딩으로 처리하면 formatting이 없는 경우에는 오히려 printf보다 빠르겠다는 생각도 들었다.

그래서 logger를 이런식으로 구현해봤다.


static void log( const char* _pSzContents )
{
    onPreSetMessage_();
    pLogger_->strCurrentMessage_ = _pSzContents;
    onPostSetMessage_();
}

template< typename T0, typename T1 >
static void log( const char* _pSzContents, T0 _t0, T1 _t1 )
{
    onPreSetMessage_();
    EStringUtils::formatStr(pLogger_->strCurrentMessage_, _pSzContents, _t0, _t1);
    onPostSetMessage_();
}

template< typename T0, typename T1, typename T2 >
static void log( const char* _pSzContents, T0 _t0, T1 _t1, T2 _t2 )
{
    onPreSetMessage_();
    EStringUtils::formatStr(pLogger_->strCurrentMessage_, _pSzContents, _t0, _t1, _t2);
    onPostSetMessage_();
}
...

물론 formatStr로 비슷하게 구현되어 있다.


template< typename T0 >
static void formatStr(std::string& _rString, const char* _pSzContents, T0 _t0 )
{
    formatStr(_rString, _pSzContents, _t0, FORMAT_INDEX_ERROR);
}

template< typename T0, typename T1 >
static void formatStr(std::string& _rString, const char* _pSzContents, T0 _t0, T1 _t1 )
{
    formatStr(_rString, _pSzContents, _t0, _t1, FORMAT_INDEX_ERROR);
}

...

static void formatStr(std::string& _rString, const char* _pSzContents, T0 _t0, T1 _t1, T2 _t2, T3 _t3, T4 _t4, T5 _t5, T6 _t6, T7 _t7 )
{
    assert(_rString.empty());
    std::vector< std::string > vBuffers;
    splitFormat_(_pSzContents, vBuffers);

    std::ostringstream oss;
    ...
    
}

뭐, 어차피 io는 느린걸…

관련 자료들


프로그래밍