사건의 발단은 VC9으로 테스팅하던 코드를 VC7.1로 포팅하면서 발생했습니다. 이상한 점은 VC7.1이 더 빠른겁니다. ?! 그것도 무려 60%정도였습니다. VC7.1은 STLPort를 사용하고 있었고, VC9은 MS에서 제공하는 녀석을 쓰고 있었지요.

일단, 코드부터 봅시다.

// STLPort 5.2.1 _vector.h:121
typedef _Tp value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type* iterator;
typedef const value_type* const_iterator;
// MSVC 2008 vector:1886
// 줄바꿈은 제가 한겁니다. @_@
typedef _Vb_const_iterator<size_type, difference_type, _Myt>
    const_iterator;
typedef _Vb_iterator<size_type, difference_type, _Myt>
    iterator;

..(생략)..

typedef iterator pointer;
typedef const_iterator const_pointer;
typedef std::reverse_iterator<iterator>
    reverse_iterator;
typedef std::reverse_iterator<const_iterator>
    const_reverse_iterator;

두둥. iterator의 타입이 포인터가 아니라.. iterator라는 클래스로 되어 있습니다. 뿐만 아니라, pointer도 iterator클래스로 되어있습니다. 내부를 파고 들어가보니 이렇습니다.


// MSVC 2008: vector:114
// 역시 줄바꿈은 제가..
_Myt& operator++()
{ // preincrement
_SCL_SECURE_VALIDATE(this->_Has_container());
_SCL_SECURE_VALIDATE_RANGE(
_Myptr < ((_Myvec *)(this->_Getmycont()))->_Mylast
);

#if _HAS_ITERATOR_DEBUGGING
if (
this->_Mycont == 0 ||
((_Myvec *)this->_Mycont)->_Mylast <= _Myptr ) _DEBUG_ERROR("vector iterator not incrementable"); #endif /* _HAS_ITERATOR_DEBUGGING */ ++_Myptr; return (*this); } [/cpp] _SCL_SECURE_VALIDATE라는 Macro를 장렬하게 호출합니다. (.. ) 이 매크로는 _SECURE_SCL 매크로에 의해 제어가 가능한데, 현재 상태가 제대로 된 상태인지 검사해주는 역할을 합니다. 잘못되면 예외를 발생시킵니다. ;; 일반적으로 vector는 T*를 반복자로 사용해도 문제가 없는 스펙을 갖고 있습니다. STLPort에서 T*를 반복자로 사용하는 이유도 그렇게 써도 되기 때문이지요. (표준안이 바뀌었을지는 모르겠습니다만..) 포인터를 반복자로 사용할 수 있다는 점은 시사하는바가 큽니다. 바로, 성능문제이지요. native타입인 T*는 컴파일러가 최적화 할 수 있는 소지도 많을 뿐더러, 인라인처리가 될까 말까 고민할 필요도 없으니까요. 대신, T*를 사용하게 되면, 이를 악용하는 프로그래머의 실수와 함께, range check와 같은 디버깅 관련 기능을 추가할 수 없다는 단점이 존재합니다.

MSVC 9.0은 단점을 위해 장점을 버린 케이스라고 할 수 있겠습니다. 뭐 성능문제는 _SECURE_SCL매크로를 끄니 5%내외로 낮아지긴 했습니다만.. 왠지 찜찜하군요. 결국 STLPort를 VC9용으로 빌드해버렸습니다. STLPort도 STLP_DEBUG모드로 사용하면, 저런 range check를 해주거든요. 🙂

사실 놀랐습니다. 저런 assertion관련 기능은 Release모드에서 별도로 켜주어야 작동하는게 맞는거 같은데 말이죠. 참고로 _SECURE_SCL을 켜두면 set에서 나는 차이는 더더욱 커집니다. 아무리 CPU가 발달해서 넘쳐나는 세상이라지만, 이건 좀 심하네요. -_-

물론, 개발툴입장에서 개발자의 편의를 추구하는 것은 당연하지만, 이런류의 편의성을 채택할거면 C#이나 Java를 쓰지 누가 C++을 쓰겠습니까. -_-; 디버깅할때나 필요할 법한 기능을 Release모드에 때려박다니.. 무슨 숨은 뜻이라도 있는걸까요. 🙁 뭐 저는 STLPort를 쓰기때문에 딱히 상관은 없습니다만. 🙂

ps1. 표준 관련 호환성은 많이 좋아지긴 한듯 합니다.
ps2. 그냥 STLPort에 투자하면 안되겠니 MS… -_-
ps3. 사고싶어요 징징.

MSVC 2008 STL vector

3 thoughts on “MSVC 2008 STL vector

  • 2009/11/26 at 1:10 오후
    Permalink

    아니 저런, _SECURE_SCL 은 항상 0으로. 저걸 끄고 최적화되면 그냥 단순 포인터와 차이가 없습니다만 (직접 코드 나오는거 보면 포인터++과 같습니다) _DEBUG가 있을 때 1로 하는 건 문제가 없는데 릴리즈일 때도 기본으로 켜는 건 문제가 있긴하죠.

    Reply
  • 2009/12/01 at 2:43 오후
    Permalink

    민장이형 이곳까지…

    Reply
  • 2009/12/01 at 4:12 오후
    Permalink

    @김민장
    단순포인터와 차이가 없기는 한데, 이상하게 약간의 차이는 있더라구요. inlining이 100% 다먹는건 아닌 모양입니다.

    그나저나, 릴리즈일때도 기본으로 켜는건 뭔 배짱인지 모르겠습니다.

    Reply

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.