STL의 map 컨테이너 테스트

STL의 컨테이너 중에서 Hash 검색 알고리즘을 사용하고 있는 map 컨테이너를 테스트 해보았다. Hash 검색 알고리즘은 검색 항목의 개수에 상관없이 검색시간은 항상 일정하다라고 되어 있다. 바로 이것을 테스트해 보고자 했다.

N의 개수는 천만(10,000,000)개를 생성했으며 hash key는 unsigned long 타입으로 했다. 0, 2000000, 5000000, 7000000, 9999999 hash key 값을 검색하여 그곳에 -1을 넣었다. 과연 상수 시간이 나올 것인가? 나올 경우 시간은 얼마나 걸릴것인가…

아래는 그 결과다..


소요 시간은 분명 상수이긴 한데…. 0초다. 분명 0초는 아니겠지만 거의 0초가 걸린다. 사실 믿기지가 않는다. 아래는 테스트한 코드인데… 잘못된 부분이라도 있는건가? 옳바르다면 stl의 map 컨테이너는 정말 물건이다…

<#include 
#include <sys/timeb.h>
#include 

using namespace std;

void PerformanceTest(bool bStart, const char *szTitle="") {
    static timeb start;
    static timeb stop;

    if(bStart) {
        ftime(&start);
    } else {
        ftime(&stop);

        double gab;
        gab = 1.0e3 * difftime(stop.time, start.time);
        gab+=(double)(stop.millitm - start.millitm);

        double ReturnValue = gab/1.0e3;
        printf( "%s: %.10lf sec required.\n", szTitle, ReturnValue);
    }
}

map container_;

int _tmain(int argc, _TCHAR* argv[])
{
    PerformanceTest(true);
    for(unsigned long i=0; i<10000000; i++) {
        container_[i] = i;
    }
    PerformanceTest(false, "generating 10000000 data");

    printf("Now container has %ld items.\n\n", container_.size());

    for(size_t i=0; i<5; i++) {
        PerformanceTest(true);
        container_[0] = -1;
        PerformanceTest(false, "finding index 0:");

        PerformanceTest(true);
        container_[2000000] = -1;
        PerformanceTest(false, "finding index 2000000:");

        PerformanceTest(true);
        container_[5000000] = -1;
        PerformanceTest(false, "finding index 5000000:");

        PerformanceTest(true);
        container_[7000000] = -1;
        PerformanceTest(false, "finding index 7000000:");

        PerformanceTest(true);
        container_[10000000-1] = -1;
        PerformanceTest(false, "finding index 9999999:");
    }

    printf("\n[%ld %ld %ld %ld %ld]\n", 
        container_[0], 
        container_[2000000], 
        container_[5000000], 
        container_[7000000], 
        container_[9999999]
    );

    return 0;
}

My MP3 Player, Cowon F2

2달전에 구입한 MP3 플레이어. 살까말까 고민에 고민을 거듭하다가 샀다. 처음엔 오로지 MP3 기능에 충실한 iRiver의 S7을 사려고 했으나, 화이트노이즈가 있다는 말에 여타 다른 MP3 플레이어 중에서 가장 음장이 좋다는 F2로 결정했다.

MP3만 넣고 듣는 용도에 사용하려고 1기가로 결정했으나, 지금은 USB 저장장치로써 온갓 데이터와 인증서는 물론이고  가끔 영화도 넣고 본다. 영화를 넣고 볼때 대대적인 MP3 숙청 작업이 이뤄질때 1기가로 결정한 것을 후회한다. 무척 작은 화면에서 보는 영화지만 전철이나 버스 안에서 혼자 보기엔 뭐… 그런대로 봐줄만하다.

지난주에 교보문고에 가서 산 볼륨있는 하트 스티커를 9개의 버튼에 붙여 놓았다. 이쁜 모양은 물론이거니와 버튼을 누를때 보다 더 정확하게 눌를 수 있어서 대만족이다. 다만 저 스티커 가격이 3천원 ㅜ_ㅜ 이라는게 가슴 미어지긴 하지만 말이다….

처음엔 MP3 플레이어 보호를 위한 쉴드에 넣고 다녔으나, 이왕산거 맘편이 마구 마구 아껴(?) 사용하려고 쉴드를 제거했다. 나름대로 장식도 해 넣고 애지중지하지 않고 맘 편하게 그래도 나름 소중하게 사용해서 그런지 지금은 무척 애착이 가는 내 분신같은 물건이 되었다.

아래는 이 MP3 플레이어에서 사용하는 2개의 바탕화면 이미지이다. 처음엔 오른쪽 이미지를 사용했으나, 지금은 왼쪽 이미지를 사용하고 있다. 참고로 이 이미지 크기로 동영상이 나온다.

창밖에서 흔적남기기

관악구 신림8동.. 전철역에서 10분 걸어 이곳 6층. 꼭대기 층이고 하나뿐이 창문과 이 창문의 잘못된 방향으로 여름엔 사우나가 따로 없는 이곳을 내 임시 거처로 마련한지… 이제 1년하고도 6개월이나 되었다. 이제 몇달 후면 본래의 주인에게 이곳을 넘기고 다른 곳으로 옮긴다는 생각이 문득 들어… 창밖의 야경을 기록으로 남긴다.

운치가 한껏 느껴지지 못하는 야경이지만 가끔 답답한 마음을 달래려 창문을 열면 늘 나를 마지해주는 풍경이다. 폼 잡고서 담배 한대 물고서 하얀 연기 속의 고독과 상념에 빠져야 삶의 멋일진데…. 아쉽게도 나는 담배의 맛을 모른다…

GDI+에서 화면에 표시될 String(문자, Text)의 정확한 Width(폭) 구하기

GDI+에서 graphics의 MeasureString 함수를 통해 출력된 문자열의 폭을 구해보면 기대했던 폭 보다 다소 넓게 구해진다. MeasureString 보다 훨씬 정확한 폭을 구하는 방법에 대한 코드이다.

static public int MeasureDisplayStringWidth(Graphics graphics,
    string text, Font font)
{
    System.Drawing.StringFormat format = 
        new System.Drawing.StringFormat();

    System.Drawing.RectangleF rect = 
        new System.Drawing.RectangleF(0, 0, 1000, 1000);

    System.Drawing.CharacterRange[] ranges  = { 
        new System.Drawing.CharacterRange0,text.Length) 
    };

    System.Drawing.Region[] regions = new System.Drawing.Region[1];

    format.SetMeasurableCharacterRanges(ranges);

    regions = graphics.MeasureCharacterRanges(text, font, rect, format);
    rect = regions[0].GetBounds(graphics);

    return (int)(rect.Right + 1.0f);
}
옮겨온 곳 : Code Project, Pierre Arnaud의 글

 

참고로, 이 방법을 알기 전에는 필자는 String에 대한 Path를 만든 후, 즉 GraphicsPath를 만들고  GetBounds 매서드를 통해 크기를 얻었다. 하지만 이 방법은 MeasureString에 비해 정확하기는 하지만 역시 다소 부정확하다. 하지만 여전이 실제 프로젝트 적용에 대해서는 Path를 이용한 방법을 사용하고 있다.

[X-File] GDI+ 관련, drawString과 GraphicsPath의 차이

GDI+는 정말 사용하기 편하다고는 말 못해도.. -_-; 사용하면 할 수록 기능면에서는 무척 뛰어난 라이브러리로 생각된다. 하지만 가끔씩 이해하기 힘든 시츄레숀…를 만들곤 해서 날 당황하게 한다. 그래도 그때 그때 잘해결해 나갔는데.. 이번 문제는 해결의 시발점도 찾지 못하것다. 해결 방법을 검색해 볼레도.. 도통 검색 키워드를 뭐로해야할지도 모르겠고… 결국 해결하지 못한 이 문제로 인해 꽤나 많은 시간(대략 5~6시간)을 낭비…


문제는 GDI+를 이용해 문자를 그리는 것으로 그냥 DrawString을 이용해 그리는 것과 GraphicPath를 이용해 문자의 Path를 만든후 그 Path를 그려주는, 두 가지 방법에 대한 결과를 비교한 것이다. “안녕하세요”라는 문자가 보이는데, 노란색은 DrawString을 이용해 그린 것이고, 검정색 외곽선은 Path를 이용해 그린것이다.

똑같은 위치, 폰트, 크기, 정렬, 스타일, 크기단위로 지정해 주었음에도 Path가 문자의 폭이 조금 더 넓게 나온다. 높이는 문제가 없다. 유독 폭만 틀리다.

음…. 이 글을 작성하면서 떠오르는 것이.. 바로 “높이는 문제가 없으나, 폭만 다르다”라는 것에 힌트를 얻을 수 있겠다는 생각이 든다…….

문득 생각이 난 검색어로 “GDI+ drawString GraphicsPath”로 검색해 본 결과 동일한 문제에 대한 Q/A가 있었고 drawString과 GraphicsPath에 대한 속도 테스트 데모를 찾을 수 있었다. 먼저 몇개 Q/A의 경우 drawString과 Path를 이용한 렌더링 방법이 다르다는 점을 들어 다를 수밖에 없다라는 답변이다. 하나의 예로 문자의 경우와 그 외의 그래픽 요소에 대한 렌더링 퀄러티에 대한 옵션 지정이 다르다는 점이다. 개인적으로 볼때 그럴듯하지만 확실하지 않은 답변인데다가 근본적인 해결책을 제시하지 못하는 답변이라 도움이 되지 못했다. 속도 테스트 데모의 경우 실행을 해보니 처음 나타난 drawString과 Path를 이용한 문자열의 크기가 똑 같아 보였으나 폰트를 늘려보니 역시 Path를 이용한 문자열 출력이 drawString보다 더 길게 나왔다. 즉, 동일한 문제점이었다.

유추되는 한가지 원인을 말해보면, 앞서 언급했던 바와 같이 높이는 같으나 폭만 다르다는 점이다. “자간”이 문제가 아닌가 싶다. 즉, drawString의 경우 동일 폰트의 각각의 문자들 마다 다르게 지정되어져 있는 자간값이 고려되어져 화면상에 그리는 반면, Path의 경우 자간이 고려되지 않고 동일한 자간의 값으로 문자들에 대한 Path가 만들어지고 이렇게 만들어진 Path가 그려지게 되기때문이 아닌가 싶다.

여튼, 결국 해결 방법을 찾지 못하고 덮는다.