NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기Jaeseung Ha
NDC 2017 발표 슬라이드
시연 영상 링크: https://youtu.be/e9Tv3jkmqKk
게임 내 정보를 추가 구현이나 패치 없이 실시간으로 수집할 수 있다면 어떨까요? 이런 아이디어를 실제로 가능하게 구현한 NEXON ZERO 발표 슬라이드 입니다.
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...Amazon Web Services Korea
서비스 런칭을 위해 라이온하트와 카카오게임즈가 어떻게 최적 성능의 인스턴스를 선택하고, Windows 운영 체제를 최적화하며, 왜 Amazon Aurora를 기본 데이터베이스로 채택하였는지를 설명합니다. 또한, 출시부터 운영까지의 과정에서 MMORPG가 어떻게 AWS 상에서 설계되고, 게임 서버 성능을 극대할 수 있었는지에 대해 전달해드립니다.
Windows IOCP vs Linux EPOLL Performance ComparisonSeungmo Koo
1. The document compares the performance of IOCP and EPOLL for network I/O handling on Windows and Linux servers.
2. Testing showed that throughput was similar between IOCP and EPOLL, but IOCP had lower overall CPU usage without RSS/multi-queue enabled.
3. With RSS/multi-queue enabled on the NIC, CPU usage was nearly identical between IOCP and EPOLL.
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기강 민우
펄어비스의 MMORPG, 검은사막에 적용되어있는 AI 네비게이션 기능은 VOXEL 기반으로 자체 개발한 엔진을 이용해 구현되어 있습니다. 기존의 대다수 상용 라이브러리들이 네비 메쉬라고 하는 이동가능한 평면을 표현하는 폴리곤 기반의 데이터를 이용해 길찾기를 수행해주는 것에 비해 근간이 다릅니다. 이 강연에서는 검은사막의 네비게이션 엔진을 구현하고, 서버 / 클라이언트에 적용하면서 얻게된 노하우와 적용된 결과물들을 소개합니다.
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버Heungsub Lee
NDC14에서 발표한 "[야생의 땅: 듀랑고] 서버 아키텍처" 세션의 슬라이드입니다.
슬라이드에 설명이 많지 않은데, 디스이즈게임에서 발표 내용을 잘 정리해주었습니다. 기사도 함께 보시면 좋을 것 같습니다.
http://www.thisisgame.com/webzine/news/nboard/4/?n=54955
NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
Windows IOCP vs Linux EPOLL Performance ComparisonSeungmo Koo
1. The document compares the performance of IOCP and EPOLL for network I/O handling on Windows and Linux servers.
2. Testing showed that throughput was similar between IOCP and EPOLL, but IOCP had lower overall CPU usage without RSS/multi-queue enabled.
3. With RSS/multi-queue enabled on the NIC, CPU usage was nearly identical between IOCP and EPOLL.
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기강 민우
펄어비스의 MMORPG, 검은사막에 적용되어있는 AI 네비게이션 기능은 VOXEL 기반으로 자체 개발한 엔진을 이용해 구현되어 있습니다. 기존의 대다수 상용 라이브러리들이 네비 메쉬라고 하는 이동가능한 평면을 표현하는 폴리곤 기반의 데이터를 이용해 길찾기를 수행해주는 것에 비해 근간이 다릅니다. 이 강연에서는 검은사막의 네비게이션 엔진을 구현하고, 서버 / 클라이언트에 적용하면서 얻게된 노하우와 적용된 결과물들을 소개합니다.
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버Heungsub Lee
NDC14에서 발표한 "[야생의 땅: 듀랑고] 서버 아키텍처" 세션의 슬라이드입니다.
슬라이드에 설명이 많지 않은데, 디스이즈게임에서 발표 내용을 잘 정리해주었습니다. 기사도 함께 보시면 좋을 것 같습니다.
http://www.thisisgame.com/webzine/news/nboard/4/?n=54955
NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
boost라이브러리 중에서 가장 많이 사용하는 기능인 BOOST_FOREACH()와 shared_ptr의 내부 구조를 분석합니다. 그리고 boost의 내부 구현에 사용된 이 기능을 프로그래밍에 응용하는 방법을 제시합니다.
* BOOST_FOREACH 구조 분석 및 응용
* shared_ptr 구조 분석 및 응용
[KGC2014] 두 마리 토끼를 잡기 위한 C++ - C# 혼합 멀티플랫폼 게임 아키텍처 설계Sungkyun Kim
이미 많은 개발자들이 C#의 장점을 누리고 있으나, 본 PT에서는 높은 성능과 생산성을 동시에 달성하기 위해 C/C++로 개발된 native 게임 코드에 스크립트 언어로서 C#을 통합 할 수 있는 방법을 제시한다. 이를 위해 오픈소스 .Net 프레임웍인 Mono의 사용방법과 모바일 플랫폼에서의 특이사항들을 자세히 설명한다.
또한, C/C++언어에 C#을 비롯한 다양한 스크립트 언어를 효율적으로 혼합하여 게임을 구현할 수 있는 아키텍처를 제시한다. clang과 reflection을 이용하여 서로 다른 언어 간 인터페이스 노출을 자동화하고, 게임 내 오브젝트의 생명주기를 자동으로 관리할 수 있는 기법에 대해 설명한다.
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기Chris Ohk
기존에 작성해 놓은 C++ 코드에 모던 C++를 적용하기는 쉽지 않습니다. 막상 개선하려고 마음먹었다고 해도, 어디서부터 바꿔야 할 지 막막하기만 합니다. 이 세션에서는 기존 C++ 코드에서 모던 C++를 적용해 프로그램의 구조와 성능을 개선하는 방법에 대해서 설명합니다. 그리고 기존 C++ 코드에 모던 C++를 적용할 때 주의해야 될 점에 대해서도 살펴봅니다.
CyberConnect2에서는 2013년부터 DirectX11세대용 멀티플랫폼엔진 개발을 시작하였으며, 제작 시 발생하였던 문제점을 DirectX9와의 차이점을 바탕으로 공유하고자 합니다.
이 세션은 DirectX11의 개발이 처음이거나 관심 있으신 분을 대상으로 합니다. Tessellation 이나 OIT와 같은 최신기술은 다루지 않으므로 주의하시기 바랍니다.
Klaytn 101 #2 Blockchain Application(BApp) 동작원리와 구성요소 이해하기
1. BApp 개요: BApp의 동작원리와 BApp을 구성하는 요소들에 대해 설명
2. Count BApp: Klaytn Docs에 소개된 Count BApp 튜토리얼을 step-by-step으로 따라가며, web 기반 BApp 구현방법에 대해 설명
* 54 페이지 두번째 줄의 함수명 callPlus은 callMius로 변경해 주세요.
2. 다중 쓰레드 환경에서 동작해야 함으로 당연히 쓰레드 안전 (Thread-Safe) 하게 동작된다 .
CGCII 의 모든 동적 생성 객체는 참조계수 (Reference Count) 를 사용하여 소멸 처리 한다 .
IUnkonwned CComPtr<T>
shared_ptr<T>
• 가장 많이 알려진 ‘스마트 포인터’
• weak_ptr<T> 등과 연동하여 사용하기 편리하다 .
• 하지만 Thread-Safe 하지 않다 .
• 내부적으로 참조계수를 추가적으로 생성한다 .
• COM 에서 사용하는 ‘스마트포인터’지원
• Thread-Safe 하게 만들 수는 있다 .
• 참조계수는 IUnknowned 클래스의 가상 함수에 의
존한다 . (AddRef, Release)
• IC 이 클래스와 유사하다 .
ICGReferenceCount CGPTR<T>
• IUnknowned, CComPtr<T> 와 거의 유사하다 .
• 다만 AddRef, Release 가 가상함수가 아니고
OnFinalRelease() 함수를 가상함수로 두었다 .
• AddRef/Release 는 Thread-Safe 하게 동작한다 .
CGCIICho sanghyun’s Game Classes II
참조계수 (ReferenceCount)?참조계수
3. class ICGReferenceCount
{
protected:
ICGReferenceCount() {}
virtual ~ICGReferenceCount() {}
public:
long AddRef() { return m_Counter.increment();}
long Release();
protected:
virtual void OnFinalRelease() PURE;
private:
Interlocked_long m_Counter;
};
class ICGReferenceCount
{
protected:
ICGReferenceCount() {}
virtual ~ICGReferenceCount() {}
public:
long AddRef() { return m_Counter.increment();}
long Release();
protected:
virtual void OnFinalRelease() PURE;
private:
Interlocked_long m_Counter;
};
long ICGReferenceCount::Release()
{
long result=m_Counter.decrement();
if(result==0)
OnFinalRelease();
return result;
}
long ICGReferenceCount::Release()
{
long result=m_Counter.decrement();
if(result==0)
OnFinalRelease();
return result;
}
1. 참조계수를 위한 변수
(Interlocked 로 동작하며 0 으로 초기화 )
2. 참조계수 증가 AddRef()
참조계수 감소 Release()
3. 참조계수 감소 Release() 로 참조 계수가 0 이 되면
OnFinalRelease() 함수 호출 !
4. OnFinalRelease() 함수는 순수가상 함수로 정의 !
ICGReferenceCount 는 기본적으로 IUnknown 와 유사하다 .
CGCIICho sanghyun’s Game Classes II
ICGReferenceCount (1)참조계수
4. 참조계수를 적용한 동적 객체를 위해서 ICGReferenceCount 는 상속해서 사용함 .
순수가상함수인 OnFinalRelease() 함수를 재정의하여 사용함 .
class foo: virtual public ICGReferenceCount
{
public:
foo() {}
virtual ~ foo() {}
…
protected:
virtual void OnFinalRelease() { delete this; }
…
};
class foo: virtual public ICGReferenceCount
{
public:
foo() {}
virtual ~ foo() {}
…
protected:
virtual void OnFinalRelease() { delete this; }
…
};
1. ICGReferenceCount 를 상속 (virtual public 으로 )
2. OnFinalRelease() 함수의 재정의 !
( 일반적으로 자기자신을 지우도록 정의 )
{
foo* pObject = new foo;
pObject->AddRef();
…
pObject->Release();
}
{
foo* pObject = new foo;
pObject->AddRef();
…
pObject->Release();
}
5. 참조계수 증가시키기 ! ( 이때 참조계수는 1)
4. 생성 ! ( 이때 참조계수는 0)
6. 참조계수 감소시키기 !
( 이때 참조계수는 0 이 되며 OnFinalRelease() 가 호출 )
CGCIICho sanghyun’s Game Classes II
ICGReferenceCount (2)참조계수
5. 일일이 수동으로 참조계수를 증가 / 감소 시키는 것은 완전히 시르고 귀찮다 !!!
그래서 CGPTR<T>(CGD::shared_object<T>) 클래스가 있다 !
template <typename TREF>
class CGPTR
{
public:
CGPTR() : m_ref(nullptr) {}
CGPTR(TREF* _ref) : m_ref(_ref) { if(_ref!=nullptr) _ref->AddRef();}
CGPTR(const CGPTR <TREF>& _ref) : m_ref(_ref.get()) { if(m_ref!=nullptr) m_ref->AddRef();}
~ CGPTR() { if(m_ref!=nullptr) m_ref->Release();}
public:
CGPTR<TREF>& operator=(TREF* _rhs) { _reset(_rhs); return (*this);}
CGPTR<TREF>& operator=(const CGPTR<TREF>& _rhs){ _reset(_rhs.get()); return (*this);}
…
protected:
TREF* m_ref;
void _reset()
{
if(m_ref==nullptr) return;
m_ref->Release();
m_ref=nullptr;
}
void _reset(TREF* _ref) // _ref 를 AddRef() 하고 m_ref 를 Release() 한다 .
…
};
template <typename TREF>
class CGPTR
{
public:
CGPTR() : m_ref(nullptr) {}
CGPTR(TREF* _ref) : m_ref(_ref) { if(_ref!=nullptr) _ref->AddRef();}
CGPTR(const CGPTR <TREF>& _ref) : m_ref(_ref.get()) { if(m_ref!=nullptr) m_ref->AddRef();}
~ CGPTR() { if(m_ref!=nullptr) m_ref->Release();}
public:
CGPTR<TREF>& operator=(TREF* _rhs) { _reset(_rhs); return (*this);}
CGPTR<TREF>& operator=(const CGPTR<TREF>& _rhs){ _reset(_rhs.get()); return (*this);}
…
protected:
TREF* m_ref;
void _reset()
{
if(m_ref==nullptr) return;
m_ref->Release();
m_ref=nullptr;
}
void _reset(TREF* _ref) // _ref 를 AddRef() 하고 m_ref 를 Release() 한다 .
…
};
CGCIICho sanghyun’s Game Classes II
CGPTR (1)참조계수
6. 일일이 AddRef()/Release() 대신 CGPTR<T> 를 쓰면 아래처럼 쓸 수 있다 .
{
foo* pObject = new foo;
pObject->AddRef();
…
pObject->Release();
}
{
foo* pObject = new foo;
pObject->AddRef();
…
pObject->Release();
}
{
CGPTR<foo> pObject = new foo;
…
}
{
CGPTR<foo> pObject = new foo;
…
}
CGCIICho sanghyun’s Game Classes II
CGPTR<T> (2)참조계수
7. ICGReferenceCount
Releaser
매번 OnFinalRelease() 함수를 재정의하는 것도 귀찮으다 !
class foo: virtual public ICGReferenceCount
{
…
protected:
virtual void OnFinalRelease() { delete this; }
};
class foo: virtual public ICGReferenceCount
{
…
protected:
virtual void OnFinalRelease() { delete this; }
};
너무 뻔하다 !!!
namespace CGReleaser
{
class NDelete: virtual public ICGReferenceCount
{
public:
virtual ~ NDelete() {}
protected:
virtual void OnFinalRelease() { delete this; }
…
};
}
namespace CGReleaser
{
class NDelete: virtual public ICGReferenceCount
{
public:
virtual ~ NDelete() {}
protected:
virtual void OnFinalRelease() { delete this; }
…
};
}
아무것도 없고 !! 이것만 달랑 ~
Releaser 를 만들어 다중 상속하여 사용한다 .
class foo: public CGReleaser::NDelete
{
…
};
class foo: public CGReleaser::NDelete
{
…
};
Releaser 를 상속받는 것만으로 끝 !!!
그래서…
CGCIICho sanghyun’s Game Classes II
Release참조계수
8. Releaser 를 상속받는 것도 귀찮으다 !! 그리고 상황에 따라 Releaser 가 변경될 수도 있다 !!!
그래서 NEW<T> 를 제공한다 !!!
class foo: virtual public ICGReferenceCount
{
…
};
class foo: virtual public ICGReferenceCount
{
…
};
단지 ICGReferenceCount 만 virtual
public 으로 상속받아서…
template <typename T>
CGPTR<T> NEW()
{
class TCREATE : public T, public CGReleaser::Ndelete
{
};
return new TCREATE();
};
template <typename T>
CGPTR<T> NEW()
{
class TCREATE : public T, public CGReleaser::Ndelete
{
};
return new TCREATE();
};
Nested class TCREATE
T 와 Releaser 를 다중상속 받는다 !!!
TCREATE 를 생성해 리턴 한다 !
NEW<T> 를 사용하면 Releaser 를 상속받거나 OnFinalRelease() 함수를 재정의하지 않고
그냥 ICGReferenceCount 만 상속받으면 된다 !!!!
{
CGPTR<foo> pObject = NEW<foo>();
}
{
CGPTR<foo> pObject = NEW<foo>();
}
자동으로 Releaser 를 붙여주기 때문에 NEW<T> 를 사용하면 생성 가능하다 !!!
CGCIICho sanghyun’s Game Classes II
NEW<T> 함수 (1)참조계수
9. 그래서 앞으로 CGCII 의 일반적으로 동적 생성이 되는 객체는 ICGReferenceCount 만 상속받으며 ..
class foo: virtual public ICGReferenceCount
{
…
};
class foo: virtual public ICGReferenceCount
{
…
};
CGPTR<foo> pObject = NEW<foo>();CGPTR<foo> pObject = NEW<foo>();
NEW<T> 함수를 사용하여 생성하고…
생성된 포인터는 CGPTR<T> 에 저장하여 보관한다 .
아니 그럼 !!! 어차피 거의 다 OnFinalRelease() 에 ‘ delete this’ 할 것이면 뭣 하러 가상함수로 만들었
나 ???
→ 왜 필요한 가는 Pool 을 한 후 설명 !!
CGCIICho sanghyun’s Game Classes II
NEW<T> 함수 (2)참조계수
#4: Reference Counter란??
Smart pointer과 동일한 기능을 수행한다.
다만 객체 자체에 참조계수를 수행하는 ICGReferenceCount 클래스를 상속받아 shared_ptr처럼 참조계수를 위한 메모리를 생성하지 않는다.
#5: ICGReferenceCount 클래스는 자체 Reference Count를 위한 Thread-safe한 변수를 가지고 있고 AddRef와 Release 함수를 가지고 있다.
Release함수를 호출하여 Ref Count가 0이 되면 가상함수인 OnFinalRelease()함수를 호출한다.
사용자는 이 ICGReferenceCount를 상속받아 반드시 OnFinalRelease()함수를 정의해 주어야 한다.+
이때 virtual public으로 상속받아야 한다!!!!
#6: 생성 후 수동으로 AddRef()함수와 Release()함수를 호출하여 참조계수를 설정할 수 있지만…
한계가 있다.
그래서 자동화를 위한 CGPTR&lt;T&gt;를 제공해준다.
#7: CGPTR&lt;T&gt;는 마치 CComPtr&lt;T&gt;와 거의 동일한 클래스로..
ICGReferenceCount를 상속받은 객체의 포인터를 넣으면 AddRef()가 호출되어 참조계수를 1증가시키고
다시 빼거나 혹은 CGPTR&lt;T&gt; 객체가 소멸되면 Release()함수를 호출하여 참조계수를 1 감소시킨다.
#8: CGPTR&lt;T&gt;는 마치 CComPtr&lt;T&gt;와 거의 동일한 클래스로..
ICGReferenceCount를 상속받은 객체의 포인터를 넣으면 AddRef()가 호출되어 참조계수를 1증가시키고
다시 빼거나 혹은 CGPTR&lt;T&gt; 객체가 소멸되면 Release()함수를 호출하여 참조계수를 1 감소시킨다.
#9: 생성시킨 객체마다 ICGReferenceCount의 OnFinalRelease()함수를 작성하기는 귀찮다.
그래서 Releaser를 만들어 그냥 상속만 받으면 동작하도록 한다.
#10: 상속받는 것도 귀찮다!! 매번 상속받는 것이 귀찮으므로 NEW&lt;T&gt; 클래스를 정의했다.
(이부분은 일종의 Meta Programming임.)
Releaser를 상속받지 않아도 자동적으로 Releaser부분을 정의해준다.
#11: 상속받는 것도 귀찮다!! 매번 상속받는 것이 귀찮으므로 NEW&lt;T&gt; 클래스를 정의했다.
(이부분은 일종의 Meta Programming임.)
Releaser를 상속받지 않아도 자동적으로 Releaser부분을 정의해준다.