Twisted에서 Select / poll 대 epoll 반응기의주의 사항


95

내가 읽고 경험 한 모든 것 (Tornado 기반 앱)은 ePoll이 특히 Twisted를 사용하는 Select 및 Poll 기반 네트워킹을 자연스럽게 대체한다고 믿게합니다. 그것은 나를 편집증으로 만듭니다. 더 나은 기술이나 방법론이 대가를 치르지 않는 것은 매우 드뭅니다.

epoll과 대안 사이의 수십 가지 비교를 읽어 보면 epoll이 속도와 확장 성의 챔피언임을 알 수 있습니다. 특히 환상적이고 선형적인 방식으로 확장된다는 것을 알 수 있습니다. 즉, 프로세서 및 메모리 사용률은 어떻습니까? epoll이 여전히 챔피언입니까?

답변:


190

매우 적은 수의 소켓 (물론 하드웨어에 따라 다르지만 10 개 이하의 정도에 대해 이야기하고 있음)의 경우 select can beat epoll in memory usage and runtime speed. 물론, 이렇게 적은 수의 소켓의 경우 두 메커니즘이 너무 빠르기 때문에 대부분의 경우이 차이에 대해 신경 쓰지 않습니다.

하지만 한 가지 설명이 있습니다. 선택 및 epoll 모두 선형으로 확장됩니다. 하지만 큰 차이점은 사용자 공간을 향한 API가 서로 다른 것을 기반으로하는 복잡성이 있다는 것입니다. select호출 비용은 전달하는 가장 높은 번호의 파일 설명 자의 값에 따라 대략적으로 달라집니다. 단일 fd (100)를 선택하면 단일 fd (50)를 선택하는 것보다 대략 두 배 더 비쌉니다. 가장 높은 값 아래에 fd를 더 추가하는 것은 무료가 아니므로 실제로는 이것보다 조금 더 복잡합니다. 대부분의 구현에서 좋은 첫 번째 근사치입니다.

epoll의 비용은 실제로 이벤트가있는 파일 설명 자의 수에 더 가깝습니다. 200 개의 파일 설명자를 모니터링하고 있지만 그중 100 개에만 이벤트가있는 경우 (대략) 100 개의 활성 파일 설명자에 대해서만 비용을 지불합니다. 이것은 epoll이 선택에 비해 주요 이점 중 하나를 제공하는 경향이 있습니다. 대부분 유휴 상태 인 1,000 명의 클라이언트가있는 경우 select를 사용할 때 여전히 1,000 명 모두에 대해 비용을 지불하게됩니다. 그러나 epoll을 사용하면 몇 개만있는 것과 같습니다. 주어진 시간에 활성화 된 항목에 대해서만 비용을 지불하면됩니다.

이 모든 것은 epoll이 대부분의 워크로드에서 CPU 사용량을 줄일 수 있음을 의미합니다. 메모리 사용량에 관한 한, 약간의 토스입니다. select필요한 모든 정보를 매우 간결한 방식으로 표현합니다 (파일 설명 자당 1 비트). 그리고 함께 사용할 수있는 파일 설명자 수에 대한 FD_SETSIZE (일반적으로 1024) 제한은 함께 사용할 수 select있는 3 개의 fd 세트 각각에 대해 128 바이트 이상을 소비하지 않음 을 의미합니다.select(읽기, 쓰기, 예외). 최대 384 바이트에 비해 epoll은 일종의 돼지입니다. 각 파일 설명자는 다중 바이트 구조로 표시됩니다. 그러나 절대적인 측면에서 여전히 많은 메모리를 사용하지 않을 것입니다. 수십 킬로바이트로 엄청난 수의 파일 설명자를 나타낼 수 있습니다 (파일 설명자 1000 개당 약 20k). 또한 select하나의 파일 설명 자만 모니터링하고 싶지만 그 값이 1024 인 경우 384 바이트를 모두 사용해야한다는 사실을 던질 수 있습니다. epoll을 사용하면 20 바이트 만 소비합니다. 그래도이 모든 숫자는 매우 작기 때문에 큰 차이는 없습니다.

그리고 epoll의 다른 이점도 있습니다. 이미 알고 계시 겠지만 FD_SETSIZE 파일 설명자에만 국한되지 않는다는 것입니다. 이를 사용하여 보유한 파일 설명자를 모니터링 할 수 있습니다. 그리고 파일 설명자가 하나만 있지만 그 값이 FD_SETSIZE보다 큰 경우 epoll도 함께 작동하지만 select그렇지 않습니다.

무작위로 최근 epollselect또는에 비해 약간의 단점을 발견했습니다 poll. 이 세 가지 API 중 어느 것도 일반 파일 (예 : 파일 시스템의 파일) 을 지원하지 select않으며 poll이러한 설명자를 항상 읽기 가능하고 쓰기 가능하다고보고하는 등의 지원 부족을 나타냅니다. 이로 인해 의미있는 종류의 비 차단 파일 시스템 I / O에는 적합하지 않습니다. 파일 시스템 에서 파일 설명자를 사용 select하거나 poll접하게되는 프로그램 은 적어도 계속 작동합니다 (또는 실패하면 그렇지 않습니다. 의 selectpoll), 그것을이기는하지만 아마도하지 최적의 성능으로.

반면 에은 (는) 이러한 파일 설명자를 모니터링하라는 요청을 받으면 epoll오류 ( EPERM분명히) 와 함께 빠르게 실패 합니다. 엄밀히 말해서 이것은 거의 틀리지 않습니다. 이는 명시적인 방식으로 지원 부족을 알리는 것일뿐입니다. 일반적으로 나는 명시적인 실패 조건에 박수를 보냅니다. 그러나 이것은 문서화되지 않았으며 (내가 말할 수있는 한) 잠재적으로 저하 된 성능으로 작동하는 애플리케이션이 아닌 완전히 손상된 애플리케이션이됩니다.

실제로 내가 본 유일한 장소는 stdio와 상호 작용할 때입니다. 사용자는 일반 파일에서 stdin 또는 stdout을 리디렉션 할 수 있습니다. 이전에는 stdin과 stdout이 파이프 였을 것입니다. epoll이 지원하는 것은 괜찮습니다. 그러면 일반 파일이되고 epoll이 크게 실패하여 응용 프로그램이 중단됩니다.


아주 좋은 대답입니다. poll완전성 을 위해 의 동작에 대해 명시 적으로 고려 하시겠습니까?
쿼크

6
일반 파일에서 읽는 동작에 대해 2 센트 : 저는 일반적으로 성능 저하보다 완전한 실패를 선호합니다. 그 이유는 개발 중에 탐지 될 가능성이 훨씬 더 높기 때문에 제대로 작동하기 때문입니다 (예 : 실제 파일에 대해 I / O를 수행하는 다른 방법을 사용하여). 물론 YMMV : 실패가 더 좋지 않은 경우 눈에 띄는 속도 저하가 없을 수 있습니다. 그러나 특수한 경우에만 발생하는 극적인 감속은 개발 중에 포착하기가 매우 어려울 수 있으며 실제로 배치되었을 때 시한 폭탄으로 남습니다.
쿼크

1
편집 내용을 완전히 읽어야합니다. 어떤 의미에서 나는 epoll이 전임자를 모방하지 않는 것이 옳지 않다는 데 동의하지만 EPERM 오류를 구현 한 개발자는 "항상 고장 났기 때문에 내 것을 깨는 것이 옳지 않다"고 생각할 수 있습니다. 잘." 그리고 또 다른 반론으로, 나는 방어적인 프로그래머로서 1 + 1 이후의 것은 의심스럽고 우아한 실패를 허용하는 방식으로 코딩합니다. 커널이 예상 외 오류를 발생시키는 것은 좋지 않거나 사려 깊지 않습니다.
David

1
@ Jean-Paul kqueue에 대한 설명도 추가 할 수 있습니까?
좋은 사람

성능을 제쳐두고, 이로 인한 문제 man select가 있습니까? Linux 커널은 고정 제한을 부과하지 않지만 glibc 구현은 FD_SETSIZE가 1024로 정의되고 FD _ * () 매크로가 다음에 따라 작동하는 고정 크기 유형으로 만듭니다. 그 한계. 1023보다 큰 파일 설명자를 모니터링하려면 대신 poll (2)를 사용하십시오. CentOS 7에서 커널이 1023보다 큰 파일 핸들을 반환했기 때문에 내 코드가 select ()에 실패한 문제를 이미 보았습니다. 현재 Twisted가 같은 문제에 부딪 힐 수있는 문제를보고 있습니다.
폴 D 스미스

4

우리 회사의 테스트에서 epoll ()에 대한 한 가지 문제가 발생하여 선택에 비해 단일 비용이 발생했습니다.

타임 아웃이있는 네트워크에서 읽기를 시도 할 때 epoll_fd (FD_SET 대신)를 생성하고 fd를 epoll_fd에 추가하는 것은 FD_SET (단순한 malloc)을 생성하는 것보다 훨씬 비쌉니다.

이전 답변에 따르면 프로세스의 FD 수가 많아 질수록 select () 비용이 더 많이 들지만 우리 테스트에서는 10,000의 fd 값을 사용하더라도 select가 여전히 승자였습니다. 이는 스레드가 대기중인 fd가 하나 뿐이고 차단 스레드 모델을 사용할 때 네트워크 읽기 및 네트워크 쓰기가 시간 초과되지 않는다는 사실을 극복하려고하는 경우입니다. 물론 블로킹 스레드 모델은 논 블로킹 리액터 시스템에 비해 성능이 낮지 만 특정 레거시 코드베이스와 통합하기 위해 필요한 경우가 있습니다.

이런 종류의 사용 사례는 고성능 애플리케이션에서는 드물다. 반응기 모델은 매번 새로운 epoll_fd를 생성 할 필요가 없기 때문이다. epoll_fd가 오래 지속되는 모델의 경우 --- 고성능 서버 설계에 분명히 선호되는 --- epoll은 모든면에서 확실한 승자입니다.


5
그러나 select()FD_SETSIZE를 변경하기 위해 시스템의 절반을 다시 컴파일하지 않는 한 10k + 범위의 파일 설명자 값이있는 경우 에도 사용할 수 없으므로이 전략이 어떻게 작동하는지 궁금합니다. 당신이 설명하는 시나리오의 경우, 아마 볼 것 poll()같은 훨씬 더되는 select()이 같은보다는 epoll()하지만 FD_SETSIZE 제한을 제거 -.
Jean-Paul Calderone 2014

FD_SET를 malloc () 할 수 있기 때문에 10K 범위의 파일 설명자 값이있는 경우 select ()를 사용할 수 있습니다. 사실, FD_SETSIZE는 컴파일 시간이고 실제 fd 제한은 런타임에 있기 때문에 FD_SET의 유일한 안전한 사용은 FD_SET의 크기에 대해 파일 설명 자의 수를 확인하고 FD_SET이 너무 작은. 나는 고객과 함께 생산 중에 이것을 보았을 때 충격을 받았습니다. 20 년 동안 소켓을 프로그래밍 한 후 내가 작성한 모든 코드와 웹상의 대부분의 튜토리얼은 안전하지 않습니다.
Brian Bulkowski 2014 년

5
내가 아는 한 인기있는 플랫폼에서는 사실이 아닙니다. C 라이브러리가 컴파일 FD_SETSIZE될 때 설정되는 컴파일 시간 상수입니다 . 응용 프로그램을 빌드 할 때 다른 값으로 정의하면 응용 프로그램과 C 라이브러리가 동의하지 않고 일이 제대로 진행되지 않습니다. 재정의하는 것이 안전하다고 주장하는 참조가 있다면 보고 싶습니다. FD_SETSIZE
Jean-Paul Calderone 2014 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.