기술적으로 Erlang의 프로세스가 OS 스레드보다 효율적인 이유는 무엇입니까?


170

얼랭의 특성

에서 얼랑 프로그래밍 (2009 년) :

Erlang 동시성은 빠르고 확장 가능합니다. Erlang 가상 머신은 생성 된 모든 프로세스에 대해 OS 스레드를 생성하지 않기 때문에 프로세스가 간단합니다. 기본 운영 체제와 상관없이 VM에서 생성, 예약 및 처리됩니다. 결과적으로 프로세스 작성 시간은 마이크로 초 단위이며 동시에 존재하는 프로세스 수와 무관합니다. 이를 Java 및 C #과 비교하십시오. 모든 프로세스에 대해 기본 OS 스레드가 작성됩니다. Erlang을 사용하면 두 언어보다 성능이 훨씬 뛰어납니다.

에서 동시성 얼랑 (PDF)에서 지향 프로그래밍 (슬라이드) (2003)

Erlang 프로세스를 만드는 데 걸리는 시간은 1µs에서 2,500 프로세스까지 일정합니다. 이후 최대 30,000 개의 프로세스에서 약 3µs까지 증가합니다. Java 및 C #의 성능이 그림의 맨 위에 표시됩니다. 프로세스 수가 적 으면 프로세스를 만드는 데 약 300µs가 걸립니다. 2 천 개 이상의 프로세스를 만드는 것은 불가능합니다.

최대 30,000 개의 프로세스에서 두 Erlang 프로세스간에 메시지를 보내는 시간은 약 0.8µs입니다. C #의 경우 최대 프로세스 수 (약 1800 개 프로세스)까지 메시지 당 약 50µs가 걸립니다. Java는 훨씬 더 나빴습니다. 최대 100 개의 프로세스에 대해 메시지 당 약 50µs가 걸리고 그 후 약 1000 개의 Java 프로세스가있을 때 메시지 당 10ms로 빠르게 증가했습니다.

내 생각

Erlang 프로세스가 새로운 프로세스를 생성하는 데 훨씬 더 효율적이고 프로세스 당 메모리 풋 프린트가 훨씬 작은 이유를 기술적으로 완전히 이해하지 못했습니다. OS와 Erlang VM은 모두 스케줄링, 컨텍스트 전환을 수행하고 레지스터의 값을 추적해야합니다.

왜 Erlang의 프로세스와 동일한 방식으로 OS 스레드가 구현되지 않습니까? 그들은 더 많은 것을 지원해야합니까? 그리고 왜 더 큰 메모리 공간이 필요합니까? 왜 산란과 의사 소통이 느려 집니까?

기술적으로 Erlang의 프로세스가 생성 및 통신에있어 OS 스레드보다 더 효율적인 이유는 무엇입니까? 그리고 왜 OS의 스레드가 동일한 효율적인 방식으로 구현되고 관리 될 수 없습니까? 왜 OS 스레드가 더 큰 메모리 풋 프린트와 더 느린 스폰 및 통신을 갖습니까?

더 많은 독서


1
가설이 참인 이유를 이해하기 전에 가설이 참 인지 여부 를 입증해야합니다 ( 예 : 증거에 의해 뒷받침 됨). Erlang 프로세스 최신 JVM의 Java 스레드보다 실제로 더 효율적 이라는 것을 보여주는 유사한 유사 비교에 대한 참조 있습니까? 아니면 OS 프로세스 및 스레드 지원을 직접 사용하는 C 앱입니까? (후자는 나에게는 매우 가능성이 거의없는 것 같습니다. 전자는 다소 가능성이 있습니다.) 제한된 환경 (프란치스코의 관점)에서는 사실 일 수도 있지만 숫자를보고 싶습니다.
TJ Crowder

1
@Donal : 다른 많은 절대 진술과 마찬가지로. :-)
TJ Crowder

1
@Jonas : 고맙지 만 날짜 (1998-11-02)와 JVM 버전 (1.1.6)까지 멈췄습니다. 썬의 JVM은 지난 11.5 년 동안 , 특히 스레딩 영역에서 상당히 개선되었습니다. (단지, 가설이 사실이 아니라고 말하는 것은 아닙니다. (프란시스코와 도날은 왜 Erland가 Erland가 무언가를 할 수 있는지 지적했습니다.) 없이 검사중인).
TJ 크라우

1
@Jonas : "...하지만 Erlang에서 할 수있을 것 같아요 ..." 그 "추측"부분입니다. :-) Erlang의 프로세스 전환이 수천 개 이상으로 확대 될 것으로 추측 하고 있습니다. 당신이있어 추측 너무 잘 Java 또는 OS 스레드에 비해 않는다는 것을. 추측과 소프트웨어 개발은 ​​훌륭한 조합이 아닙니다. :-) 그러나 나는 나의 주장을했다.
TJ Crowder

17
@TJ Crowder : erlang을 설치하고 실행 erl +P 1000100 +hms 100하고 유형 {_, PIDs} = timer:tc(lists,map,[fun(_)->spawn(fun()->receive stop -> ok end end) end, lists:seq(1,1000000)]).보다 3 분 정도 기다렸다가 결과를 기다립니다. 너무 간단합니다. 내 노트북에는 프로세스 당 140us와 1GB의 전체 RAM이 필요합니다. 그러나 직접 쉘 형태이므로 컴파일 된 코드에서 더 좋습니다.
Hynek -Pichi- Vychodil

답변:


113

몇 가지 기여 요인이 있습니다.

  1. Erlang 프로세스는 OS 프로세스가 아닙니다. Erlang VM은 경량의 협업 스레딩 모델을 사용하여 Erlang VM에 의해 구현됩니다 (Erlang 수준에서는 선제 적이지만 협력 적으로 예약 된 런타임 제어하에 있음). 이는 알려진 제어 지점에서만 전환하므로 전체 CPU 상태 (일반, SSE 및 FPU 레지스터, 주소 공간 매핑 등)를 저장할 필요가 없기 때문에 컨텍스트 전환이 훨씬 저렴하다는 것을 의미합니다.
  2. Erlang 프로세스는 동적으로 할당 된 스택을 사용하며, 매우 작은 규모로 시작하여 필요에 따라 확장됩니다. 이를 통해 사용 가능한 모든 RAM을 빨아 들이지 않고도 수천, 심지어 수백만 개의 Erlang 프로세스를 생성 할 수 있습니다.
  3. Erlang은 단일 스레드였으며 프로세스 간 스레드 안전성을 보장 할 필요가 없었습니다. 이제 SMP를 지원하지만 동일한 스케줄러 / 코어에서 Erlang 프로세스 간의 상호 작용은 여전히 ​​매우 가볍습니다 (코어마다 별도의 실행 큐가 있음).

6
두 번째 포인트 : 프로세스가 아직 실행되지 않은 경우 스택을 할당 할 이유가 없습니다. 또한 : 메모리를 수집하지 않도록 프로세스의 GC를 조정하여 몇 가지 트릭을 재생할 수 있습니다. 그러나 그것은 발전하고 다소 위험합니다 :)
나는 크랩 답변을 제공합니다

3
세 번째 요점 : Erlang은 불변 데이터를 적용하므로 SMP를 도입하면 스레드 안전성에 영향을 미치지 않습니다.
nilskp

@nilskp, 맞습니다 .erlang도 함수형 프로그래밍 언어입니다. 따라서 "가변"데이터가 없으므로 스레드 안전성이 발생합니다.
liuyang1

6
@nilskp : (RE : 당신은 포인트 3에 대해 언급합니다…) 언어 자체에는 불변의 타입 시스템이 있지만, 기본 구현 (메시지 전달, 스케줄러 등)은 완전히 다른 이야기입니다. 스위치 조작만으로 정확하고 효율적인 SMP 지원이 이루어지지 않았습니다.
Marcelo Cantos

@rvirding : 명확한 부록에 감사드립니다. 나는 당신의 요점을 나의 대답의 본문에 통합 할 자유를 얻었습니다.
Marcelo Cantos

73

좀 더 조사한 후 Joe Armstrong의 프레젠테이션을 찾았습니다.

에서 얼랑 - 동시 세계 (프레젠테이션) 소프트웨어 (13 분에) :

[Erlang]은 동시 언어입니다. 즉, 스레드는 프로그래밍 언어의 일부이며 운영 체제에 속하지 않습니다. 그것은 실제로 Java 및 C ++와 같은 프로그래밍 언어의 문제입니다. 스레드는 프로그래밍 언어가 아니며 스레드는 운영 체제에있는 것으로 운영 체제에있는 모든 문제를 상속합니다. 문제 중 하나는 메모리 관리 시스템의 세분성입니다. 운영 체제의 메모리 관리는 전체 메모리 페이지를 보호하므로 스레드가 될 수있는 가장 작은 크기는 페이지의 가장 작은 크기입니다. 실제로 너무 큽니다.

당신이 당신의 컴퓨터에 더 많은 메모리를 추가하는 경우 - 당신은 페이지 테이블의 세분화가 진행되도록 메모리를 보호하는 비트 수가 같아 - 당신은 몇 백 바이트에서 실행 알고 프로세스에 대한 말의 64KB의를 사용하여 끝낸다.

나는 그것이 전부는 아니지만 적어도 내 질문에 대한 답이라고 생각합니다.



2
스택의 메모리 보호는 이유가 있습니다. Erlang은 프로세서의 MMU를 통해 다른 실행 컨텍스트의 스택을 보호하지 않습니까? 스레드가 작은 스택보다 더 많은 것을 사용한다면 어떨까요? (더 큰 스택이 필요한지 확인하기 위해 모든 스택 할당을 확인 했습니까? 스택이 움직일 수 있습니까?)
Thanatos

2
@Thanatos : Erlang은 프로그램이 메모리에 액세스하거나 스택과 바이올린을 사용할 수 없습니다. 모든 할당은 힙과 스택 모두 관리 런타임을 거쳐야합니다. 즉, 하드웨어 보호는 어쨌든 일어날 수없는 일을 방지하기 때문에 쓸모가 없습니다. 언어는 포인터 안전, 스택 안전, 메모리 안전 및 유형 안전입니다. 스택은 필요에 따라 커지기 때문에 프로세스는 "작은 스택"이상을 사용할 수 없습니다. 당신은 그것을 작은 것의 반대라고 생각할 수 있습니다 : 무한히 크다. (그러나 게으르게 할당 됨)
Jörg W Mittag

4
Microsoft Research의 특이점 운영 체제를 살펴보십시오. 특이점에서 모든 코드, 커널, 장치 드라이버, 라이브러리 및 사용자 프로그램은 전체 커널 권한으로 링 0에서 실행됩니다. 모든 코드, 커널, 장치 드라이버, 라이브러리 및 사용자 프로그램은 메모리 보호없이 단일 플랫 물리적 주소 공간에서 실행됩니다. 팀은 언어 보장이 MMU가 보장하는 것보다 훨씬 강력하다는 것을 발견했으며 동시에 MMU를 사용하면 성능이 최대 30 % (!!!)까지 상승했습니다. 그렇다면 어쨌든 MMU를 사용하는 이유는 무엇입니까?
Jörg W Mittag

1
OS / 400 운영 체제는 같은 방식으로 작동합니다. 모든 프로그램에는 단일 주소 공간이 하나만 있습니다. 오늘날 실제로 사용되는 대부분의 언어는 동일한 안전 속성 (ECMAScript, Java, C♯, VB.NET, PHP, Perl, Python, Ruby, Clojure, Scala, Kotlin, Groovy, Ceylon, F♯, OCaml, "Objective-C"의 "Objective"부분, "C ++"의 "++"부분). 레거시 C 코드 및 C ++ 및 Objective-C의 레거시 기능이 아니라면 더 이상 가상 메모리가 필요하지 않습니다.
Jörg W Mittag

47

어셈블러에서 코 루틴을 구현하고 성능을 측정했습니다.

Erlang 프로세스로 알려진 코 루틴 간 전환은 최신 프로세서에서 약 16 개의 명령과 20 나노초가 걸립니다. 또한 전환하려는 프로세스 (예 : 대기열에서 메시지를 수신하는 프로세스를 호출 프로세스에서 수신 프로세스로 직접 전달할 수 있음)를 알고 있으므로 스케줄러가 작동하지 않습니다. 그것은 O (1) 연산입니다.

OS 스레드를 전환하려면 커널을 호출하기 때문에 약 500-1000 나노초가 걸립니다. OS 스레드 스케줄러는 O (log (n)) 또는 O (log (log (n))) 시간에 실행될 수 있으며, 수만 또는 수백만 개의 스레드가있는 경우 눈에 띄기 시작합니다.

따라서 스위칭의 기본 작업이 더 빠르며 스케줄러가 덜 자주 실행되므로 Erlang 프로세스가 더 빠르고 확장 성이 뛰어납니다.


33

Erlang 프로세스는 (대략) 다른 언어의 녹색 스레드 에 해당 합니다. 프로세스간에 OS 강제 분리가 없습니다. (언어 강제 분리가있을 수 있지만 Erlang이 다른 것보다 더 나은 작업을 수행하더라도 보호 수준은 떨어집니다.) 너무 가벼워서 훨씬 더 광범위하게 사용할 수 있습니다.

반면에 OS 스레드는 다른 CPU 코어에서 간단하게 예약 할 수 있으며 독립적 인 CPU 바인딩 처리를 지원할 수 있습니다. OS 프로세스는 OS 스레드와 비슷하지만 OS 강제 분리가 훨씬 강력합니다. 이러한 기능의 가격은 OS 스레드 및 프로세스가 더 비싸다는 것입니다.


차이점을 이해하는 또 다른 방법은 이것입니다. JVM 위에 Erlang 구현을 작성한다고 가정하면 (특히 미친 제안은 아님) 각 Erlang 프로세스를 상태가있는 객체로 만듭니다. 그런 다음 Erlang 프로세스를 실행하는 스레드 인스턴스 풀 (일반적으로 호스트 시스템의 코어 수에 따라 크기가 조정 됨)이 실제 Erlang 런타임 BTW에서 조정 가능한 매개 변수입니다. 그러면 사용 가능한 실제 시스템 리소스에 수행 할 작업이 분산됩니다. 작업을 수행하는 매우 깔끔한 방법이지만 완전히 의존합니다.각각의 개별 Erlang 프로세스가 그다지 많은 것을하지 않는다는 사실에. 물론 괜찮습니다. Erlang은 개별 프로세스가 프로그램을 실행하는 프로세스의 전체 앙상블이므로 무거운 프로세스를 요구하지 않도록 구성되었습니다.

여러면에서 실제 문제는 용어 중 하나입니다. Erlang이 프로세스를 호출하는 것 (그리고 CSP, CCS, 특히 π- 미적분에서 동일한 개념에 강력하게 대응하는 것)은 C 헤리티지 언어 (C ++, Java, C # 및 다른 많은 것들) 프로세스 또는 스레드를 호출하십시오. 있습니다 어떤 유사성 (모든 동시 실행의 몇 가지 개념을 포함한다)하지만 동등한 확실히 없다. 누군가가“공정”이라고 말할 때주의하십시오. 그들은 완전히 다른 것을 의미하는 것으로 이해할 수도 있습니다…


3
Erlang은 Pi Calculus와 가까운 곳이 아닙니다. Pi 미적분은 변수에 바인딩 될 수있는 채널을 통한 동기 이벤트를 가정합니다. 이런 종류의 개념은 Erlang 모델에 전혀 맞지 않습니다. Erlang과 더 가까운 Calculus에 참여해보십시오. 그래도 여전히 일부 메시지와 기본 메시지에 참여할 수 있어야합니다. 이를 구현 한 JErlang 전용이라는 논문 (및 프로젝트)이있었습니다.
나는 끔찍한 조언을한다

그것은 pi-calculus를 정확히 보는 것에 달려 있습니다 (동기 채널과 버퍼 프로세스로 비동기 채널을 모델링 할 수 있습니다).
Donal Fellows

Erlang 프로세스는 가볍지 만 왜 작은 공간을 차지하는지 (가벼운) 왜 OS 스레드보다 성능이 좋은지 설명하지 않습니다.
조나스

1
@Jonas : 일부 유형의 작업 (특히 계산이 많은 작업)의 경우 OS 스레드가 더 좋습니다. 일반적으로 Erlang이 사용되는 작업은 아닙니다. Erlang은 많은 수의 간단한 의사 소통 작업에 중점을두고 있습니다. 이를 통해 얻을 수있는 이점 중 하나는 해결 방법을 제시하고 결과를 기다리는 작업 그룹의 경우 단일 프로세서의 단일 OS 스레드에서 수행 할 수 있다는 것입니다. 컨텍스트 스위치가 있습니다.
Donal Fellows

이론적으로 매우 작은 스택을 사용하고 할당 된 다른 스레드 관련 리소스의 수를 신중하게 제어하여 OS 스레드를 매우 저렴하게 만들 수 있지만 실제로는 문제가 있습니다. (스택 요구 사항을 예측하는 것은 다소 까다로운 작업입니다.) 대신 OS 스레드는 그 수가 적거나 (CPU 코어 수의 순서) 더 중요한 경우에 최적으로 설계되었습니다. 각각의 처리량.
Donal Fellows

3

Jonas는 OS 스레드를 Erlang 프로세스와 비교하는 데 많은 숫자를 원했다고 생각합니다. 프로그래밍 얼랭 (Erlang)의 저자 인 조 암스트롱 (Joe Armstrong)은 얼랭 (Erlang) 프로세스 생성의 OS 스레드로의 확장 성을 다시 테스트했습니다. 그는 Erlang에서 간단한 웹 서버를 작성하여 다중 스레드 Apache에 대해 테스트했습니다 (Apache가 OS 스레드를 사용하므로). 1998 년으로 거슬러 올라가는 데이터가있는 오래된 웹 사이트가 있습니다. 나는 그 사이트를 정확히 한 번만 찾을 수있었습니다. 그래서 링크를 제공 할 수 없습니다. 그러나 정보가 있습니다. 이 연구의 주요 요점은 Apache가 8K 이하의 프로세스에서 최대치를 기록한 반면 Erlang 서버는 10K 이상의 프로세스를 처리했습니다.


5
나는 이것에 대해 이야기하고 있다고 생각합니다 : sics.se/~joe/apachevsyaws.html 그러나 erlang이 kerlenl 스레드와 비교하여 스레드를 어떻게 효율적으로 만드는지 물었습니다.
Jonas

@Jonas 링크가 종료되었습니다. 마지막 스냅 샷은 여기
알바 g

1
"아파치는 약 4,000 개의 병렬 세션에서 죽는다. Yaws는 여전히 80,000 개 이상의 병렬 연결에서 작동하고있다."
Nathan Long

citeseerx.ist.psu.edu/viewdoc/ 에서 전체 기사를 참조하십시오. 사실, 아파치 서버를 중지하기는 쉽지만 16 대의 공격 시스템을 사용하여 Erlang 서버를 중단 할 수 없음이 입증되었습니다.
Bernhard


0

이유는 erlang 프로세스가 OS가 아니라 evm (erlang 가상 머신)에 생성되므로 비용이 더 적기 때문입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.