Upload
naver-d2
View
1.781
Download
0
Embed Size (px)
Citation preview
Thread Blocking Is Evil
게임네트웍컴포넌트팀
김준현
Thread
Blocking
Non-Blocking
&
순차적 코드 작성
Why does
Multi-Thread
matter?
“The Free Lunch
is OVER.”
Herb Sutter
December 2004
Clock speed
Execution optimization
Cache
Cache
Hyperthreading
Multicore
Cache
Write Multithreaded
Application
MULTI
THREAD
CONCURRENCY
하지만 현실은?
줄을 서서 기다린다
도대체
왜?
Thread
Blocking
Starvation
Deadlock
Starvation
Task A Task B
1: Lock 1: Sleep 1msec
2: Sleep 2msec
3: Unlock
Deadlock Hold & Wait
Thread A Thread B
1A: Lock 1B: Lock
2A: Request 2B: Send Response
3A: Wait for Response 3B: Unlock
4A: Do something with Response
5A: Unlock
Thread A Thread B
1A: Lock 1B: Lock
2A: Request 2B: Send Response
3A: Wait for Response 3B: Unlock
4A: Do something with Response
5A: Unlock
My
Problem
로비-룸 형태의
게임을 제작
Remote Procedure Call
처리 로직을 함수 단위로
짜기 때문에 개발이 쉽다
Game Client Lobby Room 방 입장 RPC 인증 RPC
Game Client Lobby Room
방 입장 RPC 호출
인증 RPC 호출
인증 RPC 반환
방 입장 RPC 반환
방 입장 RPC
처리 로직
인증 RPC
처리 로직
Game Client Lobby Room
방 입장 RPC 호출
인증 RPC 호출
방 입장 RPC
처리 로직
인증 RPC
처리 로직
인증 RPC 반환
방 입장 RPC 반환
Game Client Lobby Room
방 입장 RPC 호출
인증 RPC 호출
인증 RPC 반환
방 입장 RPC 반환
방 입장 RPC
처리 로직
인증 RPC
처리 로직 Lobby 응답 지연
Game Client Lobby Room
방 입장 RPC 호출
인증 RPC 호출
인증 RPC 반환
방 입장 RPC 반환
방 입장 RPC
처리 로직
인증 RPC
처리 로직 Lobby 응답 지연
Room서버 throughput
저하
악의 축은?
Thread
Blocking
Game Client Lobby Room
방 입장 RPC 호출
인증 RPC 호출
인증 RPC 반환
방 입장 RPC 반환
RPC의 태생적 한계
처리 로직을 함수 단위로
짜기 때문에 개발이 쉽다
처리 로직을 함수 단위로
짜기 때문에 찢을 수 없다
RPC::Result* JoinRoom(…)
{
…
RPC::Result answer = RPC::SyncCall(“VerifyLobbyUserToken”, …);
….
return result;
}
우리가 원하는 것
RPC의 장점인
순차적 코드 작성
Non-Blocking
가능한 해결책은?
RPC 이원화
Game Client Lobby Room
방 입장 응답 RPC
인증 요청 RPC 방 입장 요청 RPC
인증 응답 RPC
Game Client Lobby Room
방 입장 응답 RPC
인증 요청 RPC 방 입장 요청 RPC
인증 응답 RPC
Non-Blocking O
순차적 코딩 X
RPC 이원화
Thread Pool 분리
Game Client Lobby TP#1
방 입장 RPC 인증 RPC Room
TP#2
기타 RPCs
Game Client Lobby TP#1
방 입장 RPC 인증 RPC Room
TP#2
기타 RPCs
순차적 코딩 O
Non-Blocking X
Thread Pool 분리
이대로 끝인 거야?
Solution
Asynchronous
Programming
Request(callback, …)
Pros: Non-Blocking
Cons: Can’t Write Sequential Code
Can’t Use Stack Variable
Can’t Split Programming Construct
…
어렵다!
이대로 끝인 거야?
Coroutine
Similar to Thread
Line of Execution
Stack
&
Local Variable
But
Non-preemptive
Instruction: Yield
Yield Break
Resume
Coroutine을
제공하는 언어는?
C#
Erlang
Haskell
JavaScript(since 1.7)
Lua
Perl
Python(since 2.5)
Ruby
…
C++은?
손수 구현해야 한다
Windows: Fiber
Linux:
getcontext/setcontext
makecontext
swapcontext
Asynchronous
Programming
+
Coroutine
Non-Blocking
&
순차적 코드 작성
Solution
for
Starvation
Task A Task B
1: Lock 1: Sleep 1msec
2: Sleep 2msec
3: Unlock
Task A Task B
Thread A 1: Sleep 1msec
1: Create & Resume Coroutine
2: Request Lock
3: Yield
Thread A‟
4: Resume
5: Sleep 2msec
6: Yield Break
7: Unlock
Non-Blocking
Sequential
Code
Solution for
Deadlock Hold & Wait
Thread A Thread B
1A: Lock 1B: Lock
2A: Request 2B: Send Response
3A: Wait for Response 3B: Unlock
4A: Do something with Response
5A: Unlock
Thread A Thread B
1A: Lock 1B: Lock
2A: Create & Resume Coroutine 2B: Send Response
3A: Request 3B: Unlock
4A: Yield
5A: Unlock
Thread A‟ (invoked by response)
6A’: Lock
7A’: Resume
8A’: Do something
with response
9A’: Yield Break
10A’: Unlock
Non-Blocking
Sequential
Code
Solution
for
My Problem
Thread
Blocking
Game Client Lobby Room
방 입장 RPC 호출
인증 RPC 호출
인증 RPC 반환
방 입장 RPC 반환
룸 Thread 로비 서비스
1R: 인증 요청 1L: 인증 요청 처리
2R: 인증 응답 대기 2L: 인증 응답 보내기
3R: 방 입장 처리
룸 Thread 로비 서비스
1R: Create & Resume Coroutine 1L: 인증 요청 처리
2R: 인증 요청 2L: 인증 응답 보내기
3R: Yield
룸 Thread‟ (invoked by response)
4R’: Resume
5R’: 방 입장 처리
6R’: Yield Break
Non-Blocking
Sequential
Code
Request & Wait
Request & Yield
Non-Blocking
RPC의 장점인
순차적 코드 작성
Coroutine
(Fiber)
Thread
CPU CPU CPU CPU
User-mode Scheduling
Kernel-mode Scheduling
Coroutine
Pool
Network I/O
Thread Pool
RPC Task Queue
RPC
Execution
Thread Pool
RPC Task
Queue RPC Execution
Thread Network I/O
Thread
enqueue
task
dequeue
task
acquire coroutine
enqueue
resume
task
dequeue
resume
task
resume
yield break
release coroutine
Network
Event
Network
Event
Coroutine
Pool
pooling
coroutine
RPC
Execution
yield return
start
RPC Task
Queue RPC Execution
Thread 1 Coroutine
Pool
RPC
Execution
enqueue
task
dequeue
task
acquire coroutine
coroutine
yield return
enqueue
resume
task
dequeue
resume
task
release coroutine
Network
Event
Network
Event
pooling
RPC Execution
Thread 2
resume
yield break
resume
Network I/O
Thread
RPC::Result* JoinRoom(…)
{
…
RPC::Result answer = RPC::SyncCall(“VerifyLobbyUserToken”, …);
….
return result;
}
RPC::Result* JoinRoom(…)
{
…
RPC::Result answer = RPC::SyncCallYield(“VerifyLobbyUserToken”, …);
….
return result;
}
TPS
쓰래드 갯수
Wrap-up
“The free lunch
is OVER.”
Write Multithreaded
Application
CONCURRENCY
Thread Blocking is Evil
Starvation Deadlock
Asynchronous
Programming
+
Coroutine
Non-Blocking
+
Writing
Sequential Code
Request & Wait
Request & Yield
Inspired by Jeffrey Richter
‘Simplified APM With
The AsyncEnumerator’
완벽함이란
더 이상 추가할 것이 없을
때가 아니라
더 이상 버릴 것이 없을
때 완성된다. „성당과 시장‟에서