SlideShare a Scribd company logo
1 of 81
Download to read offline
던전 앤 파이터
클라이언트 로딩 최적화
"우리 아이가 3배 빨라졌어요!"
NEOPLE 하재승
나 소개
Ymir Entertainment - 메틴2
NEXON - 빅샷
NCSOFT
NEOPLE- Dungeon & Fighter
TAOMP 번역
발표 목표
던파에 적용한 최적화 아이디어 소개 및 경험 공유
개요
상황 소개
데이터 분할 압축
Dumpable 라이브러리
이미지 미리읽기 리스트
그 외 효과가 컸던 최적화
초기 기동 시간 감소
TBB malloc 적용
버그 수정
최적화 목표
유저가 만족하는
편안한 게임 플레이
현실
8년간의 라이브 개발
수많은 깨진 창문
잦은 업데이트
상황 분석
데이터 파일 54만개, 패킹 후 300MB
이미지 1000만개 이상, 4.1GB
게임 플레이 시 자주 버벅이고 크래쉬
필요한 데이터를 그때 그때 하드에서 읽어옴
SSD가 사실상 필수
메모리 사용량이 2GB를 넘어서 크래쉬 하는 경우
로드맵
랙 최소화
일반 HDD 사용 시에도
메모리 사용량 최적화
크래쉬 문제 해결
복잡한 코드 구조로 인한 문제 해결
현재 적용한 최적화
랙 최소화
일반 HDD 사용 시에도
메모리 사용량 최적화
크래쉬 문제 해결
복잡한 코드 구조로 인한 문제 해결
최적화 전과 후 비교
시연 동영상: 초기 구동 시간 감소, 스킬 사용 랙 감소
goo.gl/0Xxm7b
위 링크에 있는 동영상
적용한 최적화들
데이터 분할 압축
Dumpable 라이브러리
이미지 미리읽기 리스트
그 외 효과가 컸던 최적화
초기 기동 시간 감소
TBB malloc 적용
버그 수정
데이터 분할 압축
데이터 파일 분할 압축
이미지, 사운드 등을 제외한 순수 데이터 파일
54만개, 642MB
XML과 유사한 태그가 존재하는 텍스트 파일
파일 이름만 모아도 30메가 수준
패킹 시 파일 별로 Binary XML과 비슷한 형태로 저장
300MB 수준
문제점
Memory mapped file 이용
메모리 공간 점유
XP SP2 이전 버전에서 실행 문제 발생
일정 크기 이상의 memory mapped file 생성 불가
하드디스크 읽기를 제어할 수 없음
데이터 분할 압축
전체 데이터를 압축하면 22MB
하지만 일부분만 얻으려면?
작게 쪼개서 압축해보자!
빠른 아이디어 검증
BLOCK = 64*1024
total = 0
for i in xrange(0, len(data), BLOCK):
total += len(zlib.compress(data[i:i+BLOCK], 9))
total ~ 55MB
다양한 블럭 크기 테스트- 64KB가 적절
실제 구현
비슷한 종류 파일들을 모아서 압축 - 35MB
압축된 내용 전체를 메모리에
54만개 파일의 이름 저장
증분 패킹
효과
게임 입장 후 메모리 사용량 100MB 감소
초기화 시간 - 큰 개선 없음
패치 용량 감소
데이터 파일 읽는 시간
mmap을 통해서 하드디스크 읽기 ~10ms
64KB 블럭 압축 해제 ~ 0.5ms (저사양 포함)
SSD ~ 0.5ms
Dumpable
Serialization without any serialization codes in C++
애니메이션 파일
전체 데이터 파일의 50%를 차지 (27만개)
화면상에 출력되는 모든 것 = 애니메이션
캐릭터 하나 로딩 시 2000개 이상 생성
데이터 파일을 빠르게 로딩할 수 없을까?
하드에 저장된 내용을 읽어와서
내부 자료구조로 변형하는 과정(파싱)이 필요
(body.ani -> CAnimation::Load)
메모리에 저장된 형태와 똑같이 하드에 저장한다면
읽어온 후 바로 사용가능
그러나 일반적으로 불가능
힙에 할당되는 string, vector등의 멤버가 존재
메모리 복사로 읽을 수 있는 class
POD struct 라면 가능 (http://en.wikipedia.org/wiki/Plain_old_data_structure)
std::string, std::vector 등이 들어가면
동적할당이 일어남
메모리 위치가 연속적이지 않음
전체 데이터와 같이 복사가 가능한
string과 vector를 만들면 되지 않을까?
std::string name
“하재승”
아이디어
복사 후에도 값들이 valid 해야 한다
동적 할당 메모리도 버퍼에 포함되어있어야 한다.
포인터형 데이터가 필요
포인터는 상대 주소의 형태로 저장
할당되는 영역을 모아서 같이 저장
이왕이면
시리얼라이즈 코드도 없으면 좋겠다
void serialize(Archive & ar, const unsigned int version) {
ar & degrees;
ar & minutes;
ar & seconds;
} // boost::serialization
Reflection이 없는 C++
변수 추가 시 수정하지 않으면 문제 발생
일반적으론 코드 생성으로 접근
Dumpable
http://github.com/ipkn/dumpable
오픈소스로 개발
추가 코드 없이 선언만 하면 읽고 쓰기 가능
복잡하게 중첩된 struct도 읽을 수 있음
파싱하는데 시간이 소요되지 않는다
Casting만 하면 바로 사용 가능
선언struct student {
dwstring name;
int score;
};
struct classroom {
dstring class_name;
dvector<student> students;
};
쓰기
classroom data;
data.class_name = "1001";
data.students.emplace_back(L"Alice",2);
data.students.emplace_back(L"Bob",5);
data.students.emplace_back(L"ud55cuae00",13);
ostringstream out;
dumpable::write(data, out);
// out.str()을 적절히 저장하거나 전송
읽기// (char*) buffer에 내용이 들어있다고 하면,
const classroom* pClassRoom = (classroom*)buffer;
// 메모리 상에 표현되는 그대로 저장되므로
// 캐스팅만 해도 값을 읽을 수 있다
사용하지 않은
경우와 비교
dumpable을 사용하지 않은 경우
// 아래와 비슷한 코드를 통해 파싱이 이루어지고
// 그 과정에서 속도 저하가 발생하게 된다.
classroom x;
stream.Read(x.class_name);
Uint32_t count;
stream.Read(count);
for(int i = 0; i < count; i ++)
{
student s;
stream.Read(s.name);
stream.Read(s.score);
x.students.push_back(s);
}
장점
Serialization 코드 없음
memcpy으로 복사 가능
Header-only library
특정 변수 제외 기능
데이터가 연속된 메모리 영역에 저장
classroom
class_name4
“1001” students34
Dumpable을 통해 저장되는 방식
struct student {
dwstring name;
int score;
};
struct classroom {
dstring class_name;
dvector<student>
students;
};
기대 효과
쓰기 비용이 큰 대신 추가 연산 없이 deserialize 완료
복잡한 게임 내부 구조체를 바로 읽기
메시지큐에 활용 가능
단순 메모리 복사로 메시지 복제
실제 효과
코드 변경량에 비해 성능 향상이 적어 롤백함
테스트 환경에서 1초 정도 개선
적용을 하려면 일부 보안용 코드를 제거해야만 했음
분석하자면,
대부분의 데이터는 2, 3개의 태그만 사용
실제 로딩에 걸리는 시간이 크지 않았다
Dumpable 내부 구현 (*)
* 실제 발표 중엔 간단히 설명하고 넘어갔습니다.
Dumpable 내부 구현
T*를 대체하는 dptr<T>
상대 주소를 저장
operator* 등을 overloading
dstring, dvector 등은 dptr 하나와 크기 정보를 저장
classroom
class_name4
“1001” students34
dumpable::write
struct student {
dwstring name;
int score;
};
struct classroom {
dstring class_name;
dvector<student>
students;
};
dumpable::write 구현 (1)
1. 할당이 필요한 메모리를 관리하기 위한 pool을 설정
2. 로컬변수와 pool을 이용하여 데이터를 복사
3. 버퍼와 내용을 모아서 스트림에 출력
Dumpable::write
template <typename T>
void write(const T& data, std::ostream& os)
{
T x;
dpool local_pool(&x, sizeof(T));
dumpable::detail::dptr_alloc() = [&local_pool]
(void* self, dumpable::size_t size)
->std::pair<void*, dumpable::ptrdiff_t>{
return local_pool.alloc(self, size);
};
x = data;
os.write((const char*)&x, sizeof(x));
local_pool.write(os);
dumpable::detail::dptr_alloc() = nullptr;
}
1
2
3
Dumpable::write
template <typename T>
void write(const T& data, std::ostream& os)
{
T x;
dpool local_pool(&x, sizeof(T));
dumpable::detail::dptr_alloc() = [&local_pool]
(void* self, dumpable::size_t size)
->std::pair<void*, dumpable::ptrdiff_t>{
return local_pool.alloc(self, size);
};
x = data;
os.write((const char*)&x, sizeof(x));
local_pool.write(os);
dumpable::detail::dptr_alloc() = nullptr;
}
1
2
3
Pool 설정
stream에 쓰기
dumpable::write 구현 (2)
dstring 등의 operator = 에서
pool에서 메모리 할당
dptr 내용을 할당된 버퍼를 가리키게 설정
할당된 버퍼에 =를 이용하여 다시 내용 복사
=를 사용하면서 재귀적으로 할당 및 대입이 이뤄지게 됨
classroom
class_name4
“1001” students34
dumpable::write
struct student {
dwstring name;
int score;
};
struct classroom {
dstring class_name;
dvector<student>
students;
};
이미지 미리읽기 리스트
유저가 플레이 시 읽는 이미지의 목록을 생성하여
게임 플레이 시 랙을 없애자!
개요 - 이미지 미리 읽기 리스트 생성
필요성 (+변명)
소스 파일 분석 (실패)
유저 로그 기반 생성
유저 로그 기반 생성의 한계점
리스트 업데이트 하기
미리 읽기 리스트 적용 결과
사실 당연히 되어야 하는건데…
던전 들어가서 스킬 처음 사용 시
하드에서 이미지 읽느라 랙 발생
어느 이미지 파일을 어느 시점에 읽는가?
이미지만 문제인가?
* 데이터 분할 압축 덕분에 데이터는 빠른 속도로 읽어올 수 있었다.
이미지만 해결하면 됨.
많은 양의 하드 코딩
직업별로 독특한 플레이 스타일을 구현
데이터 만으로 표현되기 힘듬
역사적인 이유
하드 코딩으로 해결
던파의 다양한 스킬들
귀검사(여) 소드마스터
검을 4가지 속성 중 하나로 강화
스킬 공격시 속성에 따라 색이 변경
마도학자 스킬 (플로레 컬라이드)
주위의 적을 번개로 공격하는 오브젝트를 소환
캐릭터는 옆의 쳇바퀴에 탑승
공격 버튼 연타 시 더 빠른 속도로 주위의 적을 공격
유저 헬마치 영상 http://www.youtube.com/watch?v=l3Pd3hZP2vA
랙이 심하게 걸려 유저들 사이에선 랙마치라고 부름
기존 던파의 이미지 관리
이미지를 그릴 때 필요하면 읽어온다
일단 읽었으면 버리지 말자!
스킬 쓸 때마다 랙이 걸리게 할 순 없음
무엇을 기준으로 버릴지 불확실
처음에 읽을 때 랙 + 메모리 문제 발생
실패한 시도 : 소스 파일 분석
컴파일러를 통해 define등 전처리기 제거 후 결과물 파싱
if ( … == SKILL_EXCALIBUR)
“character/swordman/animation/excalibur/excalibur_sw
ord_start_%s_%s_glow.ani”
* 슬라이드에 등장하는 파일 이름은 실제 데이터와는 다르게 변형되었습니다.
소스 파일 분석의 한계
애니메이션 파일 읽는 다양한 함수
함수를 호출 하는데 그 안에서 파일을 읽는 경우
다른 스킬과 소스를 공유하는 경우
일부 추출된 결과로 랙이 줄길 기대했으나
해당 리스트만으론 불충분
좋은 결과를 내려면 제대로 된 정적 분석이 필요
유저 로그 기반 추출
유저 로그
스킬 사용
이미지 읽음
현재 던전
스킬 사용 후
읽은 이미지
타이밍 정보
던전과 연관된
이미지
스킬 애니메이션
스킬 사용 모션
던전 애니메이션
유저 사용 로그 남기기
이미지를 실제로 하드에서 읽는 루틴 수정
해당 이미지를 처음 읽는 경우
현재 던전, 읽은 이미지, 해당 애니메이션 파일
유저가 스킬을 사용한 시점을 기록
직업, 스킬 번호
테스트 서버 일주일치 데이터
csv 파일 15GB
이미지 읽은 기록
7750만 회
유저 스킬 사용 기록
140만 회
모든 스킬이 포함
분석 (1) – 간단한 통계
유저가 사용한 스킬 별로
사용 후 일정 시간 이내에 읽은 이미지를 모두 수집
스킬 사용 기준으로 이미지 읽은 시간 통계
스킬에 의해 출력되는 이미지라면
→ 매번 비슷한 타이밍에 읽을 것이다.
분석 (1) – 간단한 통계
분산(표준편차)을 통해 추정
스킬
사용
시점
분산이 작다: 스킬 사용에 의해 읽는 이미지!
분산이 크다: 스킬과 무관한 이미지
이미지 읽은 시점
분석 (2) - 스킬 전용 모션
2D 게임, 옷이 여러 파츠로 나뉘어짐
파츠 이름/모션이름 위치에 저장
body/RandomKick.ani face/RandomKick.ani
하나만 추출되어도 뭉쳐서 읽음
*/RandomKick.ani
분석 (3) - 던전
그래도 계속 렉이 걸렸기 때문에
스킬로 구분되지 않은 데이터 중
특정 던전에서 반복해서 읽는 경우 구분
처음의 랙 개선된 동영상이 완성!
유저 로그 기반 추출
유저 로그
스킬 사용
이미지 읽음
현재 던전
스킬 사용 후
읽은 이미지
타이밍 정보
던전과 연관된
이미지
스킬 애니메이션
스킬 사용 모션
던전 애니메이션
한계 (1)
포털이 있는 맵 방식
A맵에서 스킬 사용 후
다른 곳으로 이동했다가 다시 A맵으로 돌아가는 경우
이전에 출력되던 스킬 이펙트가 남아서 화면에 이어 출력됨
→ 타이밍이 다른 로그가 남음
최대 시간 제한을 줄여서 회피
한계 (2)
저사양 데이터가 섞여서 구분이 힘듬
GrabBlastBlood.ani
322개, 0~1초 308개(95%), 5~19초 14개
평균 0.767초, 표준편차 2.59초
관련 없는 항목이 포함되기도 함
Outlier에 강한 분포를 이용해서 잘 할 수 있지 않을까?
한계 (3)
출력 자체가 랜덤한 경우
일반 공격 시 일정 확률 발동 등
가정에서 벗어난 케이스
일단은 손으로 보강
많지 않을 꺼라 가정
미리 읽기 리스트의 업데이트
업데이트가 필요한 경우
리스트에서 빠진 파일 추가
직업, 스킬 추가나 이펙트 변경
던전 밸런스 수정 – 몹 배치 변경 등
이벤트로 인한 일시적인 데이터 추가
이벤트 던전, 이벤트 몬스터 등
미리 읽기 데이터 업데이트 고려점 (1)
유저가 읽은 파일 목록 기반으로 추가하는 시스템이므로,
이미 한 번 미리 읽기 리스트에 추가가 된 경우
더 이상 그 파일을 읽는지 안 읽는지 알 수 없게 된다
리스트가 계속 늘어나게 되는 문제점이 있음
자동으로 필요 없어진 파일을 삭제할 방법이 필요
자동으로 제거하기 위한 아이디어
랜덤하게 적은 개수의 파일(10% 미만)을 리스트에서 삭제
계속 필요한 파일의 경우
사용하면서 다시 리스트에 추가된다
필요 없어진 파일의 경우
읽지 않으므로 다시 리스트에 추가되지 않는다
랙에는 크게 영향은 안주면서 미리 읽기 리스트 갱신
아직 적용해보지 않아서 적절한 비율은 판단하기 어렵다
결과
던전 입장 시간 증가, 게임 중 랙 감소
메모리 사용량 증가로 크래쉬 증가 우려
일단 1인 플레이에만 적용
유저가 배운 스킬이 많은 경우
1GB 머신에서 메모리 부족으로 쓰레싱 발생
그 외 효과가 컸던 최적화
이미지 팩팩 색인, std::map 변경, TBB malloc, 코드 버그 수정
4기가 이상의 이미지 데이터
이미지 1000만 개 이상
이미지 팩 8만 개 이상
이를 다시 2천 개 이상 파일(이미지 팩팩?)로 묶음
이미지 팩팩을 배포
이미지 팩팩 사용 시 기동 시간 크게 증가
이미지 팩팩 사용 시 느린 이유
처음 게임이 실행될 때
2천 개의 이미지 팩팩(총 4GB)을
하나하나 열어서
내부에 어떤 이미지 팩이 들어있는지 읽은 후
리스트로 저장
이미지 팩팩 색인 파일 생성
스캔 후 결과를 저장하는 파일을 생성
2천 개 파일 읽기 → 파일 하나 읽기
기동 시간 약 20초 감소
std::map 변경
프로파일링 결과 상위권 중에 std::map이 자주 등장
boost::unordered_map으로 변경
VS 2010의 unordered_map 성능 문제
boost::unordered_map 사용 시
std::unordered_map보다 최대 열 배 빠름
TBB malloc 적용
기존 VC++ CRT malloc 사용
TBB scalable_malloc으로 변경
초기 기동 시간 약 10% 개선
불필요한 추적용 정보 제거
보안을 위해 primitive type 변수를 래핑
매번 사용 기록을 남김
정상 접근인 경우 포함
실수로 넣은 것으로 추정
제거 후 10-20% 이상의 성능 향상
유저 복제하는 몬스터
2초 이상 -> 0.5초 수준
유저 반응
5/15일 적용
패치 후 유저 반응
VS
패치 후 유저 반응 (요약)
저사양 : 빨라져서 좋다
고사양 : 뭔 차이지?
스킨이 막혔어요!
더 튕긴다!
파티플 랙은 여전하다!
밸런스 패치 제대로 해달라
이후 목표
스킬 사용시 읽어야 할 데이터를 알게 됨
던전 종료 시 버릴 수 있다
마을 메모리 사용량 높은 이유 확인
메모리 사용량 최적화
파티 플레이에도 랙 감소 적용
크래쉬 감소, 쾌적한 게임 플레이
Q&A
데이터 분할 압축
Dumpable 라이브러리
유저 로그 기반 미리 읽기 리스트 생성
초기 기동 시간 감소
프로파일링
TBB malloc 적용
일반적인 최적화 관련 정보
아래 발표를 참고하세요.
"최적화와 프로파일링"
NDC 2008 송창규
"사례를 통해 살펴보는 프로파일링과 최적화“
NDC 2013 김이선

More Related Content

What's hot

전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019devCAT Studio, NEXON
 
MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현YEONG-CHEON YOU
 
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기Jaeseung Ha
 
NDC15 - 사례로 살펴보는 MSVC 빌드 최적화 팁
NDC15 - 사례로 살펴보는 MSVC 빌드 최적화 팁NDC15 - 사례로 살펴보는 MSVC 빌드 최적화 팁
NDC15 - 사례로 살펴보는 MSVC 빌드 최적화 팁Yi-kwon Hwang
 
[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기Sang Heon Lee
 
NDC2016 프로젝트 A1의 AAA급 캐릭터 렌더링 기술
NDC2016 프로젝트 A1의 AAA급 캐릭터 렌더링 기술NDC2016 프로젝트 A1의 AAA급 캐릭터 렌더링 기술
NDC2016 프로젝트 A1의 AAA급 캐릭터 렌더링 기술Ki Hyunwoo
 
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018devCAT Studio, NEXON
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010Ryan Park
 
[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리
[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리
[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리강 민우
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템QooJuice
 
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012Esun Kim
 
게임 분산 서버 구조
게임 분산 서버 구조게임 분산 서버 구조
게임 분산 서버 구조Hyunjik Bae
 
빌드관리 및 디버깅 (2010년 자료)
빌드관리 및 디버깅 (2010년 자료)빌드관리 및 디버깅 (2010년 자료)
빌드관리 및 디버깅 (2010년 자료)YEONG-CHEON YOU
 
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019devCAT Studio, NEXON
 
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012devCAT Studio, NEXON
 
게임서버프로그래밍 #1 - IOCP
게임서버프로그래밍 #1 - IOCP게임서버프로그래밍 #1 - IOCP
게임서버프로그래밍 #1 - IOCPSeungmo Koo
 
What is Game Server ?
What is Game Server ?What is Game Server ?
What is Game Server ?흥배 최
 
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019devCAT Studio, NEXON
 
NDC2019 - 게임플레이 프로그래머의 역할
NDC2019 - 게임플레이 프로그래머의 역할NDC2019 - 게임플레이 프로그래머의 역할
NDC2019 - 게임플레이 프로그래머의 역할Hoyoung Choi
 
프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법
프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법
프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법YEONG-CHEON YOU
 

What's hot (20)

전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
 
MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현
 
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
 
NDC15 - 사례로 살펴보는 MSVC 빌드 최적화 팁
NDC15 - 사례로 살펴보는 MSVC 빌드 최적화 팁NDC15 - 사례로 살펴보는 MSVC 빌드 최적화 팁
NDC15 - 사례로 살펴보는 MSVC 빌드 최적화 팁
 
[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기
 
NDC2016 프로젝트 A1의 AAA급 캐릭터 렌더링 기술
NDC2016 프로젝트 A1의 AAA급 캐릭터 렌더링 기술NDC2016 프로젝트 A1의 AAA급 캐릭터 렌더링 기술
NDC2016 프로젝트 A1의 AAA급 캐릭터 렌더링 기술
 
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
 
[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리
[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리
[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템
 
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
 
게임 분산 서버 구조
게임 분산 서버 구조게임 분산 서버 구조
게임 분산 서버 구조
 
빌드관리 및 디버깅 (2010년 자료)
빌드관리 및 디버깅 (2010년 자료)빌드관리 및 디버깅 (2010년 자료)
빌드관리 및 디버깅 (2010년 자료)
 
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
 
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
 
게임서버프로그래밍 #1 - IOCP
게임서버프로그래밍 #1 - IOCP게임서버프로그래밍 #1 - IOCP
게임서버프로그래밍 #1 - IOCP
 
What is Game Server ?
What is Game Server ?What is Game Server ?
What is Game Server ?
 
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
 
NDC2019 - 게임플레이 프로그래머의 역할
NDC2019 - 게임플레이 프로그래머의 역할NDC2019 - 게임플레이 프로그래머의 역할
NDC2019 - 게임플레이 프로그래머의 역할
 
프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법
프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법
프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법
 

Similar to [NDC 2014] 던전앤파이터 클라이언트 로딩 최적화

전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013devCAT Studio, NEXON
 
NDC 2016, [슈판워] 맨땅에서 데이터 분석 시스템 만들어나가기
NDC 2016, [슈판워] 맨땅에서 데이터 분석 시스템 만들어나가기NDC 2016, [슈판워] 맨땅에서 데이터 분석 시스템 만들어나가기
NDC 2016, [슈판워] 맨땅에서 데이터 분석 시스템 만들어나가기Wonha Ryu
 
Ndc2013 정리(upload버전)
Ndc2013 정리(upload버전)Ndc2013 정리(upload버전)
Ndc2013 정리(upload버전)Minsu Park
 
FIFA 온라인 3의 MongoDB 사용기
FIFA 온라인 3의 MongoDB 사용기FIFA 온라인 3의 MongoDB 사용기
FIFA 온라인 3의 MongoDB 사용기Jongwon Kim
 
Spark machine learning & deep learning
Spark machine learning & deep learningSpark machine learning & deep learning
Spark machine learning & deep learninghoondong kim
 
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드cranbe95
 
리소스 중심의 서든어택2 실시간 메모리 프로파일링 시스템 개발기
리소스 중심의 서든어택2 실시간 메모리 프로파일링 시스템 개발기리소스 중심의 서든어택2 실시간 메모리 프로파일링 시스템 개발기
리소스 중심의 서든어택2 실시간 메모리 프로파일링 시스템 개발기Wonha Ryu
 
[264] large scale deep-learning_on_spark
[264] large scale deep-learning_on_spark[264] large scale deep-learning_on_spark
[264] large scale deep-learning_on_sparkNAVER D2
 
Mapreduce tuning
Mapreduce tuningMapreduce tuning
Mapreduce tuningGruter
 
전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012
전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012
전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012devCAT Studio, NEXON
 
Chapter5 embedded storage
Chapter5 embedded storage Chapter5 embedded storage
Chapter5 embedded storage Hyun Wong Choi
 
Chapter5 embedded storage
Chapter5 embedded storage Chapter5 embedded storage
Chapter5 embedded storage Hyun Wong Choi
 
[KGC2014] 울프나이츠 엔진 프로그래밍 기록
[KGC2014] 울프나이츠 엔진 프로그래밍 기록 [KGC2014] 울프나이츠 엔진 프로그래밍 기록
[KGC2014] 울프나이츠 엔진 프로그래밍 기록 JiUng Choi
 
[16]Obfuscation 101 : 난독화, 프로가드, R8, 트랜스포머 API
[16]Obfuscation 101 : 난독화, 프로가드, R8, 트랜스포머 API[16]Obfuscation 101 : 난독화, 프로가드, R8, 트랜스포머 API
[16]Obfuscation 101 : 난독화, 프로가드, R8, 트랜스포머 APINAVER Engineering
 
데이터 분석 1 - 소개
데이터 분석 1 - 소개데이터 분석 1 - 소개
데이터 분석 1 - 소개Jaewook Byun
 
The hows and_whys_of_level_design_01
The hows and_whys_of_level_design_01The hows and_whys_of_level_design_01
The hows and_whys_of_level_design_01용태 이
 
게임 애셋 스트리밍 패치
게임 애셋 스트리밍 패치게임 애셋 스트리밍 패치
게임 애셋 스트리밍 패치Seungjae Lee
 
2D RPG 개발 이론 + 티뮤리티 개발 포스트모템
2D RPG 개발 이론 + 티뮤리티 개발 포스트모템2D RPG 개발 이론 + 티뮤리티 개발 포스트모템
2D RPG 개발 이론 + 티뮤리티 개발 포스트모템WooSung Jeon
 
프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기Chang W. Doh
 

Similar to [NDC 2014] 던전앤파이터 클라이언트 로딩 최적화 (20)

전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
 
NDC 2016, [슈판워] 맨땅에서 데이터 분석 시스템 만들어나가기
NDC 2016, [슈판워] 맨땅에서 데이터 분석 시스템 만들어나가기NDC 2016, [슈판워] 맨땅에서 데이터 분석 시스템 만들어나가기
NDC 2016, [슈판워] 맨땅에서 데이터 분석 시스템 만들어나가기
 
Ndc2013 정리(upload버전)
Ndc2013 정리(upload버전)Ndc2013 정리(upload버전)
Ndc2013 정리(upload버전)
 
FIFA 온라인 3의 MongoDB 사용기
FIFA 온라인 3의 MongoDB 사용기FIFA 온라인 3의 MongoDB 사용기
FIFA 온라인 3의 MongoDB 사용기
 
Spark machine learning & deep learning
Spark machine learning & deep learningSpark machine learning & deep learning
Spark machine learning & deep learning
 
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
 
리소스 중심의 서든어택2 실시간 메모리 프로파일링 시스템 개발기
리소스 중심의 서든어택2 실시간 메모리 프로파일링 시스템 개발기리소스 중심의 서든어택2 실시간 메모리 프로파일링 시스템 개발기
리소스 중심의 서든어택2 실시간 메모리 프로파일링 시스템 개발기
 
[264] large scale deep-learning_on_spark
[264] large scale deep-learning_on_spark[264] large scale deep-learning_on_spark
[264] large scale deep-learning_on_spark
 
엑셀왕국
엑셀왕국엑셀왕국
엑셀왕국
 
Mapreduce tuning
Mapreduce tuningMapreduce tuning
Mapreduce tuning
 
전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012
전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012
전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012
 
Chapter5 embedded storage
Chapter5 embedded storage Chapter5 embedded storage
Chapter5 embedded storage
 
Chapter5 embedded storage
Chapter5 embedded storage Chapter5 embedded storage
Chapter5 embedded storage
 
[KGC2014] 울프나이츠 엔진 프로그래밍 기록
[KGC2014] 울프나이츠 엔진 프로그래밍 기록 [KGC2014] 울프나이츠 엔진 프로그래밍 기록
[KGC2014] 울프나이츠 엔진 프로그래밍 기록
 
[16]Obfuscation 101 : 난독화, 프로가드, R8, 트랜스포머 API
[16]Obfuscation 101 : 난독화, 프로가드, R8, 트랜스포머 API[16]Obfuscation 101 : 난독화, 프로가드, R8, 트랜스포머 API
[16]Obfuscation 101 : 난독화, 프로가드, R8, 트랜스포머 API
 
데이터 분석 1 - 소개
데이터 분석 1 - 소개데이터 분석 1 - 소개
데이터 분석 1 - 소개
 
The hows and_whys_of_level_design_01
The hows and_whys_of_level_design_01The hows and_whys_of_level_design_01
The hows and_whys_of_level_design_01
 
게임 애셋 스트리밍 패치
게임 애셋 스트리밍 패치게임 애셋 스트리밍 패치
게임 애셋 스트리밍 패치
 
2D RPG 개발 이론 + 티뮤리티 개발 포스트모템
2D RPG 개발 이론 + 티뮤리티 개발 포스트모템2D RPG 개발 이론 + 티뮤리티 개발 포스트모템
2D RPG 개발 이론 + 티뮤리티 개발 포스트모템
 
프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기
 

[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화

  • 1. 던전 앤 파이터 클라이언트 로딩 최적화 "우리 아이가 3배 빨라졌어요!" NEOPLE 하재승
  • 2. 나 소개 Ymir Entertainment - 메틴2 NEXON - 빅샷 NCSOFT NEOPLE- Dungeon & Fighter TAOMP 번역
  • 3. 발표 목표 던파에 적용한 최적화 아이디어 소개 및 경험 공유
  • 4. 개요 상황 소개 데이터 분할 압축 Dumpable 라이브러리 이미지 미리읽기 리스트 그 외 효과가 컸던 최적화 초기 기동 시간 감소 TBB malloc 적용 버그 수정
  • 6. 현실 8년간의 라이브 개발 수많은 깨진 창문 잦은 업데이트
  • 7. 상황 분석 데이터 파일 54만개, 패킹 후 300MB 이미지 1000만개 이상, 4.1GB 게임 플레이 시 자주 버벅이고 크래쉬 필요한 데이터를 그때 그때 하드에서 읽어옴 SSD가 사실상 필수 메모리 사용량이 2GB를 넘어서 크래쉬 하는 경우
  • 8. 로드맵 랙 최소화 일반 HDD 사용 시에도 메모리 사용량 최적화 크래쉬 문제 해결 복잡한 코드 구조로 인한 문제 해결
  • 9. 현재 적용한 최적화 랙 최소화 일반 HDD 사용 시에도 메모리 사용량 최적화 크래쉬 문제 해결 복잡한 코드 구조로 인한 문제 해결
  • 10. 최적화 전과 후 비교 시연 동영상: 초기 구동 시간 감소, 스킬 사용 랙 감소 goo.gl/0Xxm7b 위 링크에 있는 동영상
  • 11.
  • 12.
  • 13. 적용한 최적화들 데이터 분할 압축 Dumpable 라이브러리 이미지 미리읽기 리스트 그 외 효과가 컸던 최적화 초기 기동 시간 감소 TBB malloc 적용 버그 수정
  • 15. 데이터 파일 분할 압축 이미지, 사운드 등을 제외한 순수 데이터 파일 54만개, 642MB XML과 유사한 태그가 존재하는 텍스트 파일 파일 이름만 모아도 30메가 수준 패킹 시 파일 별로 Binary XML과 비슷한 형태로 저장 300MB 수준
  • 16. 문제점 Memory mapped file 이용 메모리 공간 점유 XP SP2 이전 버전에서 실행 문제 발생 일정 크기 이상의 memory mapped file 생성 불가 하드디스크 읽기를 제어할 수 없음
  • 17. 데이터 분할 압축 전체 데이터를 압축하면 22MB 하지만 일부분만 얻으려면? 작게 쪼개서 압축해보자!
  • 18. 빠른 아이디어 검증 BLOCK = 64*1024 total = 0 for i in xrange(0, len(data), BLOCK): total += len(zlib.compress(data[i:i+BLOCK], 9)) total ~ 55MB 다양한 블럭 크기 테스트- 64KB가 적절
  • 19. 실제 구현 비슷한 종류 파일들을 모아서 압축 - 35MB 압축된 내용 전체를 메모리에 54만개 파일의 이름 저장 증분 패킹
  • 20. 효과 게임 입장 후 메모리 사용량 100MB 감소 초기화 시간 - 큰 개선 없음 패치 용량 감소 데이터 파일 읽는 시간 mmap을 통해서 하드디스크 읽기 ~10ms 64KB 블럭 압축 해제 ~ 0.5ms (저사양 포함) SSD ~ 0.5ms
  • 21. Dumpable Serialization without any serialization codes in C++
  • 22. 애니메이션 파일 전체 데이터 파일의 50%를 차지 (27만개) 화면상에 출력되는 모든 것 = 애니메이션 캐릭터 하나 로딩 시 2000개 이상 생성
  • 23. 데이터 파일을 빠르게 로딩할 수 없을까? 하드에 저장된 내용을 읽어와서 내부 자료구조로 변형하는 과정(파싱)이 필요 (body.ani -> CAnimation::Load) 메모리에 저장된 형태와 똑같이 하드에 저장한다면 읽어온 후 바로 사용가능 그러나 일반적으로 불가능 힙에 할당되는 string, vector등의 멤버가 존재
  • 24. 메모리 복사로 읽을 수 있는 class POD struct 라면 가능 (http://en.wikipedia.org/wiki/Plain_old_data_structure) std::string, std::vector 등이 들어가면 동적할당이 일어남 메모리 위치가 연속적이지 않음 전체 데이터와 같이 복사가 가능한 string과 vector를 만들면 되지 않을까? std::string name “하재승”
  • 25. 아이디어 복사 후에도 값들이 valid 해야 한다 동적 할당 메모리도 버퍼에 포함되어있어야 한다. 포인터형 데이터가 필요 포인터는 상대 주소의 형태로 저장 할당되는 영역을 모아서 같이 저장
  • 26. 이왕이면 시리얼라이즈 코드도 없으면 좋겠다 void serialize(Archive & ar, const unsigned int version) { ar & degrees; ar & minutes; ar & seconds; } // boost::serialization Reflection이 없는 C++ 변수 추가 시 수정하지 않으면 문제 발생 일반적으론 코드 생성으로 접근
  • 27. Dumpable http://github.com/ipkn/dumpable 오픈소스로 개발 추가 코드 없이 선언만 하면 읽고 쓰기 가능 복잡하게 중첩된 struct도 읽을 수 있음 파싱하는데 시간이 소요되지 않는다 Casting만 하면 바로 사용 가능
  • 28. 선언struct student { dwstring name; int score; }; struct classroom { dstring class_name; dvector<student> students; };
  • 29. 쓰기 classroom data; data.class_name = "1001"; data.students.emplace_back(L"Alice",2); data.students.emplace_back(L"Bob",5); data.students.emplace_back(L"ud55cuae00",13); ostringstream out; dumpable::write(data, out); // out.str()을 적절히 저장하거나 전송
  • 30. 읽기// (char*) buffer에 내용이 들어있다고 하면, const classroom* pClassRoom = (classroom*)buffer; // 메모리 상에 표현되는 그대로 저장되므로 // 캐스팅만 해도 값을 읽을 수 있다
  • 31. 사용하지 않은 경우와 비교 dumpable을 사용하지 않은 경우 // 아래와 비슷한 코드를 통해 파싱이 이루어지고 // 그 과정에서 속도 저하가 발생하게 된다. classroom x; stream.Read(x.class_name); Uint32_t count; stream.Read(count); for(int i = 0; i < count; i ++) { student s; stream.Read(s.name); stream.Read(s.score); x.students.push_back(s); }
  • 32. 장점 Serialization 코드 없음 memcpy으로 복사 가능 Header-only library 특정 변수 제외 기능 데이터가 연속된 메모리 영역에 저장
  • 33. classroom class_name4 “1001” students34 Dumpable을 통해 저장되는 방식 struct student { dwstring name; int score; }; struct classroom { dstring class_name; dvector<student> students; };
  • 34. 기대 효과 쓰기 비용이 큰 대신 추가 연산 없이 deserialize 완료 복잡한 게임 내부 구조체를 바로 읽기 메시지큐에 활용 가능 단순 메모리 복사로 메시지 복제
  • 35. 실제 효과 코드 변경량에 비해 성능 향상이 적어 롤백함 테스트 환경에서 1초 정도 개선 적용을 하려면 일부 보안용 코드를 제거해야만 했음 분석하자면, 대부분의 데이터는 2, 3개의 태그만 사용 실제 로딩에 걸리는 시간이 크지 않았다
  • 36. Dumpable 내부 구현 (*) * 실제 발표 중엔 간단히 설명하고 넘어갔습니다.
  • 37. Dumpable 내부 구현 T*를 대체하는 dptr<T> 상대 주소를 저장 operator* 등을 overloading dstring, dvector 등은 dptr 하나와 크기 정보를 저장
  • 38. classroom class_name4 “1001” students34 dumpable::write struct student { dwstring name; int score; }; struct classroom { dstring class_name; dvector<student> students; };
  • 39. dumpable::write 구현 (1) 1. 할당이 필요한 메모리를 관리하기 위한 pool을 설정 2. 로컬변수와 pool을 이용하여 데이터를 복사 3. 버퍼와 내용을 모아서 스트림에 출력
  • 40. Dumpable::write template <typename T> void write(const T& data, std::ostream& os) { T x; dpool local_pool(&x, sizeof(T)); dumpable::detail::dptr_alloc() = [&local_pool] (void* self, dumpable::size_t size) ->std::pair<void*, dumpable::ptrdiff_t>{ return local_pool.alloc(self, size); }; x = data; os.write((const char*)&x, sizeof(x)); local_pool.write(os); dumpable::detail::dptr_alloc() = nullptr; } 1 2 3
  • 41. Dumpable::write template <typename T> void write(const T& data, std::ostream& os) { T x; dpool local_pool(&x, sizeof(T)); dumpable::detail::dptr_alloc() = [&local_pool] (void* self, dumpable::size_t size) ->std::pair<void*, dumpable::ptrdiff_t>{ return local_pool.alloc(self, size); }; x = data; os.write((const char*)&x, sizeof(x)); local_pool.write(os); dumpable::detail::dptr_alloc() = nullptr; } 1 2 3 Pool 설정 stream에 쓰기
  • 42. dumpable::write 구현 (2) dstring 등의 operator = 에서 pool에서 메모리 할당 dptr 내용을 할당된 버퍼를 가리키게 설정 할당된 버퍼에 =를 이용하여 다시 내용 복사 =를 사용하면서 재귀적으로 할당 및 대입이 이뤄지게 됨
  • 43. classroom class_name4 “1001” students34 dumpable::write struct student { dwstring name; int score; }; struct classroom { dstring class_name; dvector<student> students; };
  • 44. 이미지 미리읽기 리스트 유저가 플레이 시 읽는 이미지의 목록을 생성하여 게임 플레이 시 랙을 없애자!
  • 45. 개요 - 이미지 미리 읽기 리스트 생성 필요성 (+변명) 소스 파일 분석 (실패) 유저 로그 기반 생성 유저 로그 기반 생성의 한계점 리스트 업데이트 하기 미리 읽기 리스트 적용 결과
  • 46. 사실 당연히 되어야 하는건데… 던전 들어가서 스킬 처음 사용 시 하드에서 이미지 읽느라 랙 발생 어느 이미지 파일을 어느 시점에 읽는가? 이미지만 문제인가? * 데이터 분할 압축 덕분에 데이터는 빠른 속도로 읽어올 수 있었다. 이미지만 해결하면 됨.
  • 47. 많은 양의 하드 코딩 직업별로 독특한 플레이 스타일을 구현 데이터 만으로 표현되기 힘듬 역사적인 이유 하드 코딩으로 해결
  • 48. 던파의 다양한 스킬들 귀검사(여) 소드마스터 검을 4가지 속성 중 하나로 강화 스킬 공격시 속성에 따라 색이 변경
  • 49. 마도학자 스킬 (플로레 컬라이드) 주위의 적을 번개로 공격하는 오브젝트를 소환 캐릭터는 옆의 쳇바퀴에 탑승 공격 버튼 연타 시 더 빠른 속도로 주위의 적을 공격
  • 50. 유저 헬마치 영상 http://www.youtube.com/watch?v=l3Pd3hZP2vA 랙이 심하게 걸려 유저들 사이에선 랙마치라고 부름
  • 51. 기존 던파의 이미지 관리 이미지를 그릴 때 필요하면 읽어온다 일단 읽었으면 버리지 말자! 스킬 쓸 때마다 랙이 걸리게 할 순 없음 무엇을 기준으로 버릴지 불확실 처음에 읽을 때 랙 + 메모리 문제 발생
  • 52. 실패한 시도 : 소스 파일 분석 컴파일러를 통해 define등 전처리기 제거 후 결과물 파싱 if ( … == SKILL_EXCALIBUR) “character/swordman/animation/excalibur/excalibur_sw ord_start_%s_%s_glow.ani” * 슬라이드에 등장하는 파일 이름은 실제 데이터와는 다르게 변형되었습니다.
  • 53. 소스 파일 분석의 한계 애니메이션 파일 읽는 다양한 함수 함수를 호출 하는데 그 안에서 파일을 읽는 경우 다른 스킬과 소스를 공유하는 경우 일부 추출된 결과로 랙이 줄길 기대했으나 해당 리스트만으론 불충분 좋은 결과를 내려면 제대로 된 정적 분석이 필요
  • 54. 유저 로그 기반 추출 유저 로그 스킬 사용 이미지 읽음 현재 던전 스킬 사용 후 읽은 이미지 타이밍 정보 던전과 연관된 이미지 스킬 애니메이션 스킬 사용 모션 던전 애니메이션
  • 55. 유저 사용 로그 남기기 이미지를 실제로 하드에서 읽는 루틴 수정 해당 이미지를 처음 읽는 경우 현재 던전, 읽은 이미지, 해당 애니메이션 파일 유저가 스킬을 사용한 시점을 기록 직업, 스킬 번호
  • 56. 테스트 서버 일주일치 데이터 csv 파일 15GB 이미지 읽은 기록 7750만 회 유저 스킬 사용 기록 140만 회 모든 스킬이 포함
  • 57. 분석 (1) – 간단한 통계 유저가 사용한 스킬 별로 사용 후 일정 시간 이내에 읽은 이미지를 모두 수집 스킬 사용 기준으로 이미지 읽은 시간 통계 스킬에 의해 출력되는 이미지라면 → 매번 비슷한 타이밍에 읽을 것이다.
  • 58. 분석 (1) – 간단한 통계 분산(표준편차)을 통해 추정 스킬 사용 시점 분산이 작다: 스킬 사용에 의해 읽는 이미지! 분산이 크다: 스킬과 무관한 이미지 이미지 읽은 시점
  • 59. 분석 (2) - 스킬 전용 모션 2D 게임, 옷이 여러 파츠로 나뉘어짐 파츠 이름/모션이름 위치에 저장 body/RandomKick.ani face/RandomKick.ani 하나만 추출되어도 뭉쳐서 읽음 */RandomKick.ani
  • 60. 분석 (3) - 던전 그래도 계속 렉이 걸렸기 때문에 스킬로 구분되지 않은 데이터 중 특정 던전에서 반복해서 읽는 경우 구분 처음의 랙 개선된 동영상이 완성!
  • 61. 유저 로그 기반 추출 유저 로그 스킬 사용 이미지 읽음 현재 던전 스킬 사용 후 읽은 이미지 타이밍 정보 던전과 연관된 이미지 스킬 애니메이션 스킬 사용 모션 던전 애니메이션
  • 62. 한계 (1) 포털이 있는 맵 방식 A맵에서 스킬 사용 후 다른 곳으로 이동했다가 다시 A맵으로 돌아가는 경우 이전에 출력되던 스킬 이펙트가 남아서 화면에 이어 출력됨 → 타이밍이 다른 로그가 남음 최대 시간 제한을 줄여서 회피
  • 63. 한계 (2) 저사양 데이터가 섞여서 구분이 힘듬 GrabBlastBlood.ani 322개, 0~1초 308개(95%), 5~19초 14개 평균 0.767초, 표준편차 2.59초 관련 없는 항목이 포함되기도 함 Outlier에 강한 분포를 이용해서 잘 할 수 있지 않을까?
  • 64. 한계 (3) 출력 자체가 랜덤한 경우 일반 공격 시 일정 확률 발동 등 가정에서 벗어난 케이스 일단은 손으로 보강 많지 않을 꺼라 가정
  • 65. 미리 읽기 리스트의 업데이트 업데이트가 필요한 경우 리스트에서 빠진 파일 추가 직업, 스킬 추가나 이펙트 변경 던전 밸런스 수정 – 몹 배치 변경 등 이벤트로 인한 일시적인 데이터 추가 이벤트 던전, 이벤트 몬스터 등
  • 66. 미리 읽기 데이터 업데이트 고려점 (1) 유저가 읽은 파일 목록 기반으로 추가하는 시스템이므로, 이미 한 번 미리 읽기 리스트에 추가가 된 경우 더 이상 그 파일을 읽는지 안 읽는지 알 수 없게 된다 리스트가 계속 늘어나게 되는 문제점이 있음 자동으로 필요 없어진 파일을 삭제할 방법이 필요
  • 67. 자동으로 제거하기 위한 아이디어 랜덤하게 적은 개수의 파일(10% 미만)을 리스트에서 삭제 계속 필요한 파일의 경우 사용하면서 다시 리스트에 추가된다 필요 없어진 파일의 경우 읽지 않으므로 다시 리스트에 추가되지 않는다 랙에는 크게 영향은 안주면서 미리 읽기 리스트 갱신 아직 적용해보지 않아서 적절한 비율은 판단하기 어렵다
  • 68. 결과 던전 입장 시간 증가, 게임 중 랙 감소 메모리 사용량 증가로 크래쉬 증가 우려 일단 1인 플레이에만 적용 유저가 배운 스킬이 많은 경우 1GB 머신에서 메모리 부족으로 쓰레싱 발생
  • 69. 그 외 효과가 컸던 최적화 이미지 팩팩 색인, std::map 변경, TBB malloc, 코드 버그 수정
  • 70. 4기가 이상의 이미지 데이터 이미지 1000만 개 이상 이미지 팩 8만 개 이상 이를 다시 2천 개 이상 파일(이미지 팩팩?)로 묶음 이미지 팩팩을 배포 이미지 팩팩 사용 시 기동 시간 크게 증가
  • 71. 이미지 팩팩 사용 시 느린 이유 처음 게임이 실행될 때 2천 개의 이미지 팩팩(총 4GB)을 하나하나 열어서 내부에 어떤 이미지 팩이 들어있는지 읽은 후 리스트로 저장
  • 72. 이미지 팩팩 색인 파일 생성 스캔 후 결과를 저장하는 파일을 생성 2천 개 파일 읽기 → 파일 하나 읽기 기동 시간 약 20초 감소
  • 73. std::map 변경 프로파일링 결과 상위권 중에 std::map이 자주 등장 boost::unordered_map으로 변경 VS 2010의 unordered_map 성능 문제 boost::unordered_map 사용 시 std::unordered_map보다 최대 열 배 빠름
  • 74. TBB malloc 적용 기존 VC++ CRT malloc 사용 TBB scalable_malloc으로 변경 초기 기동 시간 약 10% 개선
  • 75. 불필요한 추적용 정보 제거 보안을 위해 primitive type 변수를 래핑 매번 사용 기록을 남김 정상 접근인 경우 포함 실수로 넣은 것으로 추정 제거 후 10-20% 이상의 성능 향상 유저 복제하는 몬스터 2초 이상 -> 0.5초 수준
  • 77. 패치 후 유저 반응 VS
  • 78. 패치 후 유저 반응 (요약) 저사양 : 빨라져서 좋다 고사양 : 뭔 차이지? 스킨이 막혔어요! 더 튕긴다! 파티플 랙은 여전하다! 밸런스 패치 제대로 해달라
  • 79. 이후 목표 스킬 사용시 읽어야 할 데이터를 알게 됨 던전 종료 시 버릴 수 있다 마을 메모리 사용량 높은 이유 확인 메모리 사용량 최적화 파티 플레이에도 랙 감소 적용 크래쉬 감소, 쾌적한 게임 플레이
  • 80. Q&A 데이터 분할 압축 Dumpable 라이브러리 유저 로그 기반 미리 읽기 리스트 생성 초기 기동 시간 감소 프로파일링 TBB malloc 적용
  • 81. 일반적인 최적화 관련 정보 아래 발표를 참고하세요. "최적화와 프로파일링" NDC 2008 송창규 "사례를 통해 살펴보는 프로파일링과 최적화“ NDC 2013 김이선

Editor's Notes

  1. "YouTube 랙 걸린 줄 알았다"
  2. 파일 이름 저장 ASCII, Unicode 구분 Path와 파일 이름 구분
  3. 어떤 그림을, 어느 위치에, 어떤 효과를 줘서 찍는지 마을의 나무, 스킬 효과, 캐릭터 움직임 등등
  4. 빌드 옵션만 천바이트 ㅠㅠ
  5. Student t 분포
  6. 일단은 랙은 감소하니 이런 어려움 들이 있어도 적당히 패치함