멀티 스레드 JavaScript 런타임 구현의 단점은 무엇입니까? [닫은]


51

지난 주 동안 멀티 스레드 JavaScript 런타임 구현을 작업했습니다. JavaScriptCore 및 boost를 사용하여 C ++로 만든 개념 증명이 있습니다.

아키텍처는 간단합니다. 런타임에서 기본 스크립트 평가가 완료되면 스레드 풀이 시작되고 스레드 우선 순위에 참여하여 공유 우선 순위 큐에서 태스크 선택을 시작합니다. 두 태스크가 동시에 변수에 액세스하려고하면 원자로 표시되고 액세스를 위해 경쟁합니다. .

멀티 스레드 node.js 런타임 작업

문제는이 디자인을 JavaScript 프로그래머에게 보여줄 때 매우 부정적인 피드백을 받고 이유를 모릅니다. 비공개로도 JavaScript는 단일 스레드, 기존 라이브러리를 다시 작성해야하며 gremlins가 계속 작동하면 모든 살아있는 존재를 생성하고 먹을 것이라고 말합니다.

원래 원래 코 루틴 구현 (부스트 컨텍스트 사용)도 있었지만 그것을 버려야했습니다 (JavaScriptCore는 스택에 대해 pedantic입니다). 나는 그들의 분노를 위험에 빠뜨리고 싶지 않기 때문에 언급하지 않기로 결정했습니다.

어떻게 생각해? JavaScript는 단일 스레드를 의미합니까? 혼자 두어야합니까? 모든 사람이 동시 JavaScript 런타임 아이디어에 반대하는 이유는 무엇입니까?

편집 : 프로젝트는 이제 GitHub 에 있으며 직접 실험하고 의견을 알려주십시오.

다음은 경합없이 병렬로 모든 CPU 코어에서 실행되는 약속의 그림입니다.

동시에 약속을 실행합니다.


7
이것은 매우 의견이 많은 질문처럼 보입니다. 당신의 생각이 마음에 들지 않는 사람들에게 그것이 귀찮을 것이라고 생각하셨습니까?
5gon12eder

26
멀티 스레드가 아닌 것에 쓰레드를 추가하는 것은 운전자의 에드를 제공하지 않고 1 차선 도로를 고속도로로 변환하는 것과 같습니다. 사람들이 무작위로 추락하기 시작할 때까지 거의 대부분 잘 작동합니다. 멀티 스레딩을 사용하면 대부분의 시간에 재생산 할 수없는 미묘한 타이밍 버그가 있거나 비정상적인 동작이 발생합니다. 이를 염두에두고 디자인해야합니다. 스레드 동기화가 필요합니다. 변수를 원 자성으로 만 만드는 것은 경쟁 조건을 제거하지 않습니다.
mgw854

2
공유 상태에 대한 다중 스레드 액세스를 어떻게 처리 할 계획입니까? "원자로 표시되고 액세스에 대한 경쟁"은 이것이 실제로 어떻게 작동한다고 생각하는지 설명하지 않습니다. 아이디어에 대한 부정적인 태도는 사람들이 실제로 어떻게이 일을하는지 전혀 모르기 때문이라고 생각합니다. 또는 Java 또는 C ++에서 개발자와 함께 적절한 뮤텍스 등을 사용하기 위해 모든 부담을지고 있다면 사람들은 아마도 그것이없는 환경에서 그 합병증과 프로그래밍 위험을 원하는 이유를 생각하고있을 것입니다.
jfriend00

17
스레드간에 임의의 상태를 자동으로 조정하는 것은 거의 불가능한 문제로 간주되므로 자동으로 수행하는 모든 것을 제공 할 수있는 신뢰성이 없습니다. 그리고 Java 또는 C ++처럼 개발자에게 부담을 줄이려면 대부분의 node.js 프로그래머는 그러한 부담을 원하지 않습니다. 그들은 node.js가 그것을 처리 할 필요가 없습니다. 대부분. 좀 더 동정적인 귀를 원한다면, 이와 관련하여 어떻게 그리고 무엇을 제공하고 왜 그것이 유용하고 유용한 지 설명하고 보여 주어야합니다.
jfriend00

3
작업을 계속하십시오. 멀티 스레딩이없는 언어를 장난감 언어로 생각합니다. 대부분의 JavaScript 개발자는 단일 스레드 모델을 가진 브라우저로 작업한다고 생각합니다.
Chloe

답변:


70

1) 멀티 스레딩은 매우 어렵습니다. 불행히도 지금까지이 아이디어를 제시 한 방식은 얼마나 어려운지 과소 평가하고 있음을 나타냅니다.

현재로서는 언어에 단순히 "스레드를 추가"하고 나중에 올바르게 수행하고 수행하는 방법에 대해 걱정하는 것처럼 들립니다. 특히:

두 작업이 변수에 동시에 액세스하려고하면 원자로 표시되고 액세스를 위해 경쟁합니다.
...
원자 변수가 모든 것을 해결하지는 못한다는 데 동의하지만 동기화 문제에 대한 해결책을 찾는 것이 다음 목표입니다.

"동기화 문제 해결"없이 Javascript에 스레드를 추가하는 것은 "추가 문제 해결"없이 Javascript에 정수를 추가하는 것과 같습니다. 문제의 본질에 매우 근본적이기 때문에 아무리 원할지라도 특정 솔루션을 염두에두고 멀티 스레딩을 추가 할 가치가 있는지 여부에 대해서는 기본적으로 논의 할 필요가 없습니다.

또한 모든 변수를 원 자성으로 만드는 것은 다중 스레드 프로그램이 단일 스레드 프로그램 보다 성능을 저하시킬 수있는 일종의 일이므로 실제로보다 현실적인 프로그램에서 성능을 테스트하고 무언가를 얻고 있는지 여부를 확인하는 것이 더 중요합니다.

또한 node.js 프로그래머로부터 스레드를 숨기려고하는지 또는 어느 시점에 스레드를 노출하려는 경우 멀티 스레드 프로그래밍을 위해 새로운 Javascript 방언을 효과적으로 만들지 여부는 분명하지 않습니다. 두 옵션 모두 잠재적으로 흥미롭지 만 아직 어느 것을 목표로 삼고 있는지 결정하지 않은 것처럼 들립니다.

따라서 현재 프로그래머에게 단일 스레드 환경에서 동기화 문제에 대한 솔루션이없고 실제 성능을 향상시키는 증거가없고 이러한 문제를 해결할 계획이없는 새로운 다중 스레드 환경으로 전환 할 것을 요청하고 있습니다.

아마 사람들이 당신을 진지하게 받아들이지 않는 이유 일 것입니다.

2) 단일 이벤트 루프의 단순성과 견고성은 이점입니다.

Javascript 프로그래머는 Javascript 언어가 경쟁 조건 및 모든 진정한 멀티 스레딩 프로그래밍을 괴롭히는 기타 교활한 버그로부터 "안전"하다는 것을 알고 있습니다. 그들이 안전을 포기한다는 확신을 포기하도록 설득하기 위해 강력한 주장이 필요하다는 사실은 그들이 책임감있게 만듭니다.

어떻게 든 그 안전성을 유지할 수 없다면 멀티 스레드 node.js로 바꾸고 싶은 사람은 멀티 스레드 애플리케이션을 위해 처음부터 설계된 Go와 같은 언어로 전환하는 것이 더 나을 것입니다.

3) 자바 스크립트는 프로그래머에게 스레드 관리를 직접 노출시키지 않고 이미 "백그라운드 스레드"(WebWorkers) 및 비동기 프로그래밍을 지원합니다.

이러한 기능은 단일 이벤트 루프의 안전성을 포기하지 않으면 서 실제 세계의 Javascript 프로그래머에게 영향을 미치는 많은 일반적인 사용 사례를 이미 해결합니다.

이러한 기능이 해결되지 않고 Javascript 프로그래머가 솔루션을 원한다는 특정 사용 사례가 있습니까? 그렇다면 특정 사용 사례의 맥락에서 multithreaded node.js를 제시하는 것이 좋습니다.


PS는 무엇 설득 것 나를 다중 스레드 Node.js를 구현 전환 시도?

Javascript / node.js에 단순한 멀티 스레딩의 이점이 있다고 생각되는 사소한 프로그램을 작성하십시오. 이 샘플 프로그램에서 일반 노드 및 다중 스레드 노드에서 성능 테스트를 수행하십시오. 사용중인 버전이 버그 나 불안정성을 유발하지 않으면 서 여러 코어의 런타임 성능, 응답 성 및 사용량을 크게 향상 시킨다는 것을 보여주십시오.

그렇게하면 사람들이이 아이디어에 훨씬 더 관심이있는 것을 보게 될 것입니다.


1
1) 이제 동기화 문제를 한동안 미루고 있음을 인정합니다. '두 가지 작업이 다투게 될 것'이라고 말할 때, 그것은 내 디자인이 아니라 주로 관찰입니다. dl.dropboxusercontent.com/u/27714141/… — 여기서 어떤 종류의 주술 JavaScriptCore가 수행되고 있는지 잘 모르겠지만 이 문자열은 본질적으로 원자가 아닌 경우 손상됩니까? 2) 나는 동의하지 않는다. 이것이 JS가 장난감 언어로 여겨지는 이유입니다. 3) 스레드 풀 스케줄러를 사용하여 구현하면 ES6 약속이 훨씬 더 성능이 우수합니다.
voodooattack

13
@voodooattack "JS가 장난감 언어로 여겨지는 이유입니다." 아니요, 이것이 당신 이 장난감 언어로 생각 하는 이유 입니다. 수백만 명의 사람들이 매일 JS를 사용하고 있으며 JS, 단점 및 모든 것에 완벽하게 만족합니다. 다른 사람들이 실제로 가진 문제를 해결하고 있는지 확인하십시오. 언어를 바꾸는 것만으로는 해결되지 않습니다.
Chris Hayes

@ChrisHayes 문제는, 내가 고칠 수 있는데 왜 단점을 견뎌야 하는가? 기능으로서의 동시성이 JavaScript를 향상 시킵니까?
voodooattack

1
@voodooattack 질문입니다. 기능으로서의 동시성이 Javascript를 개선합니까? "아니오"가 아닌 것에 대한 커뮤니티 답변을 얻을 수 있다면 아마도 무언가에 대한 것일 수 있습니다. 그러나 이벤트를 차단하기 위해 이벤트 루프와 노드의 작업자 스레드에 대한 기본 위임은 사람들이해야 할 대부분의 작업에 충분합니다. 사람들이 정말로 스레드 된 자바 스크립트를 필요로한다면 자바 스크립트 워커를 사용할 것이라고 생각합니다. 그러나 작업자가 JS 파일 대신 일류 함수로 작업하게하는 방법을 찾을 수 있다면 .... 뭔가 실제로 있을 수 있습니다 .
lunchmeat317

7
@voodooattack JavaScript를 장난감 언어라고 부르는 사람들은 자신이 말하는 것을 모른다. 모든 언어에 사용되는 언어입니까? 물론 그렇지는 않지만 그렇게 무시 하는 것은 분명히 실수입니다. JS가 장난감 언어라는 개념을 없애려면, 사소한 프로덕션 응용 프로그램을 만들거나 기존 언어를 가리 킵니다. 어쨌든 동시성을 추가해도 사람들의 마음은 바뀌지 않습니다.
jpmc26

16

접근 방식에서 문제를 보여주기 위해 여기를 추측하십시오. 어디에도 링크가 없으므로 실제 구현에 대해 테스트 할 수 없습니다 ...

변하지 않는 것이 항상 하나의 변수 값으로 표현되는 것은 아니며 '하나의 변수'는 일반적인 경우 잠금 범위로 충분하지 않기 때문입니다. 예를 들어, 우리가 변하지 않는 것을 상상해보십시오 a+b = 0(은행의 두 계좌와의 잔고). 아래의 두 함수는 변하지 않는 것이 항상 각 함수의 끝 (단일 스레드 JS의 실행 단위) 에서 유지 되도록합니다 .

function withdraw(v) {
  a -= v;
  b += v;
}
function deposit(v) {
  b -= v;
  a += v;
}

두 개의 스레드를 실행할 때 지금, 당신의 멀티 스레드 세계에서 어떤 일이 발생 withdraw하고 deposit동시에? 고마워 머피

(+ =와-=를 특별하게 다루는 코드가있을 수 있지만 도움이되지 않습니다. 어떤 시점에서는 함수에 로컬 상태가 있고 동시에 두 변수를 '잠글'방법이 없습니다. 위반 될 것입니다.)


편집 : 코드가 의미 적으로 https://gist.github.com/thriqon/f94c10a45b7e0bf656781b0f4a07292a 의 Go 코드와 동등한 경우 내 의견은 정확합니다 ;-)


이 의견은 관련이 없지만 철학자들은 여러 객체를 잠글 수 있지만 일관성이없는 순서로 잠그기 때문에 굶어 죽습니다.
Dietrich Epp

3
@voodooattack "방금 테스트했습니다 ..."스레드 스케줄링과 일치하지 않는 실행 순서를 경험 한 적이 있습니까? 기계마다 다릅니다. 작업 예약 방법에 대한 메커니즘 을 식별하지 않고 단일 테스트 (또는 수백 개의 테스트)를 앉아서 실행하는 것은 무의미합니다.
jpmc26

4
@voodooattack 문제는 동시성을 테스트하는 것이 유용하지 않다는 것입니다. 고정이 유지 될 것임을 증명할 수 있어야합니다 . 그렇지 않으면 메커니즘이 프로덕션에서 절대 신뢰할 수 없습니다.
sapi

1
그러나 잠금 메커니즘이 없기 때문에 사용자에게 "책임감있게 시스템 사용"을위한 도구를 제공하지 않았습니다. 모든 것을 원 자성으로 만들면 스레드 안전성이 환상적이며 원 자성 액세스가 필요하지 않은 경우에도 원자 성인 모든 것에 대한 성능 저하를 가져옵니다. 그러나 실제로는 thriqon이 제공하는 것과 같은 대부분의 동시성 문제를 해결하지 못합니다. 다른 예를 들어, 한 스레드에서 배열을 반복하고 다른 스레드는 배열에서 요소를 추가하거나 제거합니다. 그 점에서 엔진의 Array 구현이 스레드로부터 안전하다고 생각하는 것은 무엇입니까?
Zach Lipton

2
@voodooattack 따라서 사용자가 공유 데이터 나 부작용이없는 함수에만 스레드를 사용할 수 있다면 (여기서 보았 듯이 스레드 안전을 보장 할 방법이 없기 때문에 다른 용도로는 쓰지 않는 것이 좋습니다), 그렇다면 웹 워커 (또는 웹 워커와 관련하여 더 유용한 API를 제공하는 많은 라이브러리 중 하나)에 비해 어떤 가치가 있습니까? 그리고 웹 워커는 사용자가 "무책임하게"시스템을 사용할 수 없기 때문에 훨씬 더 안전합니다.
Zach Lipton

15

10 년 전, Brendan Eich (JavaScript를 발명 한 사람)는 Threads Suck 이라는 에세이를 썼습니다.이 글 은 JavaScript의 디자인 신화에 대한 몇 안되는 표준 문서 중 하나입니다.

그것이 올바른지 여부는 또 다른 질문이지만 JavaScript 커뮤니티가 동시성에 대해 어떻게 생각하는지에 큰 영향을 미쳤다고 생각합니다.


31
내가 조언을받을 마지막 사람은 Brendan Eich입니다. 그의 경력은 자바 스크립트를 만드는 데 기반을두고 있으며, 이는 우리가 타고난 허약함을 극복하기 위해 만들어진 수많은 도구를 가지고 있기 때문에 매우 나쁩니다. 그로 인해 세계에서 얼마나 많은 개발자 시간이 낭비되었는지 생각해보십시오.
Phil Wright

12
나는 당신이 왜 그의 의견을 할인하고 JavaScript에 대한 당신의 경멸조차 이해할지 이해하지만, 당신의 관점이 그의 도메인에 대한 그의 전문 지식을 무시할 수있는 방법을 이해하지 못합니다.
Billy Cravens

4
@BillyCravens haha, 심지어 Javascript에 대한 표준 책 : Crockford "Javascript the good parts "는 게임에서 타이틀을 제공합니다. 같은 방법으로 아이 흐의 태도를 다루고, 그가 좋아하는 것을 고수하십시오. :-)
gbjbaanb

13
@PhilWright : 그의 첫 자바 스크립트 구현은 Lisp 변형이었습니다. 나에게 큰 존경을 얻습니다. Lisp 구문을 C와 유사한 구문으로 바꾸도록 강요 한 그의 상사의 결정은 그의 잘못이 아닙니다. 핵심 Javascript는 여전히 Lisp 런타임입니다.
slebetman

7
@PhilWright : 언어의 허풍에 대해 Eich를 비난해서는 안됩니다. 초기 구현의 버그이며 JS가 성숙하지 못하게하는 웹 언어에 대한 하위 호환성이 필요합니다. 핵심 개념은 여전히 ​​훌륭한 언어를 형성합니다.
Bergi

8

원자 적 액세스는 스레드 안전 동작으로 변환되지 않습니다.

예를 들어 해시 맵을 다시 해싱 (예 : 객체에 속성을 추가 할 때)하거나 전역 배열을 정렬하는 등의 업데이트 중에 전역 데이터 구조가 유효하지 않은 경우가 있습니다. 그 동안 다른 스레드가 변수에 액세스 할 수 없습니다. 이것은 기본적으로 전체 읽기-쓰기-쓰기주기를 감지하고이를 잠 가야한다는 것을 의미합니다. 업데이트가 사소하지 않은 경우 문제 영역을 중지시킬 수 있습니다.

Javascript는 처음부터 단일 스레드 및 샌드 박스 처리되었으며 모든 코드는 이러한 가정을 염두에두고 작성되었습니다.

이는 격리 된 컨텍스트와 관련하여 2 개의 개별 컨텍스트가 다른 스레드에서 실행되도록하는 데 큰 이점이 있습니다. 또한 자바 스크립트를 작성하는 사람들은 경쟁 조건 및 기타 다양한 멀티 스레드 pitfal을 처리하는 방법을 알 필요가 없습니다.


그렇기 때문에 스케줄러 API가 고급 측면에 있어야하고 부작용이없는 약속 및 기능에 내부적으로 사용되어야한다고 생각합니다.
voodooattack

6

접근 방식으로 성능이 크게 향상됩니까?

못 미더운. 당신은 이것을 증명해야합니다.

귀하의 접근 방식으로 코드를보다 쉽고 빠르게 작성할 수 있습니까?

분명히 아닙니다. 멀티 스레드 코드는 단일 스레드 코드보다 여러 번 올바르게 작성하기가 어렵습니다.

당신의 접근 방식이 더 강력 해 질 것입니까?

교착 상태, 경쟁 조건 등은 해결해야 할 악몽입니다.


2
node.js를 사용하여 raytracer를 빌드하고 이제 스레드로 다시 시도하십시오. 다중 프로세스가 전부는 아닙니다.
voodooattack

8
@voodooattack, 올바른 마음을 가진 사람은 스레딩 유무에 관계없이 자바 스크립트를 사용하여 광선 추적 프로그램을 작성하지 않습니다. 이는 비교적 간단하지만 계산 집약적 인 알고리즘으로 작성됩니다. . 자바 스크립트가 사용되는 문제의 경우 다중 프로세스로 충분합니다.
Jan Hudec

@ JanHudec : Heh, JS는 SIMD도 지원할 것입니다 :-) hacks.mozilla.org/2014/10/introducing-simd-js
Bergi

2
@voodooattack 모르는 경우 SharedArrayBuffers를 살펴 보십시오 . JavaScript는 더 많은 동시성 구성을 갖지만 특정 문제를 해결하면서 신중하게 추가되어 수년간 살아야 할 나쁜 디자인 결정을 최소화하려고 노력하고 있습니다.
REINSTATE MONICA-제레미 뱅크스

2

구현은 동시성을 도입하는 것이 아니라 동시 변경 가능한 공유 상태로 동시성을 구현하는 특정 방법을 도입하는 것입니다. 역사적으로 사람들은 이러한 유형의 동시성을 사용하여 많은 종류의 문제를 일으켰습니다. 물론 공유 가능한 가변 상태 동시성을 사용하여 완벽하게 작동하는 간단한 프로그램을 만들 수 있지만 메커니즘의 실제 테스트는 수행 할 수있는 것이 아니라 프로그램이 복잡해지고 점점 더 많은 기능이 프로그램에 추가됨에 따라 확장 될 수 있습니다. 소프트웨어는 한 번만 구축하면 완료되는 정적 인 것이 아니라 시간이 지남에 따라 계속 발전하고 메커니즘이나 개념이

다른 모델의 동시성 (예 : 메시지 전달)을보고 해당 모델이 제공하는 이점의 종류를 파악할 수 있습니다.


1
ES6 약속은 구현 모델에서 혜택을 얻을 수 있다고 생각합니다.
voodooattack

WebWorkers 사양을 살펴보십시오. 구현을 제공하는 npm 패키지가 있지만 패키지 대신 엔진의 핵심으로 구현할 수 있습니다.
Ankur

JavaScriptCore (사용중인 JS의 웹 키트 구현)는 이미 구현했으며 컴파일 플래그 일뿐입니다.
voodooattack

승인. WebWorkers는 메시지 전달과 동시성입니다. 레이트 레이서 예제를 사용 해보고 변경 가능한 상태 접근 방식과 비교할 수 있습니다.
Ankur

4
메시지 전달은 항상 변경 가능한 상태에서 구현되므로 속도가 느려집니다. 나는 당신의 요점을 여기서 보지 못합니다. :-/
voodooattack

1

이것은 필요합니다. 노드 js에 낮은 수준의 동시성 메커니즘이 없기 때문에 수학 및 생물 정보학 등의 분야에서 응용 프로그램의 응용 프로그램이 제한됩니다. 게다가 스레드와의 동시성이 노드에서 사용되는 기본 동시성 모델과 반드시 ​​충돌하지는 않습니다. ui 프레임 워크 (및 nodejs)와 같은 주요 이벤트 루프가있는 환경에서 스레딩에 대한 잘 알려진 의미가 있으며 여전히 유효한 용도로 사용되는 대부분의 상황에서 지나치게 복잡합니다.

물론, 일반적인 웹 앱에는 스레드가 필요하지 않지만 조금 덜 전통적인 것을 시도해보십시오. 소리가 낮은 수준의 동시성 프리미티브가 없으면 제공하는 다른 것으로 빠르게 저어 줄 것입니다.


4
그러나 "수학 및 생물 정보학"은 C #, JAVA 또는 C ++로 작성하는 것이 좋습니다.
Ian

실제로 파이썬과 펄은 그 분야에서 지배적 인 언어입니다.
dryajov

1
실제로, 이것을 구현하는 주된 이유는 기계 학습 응용 프로그램 때문입니다. 그래서 당신은 요점을 가지고 있습니다.
voodooattack

@dryajov 일부 계산 과학 분야에서 FORTRAN이 얼마나 큰지 모른다는 사실에 기뻐하십시오.
cmaster

@dryajov 그들은 게놈 시퀀싱에 본질적으로 더 우수하지 않기 때문에 풀 타임으로 프로그래머가 아닌 인간에게 더 접근하기 쉽기 때문에 R과 같은 특수 목적 언어와 Fortran과 같은 과학 언어를 컴파일했습니다.
cat

0

나는 그것이 다르고 강력한 아이디어이기 때문에 정말로 믿는다. 당신은 신념 체계에 반대하고 있습니다. 네트워크를 통해 물건이 받아 들여 지거나 대중화되는 것은 가치에 근거하지 않습니다. 또한 아무도 새로운 스택에 적응하기를 원하지 않습니다. 사람들은 너무 다른 것을 자동으로 거부합니다.

소리가 나지 않는 일반 npm 모듈로 만드는 방법을 생각해 내면 일부 사람들이 그것을 사용할 수 있습니다.


JS 프로그래머가 npm에 벤더 잠금 상태임을 의미합니까?
voodooattack

3
문제는 일부 npm 모듈이 아닌 새로운 런타임 시스템에 관한 것이며 변경 가능한 공유 상태 동시성은 실제로 오래된 아이디어입니다.
Ankur

1
@voodooattack 나는 이미 인기있는 접근 방식에 빠져 있으며 상태 바이어스를 극복하는 것이 불가능할 것입니다.
Jason Livesay
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.