• 2006-04-11

    Migrate To ACE

    예전에도 밝혔다시피 요즘 legacy server core framework 를 ACE 기반으로 마이그레이션하고 있다. 기존 코드의 경우 골치아픈 동기화와 데드락을 최대한 피하기 위해서 IOCP를 썼음에도 불구하고 polling 을 통한 순차 처리를 하도록 되어 있어서, 일단 이 형태를 그대로 ACE 기반으로 재구성 한 후 제대로 된 이벤트 드리븐을 구현해보려고 노력 중이다. 사실, 테스트 결과는 그다지 좋지는 않지만, 숨겨진 병목 부분을 해결하면 원래 코드의 80-90% 정도는 따라갈 수 있으리라고 예상중이다.

    그런데 작업 도중 오랜만에 동기화 관련 버그를 만났다. ACE_ASSERT( p != 0 ); 에서 에러가 났는데 디버거로 쫒아가면 우습게도 포인터가 정상이 아닌가... 처음엔 VS2005를 탓하면서 한동안 헤롱거리다가 가만히 생각해보니, ASSERT가 발생한 직후 다른 쓰레드가 재빨리 값을 바꾸어 버리는 것 외에는 이유가 없다는 것을 깨달았다. 알고 보니 ACE API 의 호출 순서를 헷갈려서 생긴 문제였다. :(

    이번 마이그레이션의 최종 목표는 ACE 기반으로 제대로 된 gather-scatter I/O를 구현하는 것이다. 프레임워크가 잘 만들어져 있어서 금방 할 수 있긴 한데, 가능한한 락과 복사를 하지 않고 구현하려고 하니 잘 안되는 듯했다. (lock 으로 보호되는 ACE_Message_Block 을 duplicate() 해서 각각의 출력 버퍼에 concat 하고 출력 스트림에다가 writev() 만 하면 되는데 말이다. 물론 메모리 풀링도 필요하다.) 과연 하나의 버퍼에 복사한 후 플러시하는 게 빠를지, 버퍼 복사 없이 리스트로 관리하다가 한꺼번에 플러시하는게 빠를지... 결과가 기대된다. (ref-count 를 위한 락 때문에 더욱 결과가 모호하다 ㅋㅋ)

    이거 외에도 써먹어야 할 ACE 고급 기능들이 부지기수인데... 스케줄은 늘어지고, 야근은 하기 싫고, 오블리비언도 해야 되고... 진퇴양난이다.

  • 2006-03-23

    윈도우즈 무인설치

    5 대 이상의 머신에 OS를 가장 빨리 (그리고 안전하게) 설치하는 방법에 대해서 정리한 문서이다.

    개요

    이번에 ETRI 에서 주관하는 온라인게임테스트베드에 당첨되어, 서버를 설치하러 분당 KT IDC 에 가야 한다. 그런데, 많은 회사들이 회선을 공유하는지라 완전히 OS 를 설치하고 패치를 적용하고 백신을 설치해야만 인터넷 연결을 허용한다고 해서, 철저하게 CD 를 준비해서 재빨리 설치하고 돌아와야 한다!!

    • 사용 OS : Windows Server 2003 Standard
    • 대상 머신 : HP DL580 (1 EA), HP DL360 (4 EA)

    순서

    • http://v4.windowsupdate.microsoft.com/catalog/ko/default.asp 에서 해당 OS 의 최신 패치들을 다운받아서 CD 에 굽는다.
    • http://support.microsoft.com/?kbid=296861 을 기반으로 다운받은 패치들을 한번만에 적용하기 위해, CD 의 루트에다가 다음과 같은 배치 파일을 만든다.

    <code> @echo off setlocal set PATHTOFIXES=Drive:\Update %PATHTOFIXES%\WindowsServer2003-KB######-Platform-LLL.exe /Z /U %PATHTOFIXES%\WindowsServer2003-KB######-Platform-LLL.exe /Z /U %PATHTOFIXES%\WindowsServer2003-KB######-Platform-LLL.exe /Z /U </code>

    • 리부팅한 후, 이제 인터넷과 연결한다. (방화벽 및 백신은 꼭 설정할 것)

    see also:

    • SeriousCode:AutomatingWindowsInstallation
    • IpSec - IP 레벨의 접근 제어에 대해
  • 2006-03-23

    Doxygen

    설치

    설정

    • Doxygen GUI frontend 를 실행한 후, 맨 처음에는 Wizard 모드로 기본 설정을 하고, 다시 Expert 모드로 상세하게 설정을 해주면 된다. 이때 매번마다 환경을 변경한 다음에는 Doxyfile 로 저장하는 것을 잊지 말도록.
    • SeriousCode:DoxygenSetup 을 참고해서 배치파일을 잘 만들어두면 편하다.

    DoxygenTips

    • 상대경로를 애용할 것 : 범용성을 위해 INPUT 및 OUTPUT_DIRECTORY 는 상대 경로로 지정하고, DoxyWizard 의 Working Directory 를 절대 경로를 사용할 것. Doxygen 이 알아서 둘을 조합한다.
    • CREATE_SUBDIR 을 설정하면, html 폴더에 너무 많은 파일들이 몰리는 현상을 막을 수 있다.
    • FULL_PATH_NAMES 를 설정하고, STRIP_FROM_PATH 에 Working Directory 를 추가해주면, 여러 개의 하위 폴더에 나눠진 파일들의 경로를 출력할 수 있다
    • HHC_LOCATION 은 일반적으로 C:/Program Files/HTML Help Workshop/hhc.exe를 지정하면 된다. (Visual Studio 를 설치하면 저기에 자동으로 설치가 되기 때문)
    • DOT_IMAGE_FORMAT 은 png 로 설정하면 용량이 많이 줄어든다. 단 jpg + DOT_TRANSPARENT 의 조합은 용량이 무지막지하게 커지므로 주의할 것.
    • DOT_PATH 는 일반적으로 C:/Program Files/ATT/Graphviz/bin을 지정할 것

    see also:

  • 2006-03-22

    Relational Database Guidelines For MMOGs 요약

    원문 보기 : Relational Database Guidelines For MMOGs from Gamasutra

    Naming Convention

    • 프로그램에서의 이름과 DB에서의 이름을 일치시켜라.
    • user-defined type 을 사용해라. (단 타입이 변할 경우 낭패!)
    • 필요할 경우 축약어를 사용해도 좋다.

    Tables

    • 정수형 키를 사용할 경우, 가능한한 큰 타입의 키값을 사용할 것. 서비스 도중 타입을 바꾸는 것은 권장하지 않는다.
    • smart key(키값 자체의 의미를 담고 있는 키)는 절대 사용하지 말 것. 변경, 확장 및 유지 보수에 애로 사항이 꽃핀다.
    • 복합 키의 경우, 각 키값의 정렬 순서는 일치하는 편이 좋다. (하나는 증가, 하나는 감소..이러면 곤란)
    • 여러 개의 데이터베이스에서 동기화 되어야 할 키가 필요하다면, 범위를 잘 나눠야 한다. 그래야 나중에 합칠 때 좋다.

    Table Index

    • 정말 필요한 경우에만 인덱스를 추가할 것.
    • 프로파일러에서 느리다고 판명된 경우, 인덱스 추가 전후의 속도를 체크해서 인덱스 추가 후에 확실히 빨라졌다면 인정.

    Schema Structure

    • denormalization 은 흑마술이므로, 자신 없으면 도전하지 말 것. 정 하려면 아래와 같은 룰을 따를 것.
    • static 데이터는 서버 시작시 한꺼번에 메모리에 올릴 것.
    • 게임 객체 데이터 로딩시 - 여러 개의 테이블을 조인해야 하더라도 - 하나의 쿼리로 모든 데이터를 읽어들일 것. (당연히 그래야 하는 게 아닌가?.?)
    • 캐릭터와 소유 아이템 등 복잡한 데이터를 로딩할 때, 정말 필요할 때까지 로딩을 연기할 것(-_-). 또한, 이런 로딩도 비동기적이어야 함. (비동기 체인 쿼리?)
    • 계층적인 데이터를 실시간으로 변경하지 않도록 하라. (가령 인벤토리 내에 인벤토리 내의 인벤토리 같은 설계는 피할 것)
    • 데이터베이스 안에 또다른 데이터베이스를 만들지 말 것. 가령 여러 정보를 담고 있는 바이너리 컬럼이라든지, 컬럼 2개를 이용해서 1개의 값을 나타내는 등 SQL 쿼리로 다양한 데이터를 뽑아낼 때 추가적인 lookup 테이블이 필요한 디자인은 대략 좋지 않다.

    Stored Procedure

    • {{{SELECT * FROM ...}}} 보다는 실제 컬럼을 지정하는 편이 좋다.
    • 모든 라이브러리가 프로시저의 리턴값을 받도록 되어 있진 않으므로, {{{SELECT 1; RETURN}}} 과 같이 SELECT 를 이용하는 것을 권장한다.

    Transaction

    • 여러 개의 테이블을 수정하는 경우 필수적으로 사용할 것. (당연하징)
    • MSSQL 은 nested transaction 을 지원하지만, 부분적인 캔슬은 지원하지 않으므로 주의할 것.

    Joins

    • Perform joins on columns that are system assigned keys with good cardinality values
    • Add an index that verifiably speeds access if a join column is not the primary key on a table.
    • Keep the number of different tables in the join down to the minimum, particular if the query will return a large number of rows from one or more tables.
    • Offload the query to server startup time when we can better afford slower than optimal performance.

    Null Value

    • Any operations attempted against a NULL value will give NULL as the result. (even NULL NULL) :(

    Referential Integrity

    • RI is not optional
    • 아이템 복사 등을 막으려면 unique + FK 를 사용할 것.
    • 컬럼 제약조건을 애용할 것.
  • 2006-03-22

    MMP Database Mini-Cookbook 요약

    Unique Identifiers for Painless Game World Transfer

    • 계정을 다른 서버(월드)로 이전할 경우에 대비, 캐릭터에 유니크한 (정수) 아이디를 할당할 때, 월드 개수만큼 아이디를 증가시킨다. 이를 통해서 월드-유니크한 아이디를 할당할 수 있으며, 아이템 같은 종속 데이터의 이전도 용이하다.
    • 월드의 최대 개수는 고정(255)이다. 따라서, 늘어나서는 곤란!

    Managing Localization Data

    • NPC 스크립트, 다이얼로그 등의 텍스트 등을 DB 에 저장해두면 편하다.
    • 이때, localization 을 고려해서 저장할 것. 수정은 자체 툴을 만들어라..
    • DarkEden 에서도 이와 비슷하게 구현했다고 한다. (본인은 월드 추가전에 나와서.. 소문만 들었다.)

    Character Inventory Management and Shared Banking

    • 인벤토리-은행-퀘스트 간 아이템 이동, '''특히 캐릭터간 아이템 이동'''을 용이하게 하기 위해서 PlayerID - CharacterID - InventoryType - ItemID 방식으로 테이블을 설계할 것.
    • DarkEden 에서도 바닥-마우스-인벤토리-창고 등의 인벤토리 타입을 사용했었다.

    Mapping Class Inheritance to Database Tables

    • 다양한 아이템을 DB에 저장할 때, 클래스 속성(per-class)과 인스턴스 속성(per-instance)으로 테이블을 분리한다.
    • 모든 아이템마다 필요한 공통 데이터를 공통 Item 테이블에 정의하고, 하위 아이템을 위한 데이터는 하위 아이템 테이블에 정의한다.
    • ex: (ItemClass-ItemInstance)-(WeaponClass-WeaponInstance)
    • DarkEden에서도 이와 비슷하게, 각 아이템 종류별 Info 테이블과 Object 테이블을 두고, 관리를 했었다. 단점이라면, 테이블이 많아지면서 관리가 귀찮아지는 점과, Save-Load 프로시저가 길어진다는 점이 있겠다.

    Shared Game Configuration Parameters

    • 월드별 서버 환경 설정을 데이터베이스에 유지하면, 굳이 config 파일을 고치지 않아도 되므로 편하다. (서버가 많아지면 서버별 환경 설정 하는 것도 꽤 힘든 일이 되니까...)