'분류 전체보기'에 해당되는 글 20건

  1. 2009/12/28 김성민 아듀 2009 (5)
  2. 2009/12/25 김성민 메리 크리스마스~ (1)
  3. 2009/11/12 김성민 Visual Studio 2005 편집기 성능 향상 팁 (2)
  4. 2009/11/04 김성민 VSMacro/ 선택된 라인들에서 중복된 라인들은 삭제하고 나머지를 정렬하기
  5. 2009/10/26 김성민 감사합니다. (2)
  6. 2009/09/09 김성민 결혼합니다. (13)
  7. 2009/09/03 김성민 Visual Studio 2005 매크로 버그
  8. 2009/09/03 김성민 미니덤프 확장
  9. 2009/09/03 김성민 VSMacro/ 주석 정렬 매크로
  10. 2009/09/03 김성민 문자열을 키로 쓰는 std::set, std::map 성능 향상시키기

아듀 2009

잡담 2009/12/28 22:24 김성민
2009년이 저물어갑니다.

개인적으로는 참 여러가지 의미가 있었던 해였습니다.

가장 큰 건 역시, 두번 하라면 적극 사양할 결혼이 되겠네요.
 
아직 세상에 나오지는 않았지만 조카 소식도 들었습니다.

상용화 이후 서비스 안정화도 어느 정도 이뤄낸 것 같고,

회사 이사에다가 팔자에 없는 프로그램팀장 역도 떠맡았습니다.

온통 익숙치 않은 일인데, 2010년에는 더하면 더했지 덜 할 것 같지는 않네요.

게임업계가 불황 탓을 덜 탄다고는 하지만,

제가 느끼기에는 딱히 그렇지만도 않은 것 같습니다.

부디 다가오는 2010년에는 업계 전체적으로 호랑이 기운이 솟아났으면 합니다.

재미있게는 일하지 못하더라도, 보람있게는 일해야 하지 않겠습니까?


사용자 삽입 이미지

2009/12/28 22:24 2009/12/28 22:24
TAG
받은 트랙백이 없고, 댓글 6개가 달렸습니다.

댓글+트랙백 RSS :: http://serious-code.net/tc/rss/response/20

댓글+트랙백 ATOM :: http://serious-code.net/tc/atom/response/20

메리 크리스마스~

잡담 2009/12/25 21:25 김성민
사용자 삽입 이미지
사용자 삽입 이미지

감기 걸려서 골골거리다가 크리스마스가 다 지나가버렸습니다. 명동에 가서 사람이 얼마나 많은지 한번 보고 싶었는데, 왠지 억울하군요. ㅡㅜ
2009/12/25 21:25 2009/12/25 21:25
받은 트랙백이 없고, 댓글 하나가 달렸습니다.

댓글+트랙백 RSS :: http://serious-code.net/tc/rss/response/19

댓글+트랙백 ATOM :: http://serious-code.net/tc/atom/response/19

컴파일 또는 링크가 느린 건 참아도, 편집기가 느린 건 못 참아주겠다!

  • 서비스팩을 설치한다.
  • 인텔리센스를 끈다. (http://serious-code.net/moin.cgi/VisualStudioTips#head-1312c2269e254b39543f98684b00988688008aac)
  • 애니메이션을 비활성화한다. (도구 -> 옵션 -> 환경 -> 환경 도구에 애니메이션 효과 주기 X)
  • 탐색모음을 비활성화한다. (도구 -> 옵션 -> 텍스트 편집기 -> 해당 언어 -> 탐색 모음 X)
  • 변경 내용 추적을 비활성화한다. (도구 -> 옵션 -> 텍스트 편집기 -> 변경 내용 추적 X)
  • 활성화된 항목 추적을 비활성화한다. (도구 -> 옵션 -> 프로젝트 및 솔루션 -> 솔루션 탐색기에서 활성화된 항목 추적 X)
  • %HOMEPATH%\Local Settings\Application Data\Microsoft\WebsiteCache\ 폴더 안에 있는 파일들을 정기적으로 삭제한다. (http://blogs.geocortex.net/blogs/geocortex/archive/2007/12/07/slow-visual-studio-performance-solved.aspx)
  • 다른 형상 관리툴 같은 경우에는 어떤지 모르겠는데, 퍼포스의 P4SCC 인터페이스 같은 경우 주기적으로 서버를 폴링하면서 업데이트를 체크한다. 이걸 비활성화한다. (도구 -> 옵션 -> 소스 제어 -> 플러그인 설정 -> 고급 -> Connection -> Data retrieval)
  • 여건이 된다면 2005보다는 2008을 사용한다. :)

2009/11/12 16:46 2009/11/12 16:46
받은 트랙백이 없고, 댓글 2개가 달렸습니다.

댓글+트랙백 RSS :: http://serious-code.net/tc/rss/response/18

댓글+트랙백 ATOM :: http://serious-code.net/tc/atom/response/18

제목 그대로 선택된 라인들에서 중복된 라인들은 삭제하고 나머지를 정렬하기 위한 매크로입니다.

Visual Assist에 선택된 라인 정렬 기능이 있기는 한데, 중복 라인 삭제는 없어서, 어쩔 수 없이 만들었습니다. 주 목적은 아무래도 C++/include 구문 정리가 되겠습니다.

Collection 객체에 정렬 함수가 따로 없다는 것이 좀 의외군요.

Function Strip(ByVal strLine As String)
    If Len(strLine) > 0 Then       
        nBegin = 1
        nEnd = Len(strLine)
        For i = 1 To Len(strLine)
            c = Mid(strLine, i, 1)
            If c <> " " And c <> Tab And c <> Lf And c <> Cr Then
                nBegin = i
                Exit For
            End If
        Next
        For i = 1 To Len(strLine)
            c = Mid(strLine, Len(strLine) - i + 1, 1)
            If c <> " " And c <> Tab And c <> Lf And c <> Cr Then
                nEnd = Len(strLine) - i + 1
                Exit For
            End If
        Next
        Return Mid(strLine, nBegin, nEnd - nBegin + 1)
    Else
        Return ""
    End If
End Function

Sub SortCollection(ByRef oCollection As Collection, Optional ByVal bSortAscending As Boolean = True)
    Dim lSort1 As Integer
    Dim lSort2 As Integer
    Dim vTempItem1 As Object
    Dim vTempItem2 As Object
    Dim bSwap As Boolean

    For lSort1 = 1 To oCollection.Count - 1
        For lSort2 = lSort1 + 1 To oCollection.Count
            If bSortAscending Then
                If oCollection(lSort1) > oCollection(lSort2) Then
                    bSwap = True
                Else
                    bSwap = False
                End If
            Else
                If oCollection(lSort1) < oCollection(lSort2) Then
                    bSwap = True
                Else
                    bSwap = False
                End If
            End If
            If bSwap Then
                vTempItem1 = oCollection(lSort1)
                vTempItem2 = oCollection(lSort2)
                oCollection.Add(vTempItem1, Nothing, lSort2)
                oCollection.Add(vTempItem2, Nothing, lSort1)
                oCollection.Remove(lSort1 + 1)
                oCollection.Remove(lSort2 + 1)
            End If
        Next
    Next
End Sub

Sub SortAndRemoveDuplicatedLine()
    Dim objLines As New Collection
    Dim objSel As TextSelection = ActiveDocument().Selection
    Dim objRanges As TextRanges = objSel.TextRanges
    Dim objStartPt As EditPoint = objRanges.Item(1).StartPoint.CreateEditPoint()
    Dim objStream As New StringBuilder

    For Each strLine In objSel.Text.Split(Lf)
        strLine = Strip(strLine)
        If objLines.Contains(strLine) = False Then
            objLines.Add(strLine, strLine)
        End If
    Next

    SortCollection(objLines)

    For Each strLine In objLines
        objStream.AppendLine(strLine)
    Next

    objSel.Text = ""
    objStartPt.Insert(objStream.ToString())
End Sub

이 포스트 내용에 대한 이후 업데이트는 http://serious-code.net/moin.cgi/VisualStudioMacro 페이지에서만 이루어질 예정입니다. :)
2009/11/04 16:33 2009/11/04 16:33
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://serious-code.net/tc/rss/response/17

댓글+트랙백 ATOM :: http://serious-code.net/tc/atom/response/17

감사합니다.

기타 2009/10/26 11:16 김성민
사용자 삽입 이미지





















친구, 친지, 회사 동료분들... 축복해주신 여러분들에게 진심으로 감사의 말씀을 드립니다. 여러분들의 덕택으로 무사히 결혼식을 마치고 신혼여행까지 잘 다녀왔습니다. 앞으로도 열심히, 그리고 행복하게 잘 살겠습니다. :)


2009/10/26 11:16 2009/10/26 11:16
TAG
받은 트랙백이 없고, 댓글 2개가 달렸습니다.

댓글+트랙백 RSS :: http://serious-code.net/tc/rss/response/16

댓글+트랙백 ATOM :: http://serious-code.net/tc/atom/response/16

결혼합니다.

기타 2009/09/09 15:59 김성민

사용자 삽입 이미지



















일시: 2009년 10월 18일 (일요일) 오후 2시 30분
장소: 강남웨딩홀 (구 마샬 웨딩프라자) 3층 그레이스홀

제가 이런 글을 올리게 될 줄은 저도 몰랐습니다만, 어찌어찌하여 장가를 가게 되었습니다.

많이들 오셔서 자리를 빛내주시면 대단히 감사하겠습니다. :)

2009/09/09 15:59 2009/09/09 15:59
받은 트랙백이 없고, 댓글 13개가 달렸습니다.

댓글+트랙백 RSS :: http://serious-code.net/tc/rss/response/15

댓글+트랙백 ATOM :: http://serious-code.net/tc/atom/response/15

Visual Studio 2005 매크로 버그

개발 2009/09/03 09:10 김성민
갑자기 매크로가 실행되지 않습니다.

마치 실행되는 것처럼 모래시계 커서가 잠시 떴다가 금방 사라집니다. 하지만 실제로는 아무 것도 실행되지 않습니다.


KB928365 패치가 뭔가 문제가 되는 모양입니다. 패치를 따로 설치하지는 않아서 .NET 프레임웍 2.0 서비스팩을 날린 후, .NET 프레임웍 2.0을 새로 설치하니 잘 돌아갑니다. 구글 만세.
2009/09/03 09:10 2009/09/03 09:10
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://serious-code.net/tc/rss/response/14

댓글+트랙백 ATOM :: http://serious-code.net/tc/atom/response/14

미니덤프 확장

개발 2009/09/03 09:09 김성민
한달쯤전에 GPG 7을 받았습니다.

1.10 장에 눈에 띄는 내용이 있더군요.

스택 오버 플로 예외가 발생했을 때, 다른 스레드를 하나 생성해서 그쪽으로 스레드 핸들과 예외 포인터를 넘겨서 덤프를 기록한다는 내용이었습니다. 슈도 코드로 보자면 대충 아래와 같은 모양입니다.

typedef struct _DUMP_PARAMETER
{
  HANDLE              Thread;
  PEXCEPTION_POINTERS ExPtrs;
} DUMP_PARAMETER, *PDUMP_PARAMETER;

DWORD WINAPI WriteDump(LPVOID param)
{
  PDUMP_PARAMETER dumpParam = reinterpret_cast<PDUMP_PARAMETER>(param);
  ...
}

LONG WINAPI HandleException(PEXCEPTION_POINTERS exPtrs)
{
  if (exPtrs)
  {
      PDUMP_PARAMETER dumpParam = (PDUMP_PARAMETER)malloc(sizeof(DUMP_PARAMETER));
      dumpParam->Thread = GetCurrentThread();
      dumpParam->ExPtrs = exPtrs;
      if (exPtrs->ExceptionRecord->ExceptionCode != EXCEPTION_STACK_OVERFLOW)
      {
          WriteDump(dumpParam);
      }
      else // 스택 오버플로 발생 시에는 별도의 스레드를 생성해서 덤프를 기록한다.
      {
          HANDLE hThread = CreateThread(NULL, 102400, WriteDump, dumpParam, 0, NULL);
          WaitForSingleObject(hThread, INFINITE);
          CloseHandle(hThread);
      }
  }
  return EXCEPTION_EXECUTE_HANDLER;
}

void main()
{
  ...
  // 예외 처리 핸들러를 설정한다.
  SetUnhandledExceptionFilter(HandleException);
  ...
}


보다시피 그리 어려운 내용이 아니라 얼른 사용 중인 코드에다 저 로직을 집어넣었습니다. 하지만 실제로 스택 오버플로가 발생했을 때, 스레드 생성을 위한 스택은 남아있을까... 라는 생각에 미심쩍었는데 얼마 전에 요놈 덕분에 버그를 하나 잡았습니다. 깔깔깔~

또한 2주일쯤 전에는 Jochen Kalmbach라는 분의 블로그에서 SetUnhandledExceptionFilter 함수와 관련된 글을 읽었습니다. 자세한 내용은 여기 있는데 CRT 내부에서 뭔가 건드리기 때문에 예외가 발생해도 유저가 설치한 예외 핸들러가 호출되지 않을 수 있다는 이야기였습니다.

스택 오버플로도 그렇고, CRT 내부에서 삽질하는 것도 그렇고 그냥 프로세스가 사라지죠. 미니 덤프를 사용하시는 분이라면 저 2가지 내용을 처리해두시는 것이 도움이 될 겁니다.

다만 2번째 글의 함수는 뭔가 코드 영역에다 쓰기를 하는 함수라서 그런지 비스타에서 동작하지 않더군요. 뭐 상관없습니다. 게임 서버 비스타에서 돌릴 일 없으니까~ 음핫핫.
2009/09/03 09:09 2009/09/03 09:09
TAG
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://serious-code.net/tc/rss/response/13

댓글+트랙백 ATOM :: http://serious-code.net/tc/atom/response/13

VSMacro/ 주석 정렬 매크로

개발 2009/09/03 09:08 김성민

Before
//////////////////////////////////////////////////////////////////////////////////////////

/// \brief 글자가
/// 처음으로
/// 나타나는 위치를
/// 반환한다.
/// \param caseSensitive 대소문자 구별을 하는가?
/// \return size_t 음 이것은 그냥 붙여보는 주석이란다. abcdefg hijklmn opqrstu vwxyz 음 이것은 그냥 붙여보는 주석이란다. abcdefg hijklmn opqrstu vwxyz
//////////////////////////////////////////////////////////////////////////////////////////

음 "그냥 붙여보는 주석이란다..." 부분이 원래 한 줄인데, 워드랩되어버리는구나. 어쨌든 원래는 매우 긴 라인이다.

After
//////////////////////////////////////////////////////////////////////////////////////////
/// \brief 글자가 처음으로 나타나는 위치를 반환한다.
/// \param text 검색 대상 문자열
/// \return size_t 음 이것은 그냥 붙여보는 주석이란다. abcdefg hijklmn opqrstu vwxyz 음
/// 이것은 그냥 붙여보는 주석이란다. abcdefg hijklmn opqrstu vwxyz
//////////////////////////////////////////////////////////////////////////////////////////

Function Strip(ByVal strLine As String)
  ' 문자열 좌우의 공백을 제거한다.
  If Len(strLine) > 0 Then
       nBegin = 1
       nEnd = Len(strLine)
       For i = 1 To Len(strLine)
           c = Mid(strLine, i, 1)
           If c <> " " And c <> Tab And c <> Lf And c <> Cr Then
               nBegin = i
               Exit For
           End If
       Next
       For i = 1 To Len(strLine)
           c = Mid(strLine, Len(strLine) - i + 1, 1)
           If c <> " " And c <> Tab And c <> Lf And c <> Cr Then
               nEnd = Len(strLine) - i + 1
               Exit For
           End If
       Next
       Return Mid(strLine, nBegin, nEnd - nBegin + 1)
  Else
       Return ""
  End If
End Function

Function GetAsciiLength(ByVal str As String)
  Return Encoding.Default.GetBytes(str).Length
End Function

Sub WrapDoxygenComment()
  Dim nMaxLength As Integer = 90 - 1 ' -1은 딱 붙어있는 거 찝찝해서
  Dim nLineLength As Integer = 0
  Dim objRegex As RegularExpressions.Regex
  Dim objMatch As RegularExpressions.Match
  Dim objStream As New StringBuilder
  Dim objLines As New Collection
  Dim objSel As TextSelection = ActiveDocument().Selection
  Dim objRanges As TextRanges = objSel.TextRanges
  Dim objStartPt As EditPoint = objRanges.Item(1).StartPoint.CreateEditPoint()

  For Each strLine In objSel.Text.Split(CrLf)
       strLine = Strip(strLine)
       If objRegex.IsMatch(strLine, "^////+$") Then
       Else
           objMatch = objRegex.Match(strLine, "^///")
           If objMatch.Success Then
               strLine = Strip(strLine.SubString(objMatch.Length))
           End If
       End If
       objLines.Add(strLine)
  Next

  For i = 1 To objLines.Count
       strLine = objLines.Item(i)

      If strLine.Length = 0 Then
           objStream.Append(CrLf)
           objStream.Append("/// ")
           nLineLength = 0
       ElseIf objRegex.IsMatch(strLine, "^////+$") Then
           objStream.Append(CrLf)
           objStream.Append(strLine)
           nLineLength = 0
       Else
           For Each match As RegularExpressions.Match In RegularExpressions.Regex.Matches(strLine, "\S+\s*")
               If nLineLength = 0 Or match.Value.StartsWith("\") Or nLineLength + GetAsciiLength(match.Value) > nMaxLength Then
                   objStream.Append(CrLf)
                   objStream.Append("/// ")
                   nLineLength = 4
               End If

               objStream.Append(Strip(match.Value) + " ")
               nLineLength += GetAsciiLength(Strip(match.Value)) + 1
           Next
       End If
  Next
  objStream.Append(CrLf)

  ' 현재 선택된 문자열을 주어진 문자열로 치환한다.
  objSel.Text = ""
  objStartPt.Insert(objStream.ToString().Substring(2))
End Sub

정렬하고자 하는 주석을 선택한 다음에 실행할 것. 지속적인 업데이트는 아래의 주소에서...

http://serious-code.net/moin.cgi/VisualStudioMacro#head-0d4b04cbb9f3b4171409fd28d95661d243c6c74b
2009/09/03 09:08 2009/09/03 09:08
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://serious-code.net/tc/rss/response/12

댓글+트랙백 ATOM :: http://serious-code.net/tc/atom/response/12

문자열(std::string)을 키로 가지는 맵 같은 경우, 문자열 비교 자체에 걸리는 시간 때문에 검색이 느려질 수 있다. 이 경우, 키로 사용하는 문자열이 별로 중요한 내용이 아니라면 아래와 같은 클래스를 사용함으로서 성능을 약간 증가시킬 수 있다.

/// \class cStringKey
/// \brief STL 컨테이너를 위한 문자열 키
class cStringKey
{
private:
  enum {
       BYTE_SIZE = 32,
  };

  char m_Text[BYTE_SIZE]; ///< 문자열


public:
  /// \brief 생성자
  cStringKey() {
       memset(m_Text, 0, sizeof(m_Text));
  }

  /// \brief 생성자
  cStringKey(const char* text) {
       memset(m_Text, 0, sizeof(m_Text));
       memcpy_s(m_Text, sizeof(m_Text), text, std::min(sizeof(m_Text), strlen(text)));
  }

  /// \brief 생성자
  cStringKey(const std::string& text) {
       memset(m_Text, 0, sizeof(m_Text));
       memcpy_s(m_Text, sizeof(m_Text), text.c_str(), std::min(sizeof(m_Text), text.size()));
  }

  /// \brief 복사 생성자
  cStringKey(const cStringKey& rhs) {
       memcpy_s(m_Text, sizeof(m_Text), rhs.m_Text, sizeof(m_Text));
  }


public:
  /// \brief 대입 연산자
  inline const cStringKey& operator = (const cStringKey& rhs) {
       if (this != &rhs)
           memcpy_s(m_Text, sizeof(m_Text), rhs.m_Text, sizeof(m_Text));
      return *this;
  }

  /// \brief 비교 연산자
  ///
  /// 이 함수는 약간 유의해야 하는데, 속도를 위해 루프를 풀어버렸기 때문이다.
  /// 클래스의 크기가 변경되면, 이 함수도 같이 변경해줘야 한다.
  inline bool operator < (const cStringKey& rhs) const {
       const int* buf1 = reinterpret_cast<const int*>(this);
       const int* buf2 = reinterpret_cast<const int*>(&rhs);

       if (*buf1 != *buf2) return *buf1 < *buf2; // 0-3

       ++buf1; ++buf2;
       if (*buf1 != *buf2) return *buf1 < *buf2; // 4-7

       ++buf1; ++buf2;
       if (*buf1 != *buf2) return *buf1 < *buf2; // 8-11

       ++buf1; ++buf2;
       if (*buf1 != *buf2) return *buf1 < *buf2; // 12-15

       ++buf1; ++buf2;
       if (*buf1 != *buf2) return *buf1 < *buf2; // 16-19

       ++buf1; ++buf2;
       if (*buf1 != *buf2) return *buf1 < *buf2; // 20-23

       ++buf1; ++buf2;
       if (*buf1 != *buf2) return *buf1 < *buf2; // 24-27

       ++buf1; ++buf2;
       return *buf1 < *buf2; // 28-31
  }
};

대소문자 구별없이 비교를 할 수 없다는 점이 좀 아쉽다. 어셈블리도 좀 안다면 비교 연산자를 좀 더 깔끔하게 만들 수 있을 텐데. 어쨌든 테스트해보니, 릴리즈 빌드에서 약 25~33% 정도의 성능이 향상되었다.

typedef std::map<std::string, std::string> OLD_MAP;
typedef std::map<cStringKey, std::string> NEW_MAP;

OLD_MAP oldMap;
NEW_MAP newMap;

for (int i=0; i<1000; ++i) {
  std::string key = generic::to_string(rand() % 1000, 4);
  std::string value = generic::to_string(rand() % 1000, 4);
  oldMap.insert(OLD_MAP::value_type(key, value));
  newMap.insert(NEW_MAP::value_type(key, value));
}

DWORD begin = 0, oldTime = 0, newTime = 0;
int repetition = 200000;

begin = timeGetTime();
for (int i=0; i<repetition; ++i)
  oldMap.find(generic::to_string(rand() % 1000, 4));
oldTime = timeGetTime() - begin;

begin = timeGetTime();
for (int i=0; i<repetition; ++i)
  newMap.find(generic::to_string(rand() % 1000, 4));
newTime = timeGetTime() - begin;

std::cout << "OLD: " << oldTime << std::endl;
std::cout << "NEW: " << newTime << std::endl;

OLD: 241
NEW: 146

이런 자잘한 최적화 해봐야 얼마나 달라지겠냐만은 기왕이면 다홍치마 아닌가.
2009/09/03 09:07 2009/09/03 09:07
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://serious-code.net/tc/rss/response/11

댓글+트랙백 ATOM :: http://serious-code.net/tc/atom/response/11