TL;DR
- busy polling์ non-blocking ์์์ ๋ฉ์ถ์ง ์๊ณ ๋ฐ๋ณต ํ์ธํ๋ synchronous ๋ฐฉ์ โ ๋ณดํต์ CPU๋ฅผ ํ์ฐ๋ ๋ญ๋น
- epoll ๊ฐ์ ์ค๋น์๋ฃ ํต์ง๊ฐ ๋๋ฌป๊ธฐ๋ฅผ ์์ ํ์ค์ด์ง๋ง ์ ๋ง์ดํฌ๋ก์ด ์ง์ฐ์ด ์๊น์ด ์ ์ง์ฐ ๋๋ฉ์ธ์ ์คํ์ ์ ํ
- ๊ณ ๋น๋ ํธ๋ ์ด๋ฉยทDPDKยทSO_BUSY_POLLยทspinlock์ด ๋ํ ์ฌ๋ก โ ์ฝ์ด ํ๋๋ฅผ ํ์ ์ง์ฐ์ ์ฌ๋ ๊ฑฐ๋
AI-assisted
1. busy polling์ด๋
Concurrency and Parallelism์์ ๋๊ธฐ/๋น๋๊ธฐ์ ๋ธ๋กํน/๋
ผ๋ธ๋กํน์ ์ง๊ตํ๋ ๋ ์ถ์ผ๋ก ๊ฐ๋๋ค.
๊ทธ์ค synchronous + non-blocking ์กฐํฉ์ด busy polling์ ๋ฟ๋ฆฌ๋ค.
- non-blocking ํธ์ถ์ ์ง๊ธ ๋๋ผ ์ ์์ผ๋ฉด ์ฆ์ ๋์์จ๋ค
- ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ ์๋ฆฌ์ ํ๋จํ๊ณ (synchronous), ์์ง์ด๋ฉด ๋ค์ ๋ฌป๋๋ค
- ์ด โ๋ค์ ๋ฌป๊ธฐโ๋ฅผ ๋ฉ์ถ์ง ์๊ณ ๋ฐ๋ณตํ๋ ๊ฒ์ด ๋ฐ์ ๋๊ธฐ(busy polling)๋ค
sock.setblocking(False)
while True:
try:
data = sock.recv(4096) # ๋ฐ์ดํฐ ์์ผ๋ฉด ์ฆ์ ์์ธ
break
except BlockingIOError:
pass # ๊ณ์ ๋๋ฌผ์ โ ๊ทธ๋์ ์ฝ์ด๋ฅผ ํ์์ค๋ ๋๊ฐ ๋ฉ์ถ์ง๋ ์๋๋ค. ๋์ ์ฝ์ด ํ๋๋ฅผ ๋ถ์ก๊ณ โ๋๋?โ๋ง ๋ฐ๋ณตํ๋ค.
2. ๋ณดํต์ ๋ญ๋น๋ค โ epoll์ด ํ์ค์ธ ์ด์
busy polling์ ๋ฌธ์ ๋ ์ค๋น๋์ง ์์ ์์์๋ CPU๋ฅผ ๊ณ์ ์ด๋ค๋ ์ ์ด๋ค. ์์ผ ํ๋๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๊ธฐ๊น์ง ์์ญ ๋ฐ๋ฆฌ์ด๊ฐ ๊ฑธ๋ฆฐ๋ค๋ฉด, ๊ทธ ์ฌ์ด ์๋ฐฑ๋ง ๋ฒ์ ํ๋์ด ๋๋ฌป๋๋ค.
๊ทธ๋์ ํ์ค ํด๋ฒ์ ์ด์์ฒด์ ์ ๊ฐ์๋ฅผ ๋งก๊ธฐ๋ ๊ฒ์ด๋ค.
- non-blocking ์์ผ ์์ฒ ๊ฐ๋ฅผ ์ผ์ผ์ด ๋๋ฌป๋ ๋์ ,
epoll(๋ฆฌ๋ ์ค)ยทkqueue(BSDยทmacOS)์ โ์ค๋น๋ ๊ฒ๋ง ์๋ ค๋ฌ๋ผโ๊ณ ๋ฑ๋กํ๋ค- ์ค๋น๋ ์์๋ง ๊ณจ๋ผ ๊ทธ๋ ํ ๋ฒ ์ฝ๋๋ค
์ด๋ฌ๋ฉด ๋๋ฌป๋ ๋ญ๋น๊ฐ ์ฌ๋ผ์ง๋ค. event loop๊ฐ ์์ฒ ์ฐ๊ฒฐ์ ํ ์ค๋ ๋๋ก ๊ฐ๋นํ๋ ์๋ฆฌ๋ค. ์์ธํ ๋์์ O์ ์์ ๋ค๋ฃฌ๋ค.
3. ๊ทธ๋ฐ๋ฐ๋ ์คํ์ ํํ๋ ์ด์ โ ์ฌ์ฐ๊ธฐยท๊นจ์ฐ๊ธฐ ์ง์ฐ
blocking์ ๊ณต์ง๊ฐ ์๋๋ค. ์ค๋ ๋๊ฐ blocking์ผ๋ก ๋๊ธฐํ๋ฉด ์ปค๋์ด ๊ทธ ์ค๋ ๋๋ฅผ ์ฌ์ฐ๊ณ (sleep), ์์์ด ์ค๋น๋๋ฉด ๋ค์ ๊นจ์ด๋ค(wake).
์ด ๊ณผ์ ์๋ ๋น์ฉ์ด ๋ถ๋๋ค.
- ์ฌ์ฐ๊ณ ๊นจ์ฐ๋ ๋ ๋ฒ์ context switch
- ์ค์ผ์ค๋ฌ๊ฐ ๋ค์ ์ด ์ค๋ ๋๋ฅผ ๊ณจ๋ผ ์คํํ๊ธฐ๊น์ง์ ์ง์ฐ
- ๊นจ์ด๋ ๋ค ์์ด๋ฒ๋ฆฐ CPU ์บ์๋ฅผ ๋ค์ ์ฑ์ฐ๋ ๋น์ฉ
ํฉ์น๋ฉด ๋๋ต ์ ๋ง์ดํฌ๋ก์ด๋ค. ๋๋ถ๋ถ์ ํ๋ก๊ทธ๋จ์๋ ๋ฌด์ํ ๊ฐ์ด์ง๋ง ๋ง์ดํฌ๋ก์ด ๋จ์๊ฐ ์์ต์ ๊ฐ๋ฅด๋ ๋๋ฉ์ธ์์๋ ์ด ์ง์ฐ์ด ์๊น๋ค. ๊ทธ๋์ ์ค๋ ๋๋ฅผ ์์ ์ฌ์ฐ์ง ์๊ณ non-blocking ๊ณ์ ํ์ธํ๋ฉฐ ๊นจ์ด ์๊ฒ ๋๋ค.
ํธ๋ ์ด๋์คํ
busy polling์ ์ฝ์ด ํ๋๋ฅผ ํต์งธ๋ก ํ์ ๊ทธ ์ ๋ง์ดํฌ๋ก์ด์ ๊นจ์ฐ๊ธฐ ์ง์ฐ์ ์์ค๋ค. โCPU๋ฅผ ์ด๋คโ๊ฐ ๋จ์ ์ด ์๋๋ผ, ์ง์ฐ์ ์ฌ๊ธฐ ์ํด ์น๋ฅด๋ ๊ฐ์ด๋ค.
4. ์ค์ ๋ก ์คํ์ ์ฐ๋ ๊ณณ
- ๊ณ ๋น๋ ํธ๋ ์ด๋ฉ(HFT): ์ฃผ๋ฌธ ์ง์ฐ ๋๋ ธยท๋ง์ดํฌ๋ก์ด๊ฐ ์์ต์ผ๋ก ์ง๊ฒฐ๋๋ค. ์ค๋ ๋๋ฅผ ์ฌ์ฐ์ง ์๊ณ ์คํํ๋ฉฐ ์์ธ๋ฅผ ๋ฐ๋๋ค
- DPDK1 ๊ฐ์ ์ปค๋ ์ฐํ: ์ปค๋ ์ธํฐ๋ฝํธ์ ์์กดํ์ง ์๊ณ non-blocking์ผ๋ก NIC์ ๋ง ๋ฒํผ๋ฅผ ์ฌ์ง ์๊ณ ํด๋งํด ํจํท์ ๊ฐ์ ธ์จ๋ค
- ๋ฆฌ๋
์ค
SO_BUSY_POLLยท NAPI busy poll: ์์ผ ์์ ๊ฒฝ๋ก์ ์ง์ฐ์ ์ค์ด๋ ค ์ปค๋์ด ์ ๊น ์คํํ๋๋ก ์ผ๋ ์ต์ ์ด๋ค - spinlock: ๋ฝ์ ๊ธฐ๋ค๋ฆด ๋์ ์คํ. ๋ค์ ์ ์์ ๋ฐ๋ก ๋ณธ๋ค
5. spinlock โ ์งง์ ์๊ณ ๊ตฌ์ญ์ ์คํ
๋ฝ๋ ๊ฐ์ ์ ํ์ ๋์ธ๋ค. ๋ฝ์ ๋ชป ์ก์์ ๋ ๋ฌด์์ ํ ์ง๊ฐ ๊ฐ๋ฆฐ๋ค.
- ๋ฎคํ ์ค(blocking): ์ค๋ ๋๋ฅผ ์ฌ์ฐ๊ณ , ๋ฝ์ด ํ๋ฆฌ๋ฉด ๊นจ์ด๋ค
- spinlock(spinning): ์ฌ์ฐ์ง ์๊ณ ์งง๊ฒ ๊ณ์ ์๋ํ๋ค
while (!try_lock(&lock)) {
/* ์๋ฌด ์ผ๋ ํ์ง ์๊ณ ๋ค์ ์๋ โ spin */
}์๊ณ ๊ตฌ์ญ์ด ์์ฃผ ์งง์ผ๋ฉด ์ฌ์ ๋ค ๊นจ์ฐ๋ ๋น์ฉ์ด ์๊ณ ๊ตฌ์ญ ์์ฒด๋ณด๋ค ์ปค์ง๋ค. ์ด๋ด ๋๋ ์ ๊น ์คํํ๋ฉฐ ๊ธฐ๋ค๋ฆฌ๋ ํธ์ด ์ธ๋ค. ๋ฐ๋๋ก ์ค๋ ๊ฑธ๋ฆฌ๋ ๊ตฌ์ญ์ ์คํ์ผ๋ก ๊ธฐ๋ค๋ฆฌ๋ฉด ์ฝ์ด๋ฅผ ํ๋๋ฆฌ๋ฏ๋ก ์ํด๋ค. ๊ทธ๋์ spinlock์ โ์๊ณ ๊ตฌ์ญ์ด ์งง๊ณ ์ฌ์ฐ๊ธฐ ๋น์ฉ์ด ์๊น์ธ ๋โ๋ง ์ด๋ค. ๋ฉํฐ์ฝ์ด ์ปค๋ ๋ด๋ถ๊ฐ ๋ํ์ ์ธ ๋ฌด๋๋ค.
6. ์ ํ ๊ธฐ์ค โ blocking vs spin
| blocking (์ฌ์ฐ๊ธฐ) | spin (busy polling) | |
|---|---|---|
| ๋๊ธฐ ์ค CPU | ๋ฐ๋ฉ | ๊ณ์ ์ ์ |
| ๊นจ์ฐ๊ธฐ ์ง์ฐ | ์์(์ ๋ง์ดํฌ๋ก์ด) | ๊ฑฐ์ ์์ |
| ์ ํฉํ ์ํฉ | ๋๊ธฐ๊ฐ ๊ธธ๊ฑฐ๋ ์ธ์ ๋๋ ์ง ๋ชจ๋ฆ | ๋๊ธฐ๊ฐ ์งง๊ณ ์ง์ฐ์ด ์์ต์ ๊ฐ๋ฆ |
| ์ | ์ผ๋ฐ ์๋ฒ I/O, ๊ธด ๋ฝ | HFT, ์ปค๋ ์ฐํ, ์งง์ ๋ฝ |
blocking์ด ๊ธฐ๋ณธ๊ฐ์ด๊ณ spin์ ์์ธ๋ค. โ์ธ์ ๊นจ์ด๋ ์ง ๋ชจ๋ฅด๋ ๊ธด ๋๊ธฐโ์๋ ์ฌ์ฐ๋ ํธ์ด ๋ง๊ณ โ๊ณง ์ค๋น๋ ์งง์ ๋๊ธฐ + ๋ง์ดํฌ๋ก์ด๊ฐ ์๊น์ด ์ํฉโ์์๋ง ์คํ์ด ์ด๊ธด๋ค.
Footnotes
-
๋ฆฌ๋ ์ค ๋ฑ ๋ฒ์ฉ ์ด์์ฒด์ ์ ์ปค๋์ ์ฐํํ์ฌ(Kernel Bypass), ์ฌ์ฉ์ ๊ณต๊ฐ(User Space)์์ ๋คํธ์ํฌ ์ธํฐํ์ด์ค ์นด๋(NIC)์ ์ง์ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๊ฒ ํด์ฃผ๋ ์คํ์์ค ๊ณ ์ฑ๋ฅ ํจํท ์ฒ๋ฆฌ ํ๋ ์์ํฌ โฉ