windowns의 IOCP( overlapped I/O) 와 Epoll...

bsakiag의 이미지

갑자기 개념적으로 혼동이 생깁니다.
windows의 IOCP 또는 Overlapped I/O 에서의 가장큰 장점은,네트웍프로그래밍의 경우,
사용자가 지정한 buffer로 바로 읽어들일 수 있다는 것이라고 생각하는데요..
즉, 기존의 커널 메모리에서 사용자 메모리로 2번에 걸쳐서 복사되던것을 한번에 얻어올수 있지요.

그런데 지금 Epoll 쪽을 보고 있는데, Epoll도 위와 마찬가지로 한번에 얻어올 수 있는지
아니면 기존과 마찬가지로 커널 메모리를 거쳐서 2번에 얻어오는것인지 혼동됩니다.

처음엔 windows의 overlapped I/O와 같은 방식으로 어렴풋이 알고 있었는데
지금 다시 보니 아닌거 같다는 느낌이 들어서요..

혹시 확실히 알고 계신분이 있다면 설명좀 부탁합니다.

그럼..이만.

neogeo의 이미지

뭐 몇번 거치냐도 성능에 영향을 주겠지만, IOCP와 EPOLL, KQueue 의 공통점은 기존의 전형적인 I/O 모델을 탈피하고,

Async 하며 thread-safe 한 I/O를 OS 레벨에서 제공하였다는게 가장 성능에 영향을 주었습니다.

기존의 I/O들은 Async 하더라도 thread-safe 자체를 직접 구현해야 하거나, Async 하지 않은 I/O 였기에 엄청난 Thread 의 대기상태를 야기했죠.

메모리에 복사했다 올리는 내용 자체도 분명 overhead가 있는건 맞습니다만, IOCP 같은 녀석은 근본적으로 기존의 I/O와 접근방식을 ( 특히 multi thread 에서 )

다르게 해야합니다.

thread 대기를 최소화 하고 thread 자체가 I/O를 polling 하지 않아도 되었다는것이 성능향상의 제일 큰 내용입니다.

이를 보장하기 위해서 OS가 직접적으로 buffer 를 관리하고 event ( 혹은 interrupt )를 발생시키며 적절한 port ( IOCP 에선 port 이죠 ) 에 알아서 data를

잘 가져다 준다는 것이 핵심입니다. ( OS 가 직접적으로 buffer 를 관리한다는 개념이 꼭 사용자 - 커널 레벨의 메모리 복사를 생략했다라는 의미로 받아들이시지는

않아도 상관없을것입니다. 사용자 혹은 app 레벨에서 보는 메모리버퍼에다 직접 커널이 driver에서 내용을 채워줄 수도 있으니까요. )

Neogeo - Future is Now.

Neogeo - Future is Now.

bsakiag의 이미지

제 질문에 답이 안달려서 꼬박 하루를 인터넷 서핑에만 매달렸는데.. 오히려 의문만 더 붙어버렸습니다.
처음의 의문은 linux의 epoll도 win32의 overlapped I/O 처럼 커널 메모리를 거치지 않고 user process로 데이터를 받을 수 있는가..? 였지만..
인터넷에 찾아보면, 질문의 답은 찾을 수가 없고, 이런 방식이(Zero Copy) (상대적으로..) 그리 빠르지도 않고 안전하지도 않다..뭐 대충이런 식이었습니다.

대표적인 글이 http://msdn.microsoft.com/ko-kr/magazine/cc302334(en-us).aspx 의 "Who Manages the Buffers?" 단락입니다. (꽤 유명한 분의 글이라고 합니다. 신뢰도 100%라고 할수 있는..)
그런데 이게 이해가 안갑니다.
극단적인 예로 UDP Streaming 데이터의 경우는 각 패킷들이 커널 버퍼 한번 생략하는것은 무시하지 못할 정도로 퍼포먼스 향상이 예상되는데..이게 별로다...라고 하니 참 난감하네요.

암튼 neogeo 님의 설명은 충분히 이해가고 공감합니다만, 저의 촛점은 Zero-Copy였기에..
좀 갈증이 남아 있습니다.

결론은 linux epoll은 win32의 Overlapped I/O와 같은 Zero-Copy 방식은 지원하지 않는다..로 생각됩니다. (커널 메모리를 거치지 않는다는 그 어떤 문구도 epoll에 대해서는 찾을 수가 없었습니다.)

누군가 이 주제에 대해 자세히 설명좀 해주었으면...하는 바램입니다.

feanor의 이미지

리눅스 epoll은 zero copy 못합니다. 아니 zero copy는 epoll의 기능 범위?에 속하는 기능이 아닙니다.

리눅스에서 zero copy는 splice, vmsplice, tee 시스템 콜로 구현되어 있습니다. 이것과 epoll을 합치면 Overlapped I/O 비슷한 효과가 나겠지요.

(아래 분이 이야기하신 sendfile도 비슷한 내용인데, 요즘 커널에서 실제로 sendfile은 splice 시스템 콜로 구현되어 있습니다.)

neogeo의 이미지

메모리 copy 자체가 over head 가 크다는 것은 그다지 공감하기 힘든 사항입니다. 커널 버퍼 한번 생략이
무시못할 퍼포 향상을 예측하시는데, context switch 자체가 이미 메모리 copy 와 레지스터 clear를 야기하기 때문에, 현대의 pipe line 에 기반한 분기예측성을 지닌 CPU 에선 더욱 치명적입니다. 메모리 복사는 심지어
cpu 에서 파이프라인상에서 그냥 명령 때려서 싹 밀어놓고 다른일 할 수도 있습니다.

아시다시피 udp 라고 하더라도 한번에 오는 패킷양은 정해져있고(mtu 등~), UDP는 순서같은게 보장이 되지 않기에
어차피 driver에서 받는 족족 올리면 땡이지요. 수많은 양을 무지하게 udp로 날라온다 하더라도, ddos 등의 공격이
아닌 이상에야 어차피 몇 클럭이면 충분히 해결될 문제입니다. 그러나 context switch는 이야기가 다릅니다.
우선 응답성이 크께 저하됩니다. 또한 CPU 파이프라인이 길면 길수록 엄청난 손해를 보게됩니다. ZERO copy보다 I/O기다리느라 thread 가 block 되어 context switch 가 일어난다면 그 손해는 수십 clock 이 되어버립니다.

현대의 CPU에서 zoro copy 가 주는 이점이 없다고는 말 못하지만 그 상황에 따라 잘 생각해보면 그렇게 크게 얻는 이득이 없다 입니다.

병목현상이 발생할때 병목 지점을 주면 전체의 소통이 아주 원활해 보이겠지요.

마찬가지로 I/O ( network 포함 ) 에서의 병목은 driver -> 커널 buffer -> 사용자 buffer 의 복사때문이 아니라, 그 I/O 때문에 block 된 thread 나 process 가 context switch 로 빠져나가는 현상이 원인이 될 확률이 훨씬 높다는 말씀을 드리고 싶습니다.

물론 큰 파일을 계속해서 다루는 상황에서는 당연히 zero-copy 가 주는 이점이 훨씬 큽니다. epoll 의 경우보단 자세한건 sendfile() 을 살펴보시는게 좋을 것 같습니다. ( epoll 자체는 zero-copy 와 별로 관계가 없습니다. 받는 경우는 read() 가 아마 라이브러리에 따라 zero-copy 를 지원할 수 있는걸로 알고 있습니다만 확실하진 않습니다. )

IOCP만 하더라도 context switch 가 얼마나 무서운줄 알기에 thread 갯수를 일부러 줄여서 돌리는 pool 방식을 고수하고 있지요.

여하튼 이게 상황에 따라 굉장히 미묘하지만 저는 게임필드에서 주로 일하고 thread 가 많이 필요한 서버 환경을 주로 공부하기 때문에 위와같이 이해하고 있습니다. 만약 파일을 주로 제공하면서 thread 가 많이 필요하지 않은 서버라면 아마 말씀대로 zero-copy가 매우 critical 할 수 있습니다.

IOCP는 이런점에서 상당히 전천후적인 녀석이라고 할 수 있겠네요. 여하튼 원하시는 목적이 무언가 잘 생각해보셔서 어느쪽이 이득일까는 실험적으로 얻으시는게 좋을 것 같습니다.

Neogeo - Future is Now.

Neogeo - Future is Now.

nineye의 이미지

질문의 요지를 잘못 해석 하신 것 같네요...
질문자는 linux에서의 epoll과 windows에서의 IOCP의 성능 차이에 대해 질문하셨는데,
기존 IO방식과의 차이점에 대해서만 글을 쓰신 것 같습니다.
IOCP가 생성되는 thread를 최소화 해서 context switching의 overhead를 없애는 것이 가장 큰 성능상의 장점이라고 한다면,
이는 epoll도 마찬가지로 non-blocking socket + edge triggered epoll을 이용하면, thread를 최소화 할 수 있습니다.
따라서 질문자께서는 이제 차이나는 것이 커널 모드에서 유저 모드로의 데이터 스트림 복사가 epoll보다 IOCP가 빠른
주된 원인이 아니냐... 라고 질문 하신 것 같습니다.
저도 참 궁금하네요. 왜 IOCP가 빠른지...
물론 windows의 winsock2 라이브러리에서의 overlapped IO는 몇 가지 트릭(?)을 사용하여 성능을 높여주긴 합니다.
예를 들면, 생성되는 소켓의 정보를 저장하는 공간을 os가 관리하는 페이징 되지 않는 메모리로 사용한다든지,
위에서 말씀하신 것처럼 유저버퍼로 직접 전송되는 데이터를 저장하게 한다든지 하는...
이것 이외에 기술적으로 차이나는 부분이 있는지 모르겠네요...

_________________________________________________________

nineye's blog

bsakiag의 이미지

정말 감사드립니다.
인터넷 어디서도 볼 수 없었던 지식을 얻은듯합니다.

사실은 voip 같은, 동접자가 많지 않으면서 rtp streaming의 경우를 염두에두고 overlapped i/o, epoll 등을 접근했기 때문에.. Zero-copy에 욕심이 생겼던 것입니다.

서로 사는 동네가 다른 epoll과 zero-copy를 자꾸 엮으려고 했네요.

암튼 개념적으로는 많이 명확해진 느낌입니다.

여담이지만... MS의 document system은 정말 칭찬할만하다..는 것.(양과 질, 그리고 편의성에 있어서..)
그리고, 리눅스 진영의 document 는 예상은 했지만..상대적으로 한마디로 너무 힘들다(?)는것을
말하고 싶네요.
하기야..돈이 넘쳐나는 곳과 비교하면 안되겠지만 말이지요.

그럼..이만..

shyblue의 이미지

뭐, 익숙해지다 보면, MSDN이 가끔은 더 불편할때도 있습니다.(양이 너무 많아서, 찾는 시간이 더 걸릴 수도 있다는.
정말 필요한 정보는 리눅스 진영이나 오픈소스 진영도 찾아보면 있습니다. 그리고, 정말 없다면, 소스 뜯으면 됩니다. >.<
(사실, 급할대는 오히려 소스를 뜯어봅니다. ;;)

時日也放聲大哭

時日也放聲大哭

sharefeel의 이미지

HP-UX 는 문서가 없을 뿐 아니라 커널 소스도 없습니다.
헤더파일 보면서 작업하고 있지만,
'이름을 보니 이런 일을 하는 함수겠군..'
이라고 생각하면서 작업하고 있다는 사실에 엄청 위기감을 느낍니다.

소스가 공개된 리눅스는 그나마 행복한 상황같습니다.
===============
Vas Rel Por

===============
Vas Rel Por

태훈의 이미지

구글링하다가 제가 하고 있는 분야에 대한 쓰레드가 있어서 보다가 잘못된 내용에 대해 오해 하실까봐 답글 달아둡니다.

Zero-Copy가 네트웍 성능 향상에 크게 기여하지 않는다고 하시는데...

실제 해본 바로는 차이가 큽니다.

동일한 네트워크 칩을 사용해서 대략 두배가까이 성능 차이가 났습니다.

결론은 네트워크 성능 향상이 주된 목적이라면 Zero-Copy를 구현하는게 좋다! 라는 것입니다.

PS. 리눅스 네트웍 드라이버 개발자 입니다.(딴짓도 많이 하지만..--)

Just do it!

neogeo의 이미지


상황묘사가 좀 애매한데, zero copy 를 구현하지 말라는 소리가 아니라,

'작은 패킷이 엄청나게 여러 client 와 자주 오가는 서버 모델의 경우는 zero-copy가 주는 이점때문에 IOCP를 사용하는게 아니다' 라는 의미 입니다.

zero copy 는 일정이상의 사이즈가 되는 패킷을 주고받을 때 이득이 비교적 클경우가 많기 때문입니다.

아주 작은 패킷이 자주 오가는 상황에선 IOCP 의 thread pool 개념이 더욱 중요한 퍼포먼스의 상승 이슈라고 생각합니다.

Neogeo - Future is Now.

Neogeo - Future is Now.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.