マルチスレッドJavaScriptランタイム実装を作成することの欠点は何ですか?[閉まっている]


51

この1週間、マルチスレッドJavaScriptランタイムの実装に取り​​組んでいます。JavaScriptCoreとboostを使用して、C ++で作成した概念実証があります。

アーキテクチャは単純です。メインスクリプトの評価が完了すると、ランタイムは起動してスレッドプールに参加します。スレッドプールは、共有優先度キューからタスクを選択し始めます。2つのタスクが同時に変数にアクセスしようとすると、アトミックとマークされ、アクセスを争います。

作業マルチスレッドnode.jsランタイム

問題は、この設計をJavaScriptプログラマーに見せると、非常に否定的なフィードバックが得られ、その理由がわからないことです。非公開でも、JavaScriptはシングルスレッドである必要があり、既存のライブラリを書き換える必要があり、作業を続けるとグレムリンがすべての生物を生成して食べると言う。

私はもともとネイティブのコルーチン実装(ブーストコンテキストを使用)も配置していましたが、それを捨てなければなりませんでした(JavaScriptCoreはスタックについてはしゃれています)。

どう思いますか?JavaScriptはシングルスレッドを対象としていますが、JavaScriptはそのままにしておくべきですか?誰もが同時JavaScriptランタイムのアイデアに反対しているのはなぜですか?

編集:プロジェクトは現在GitHubにあります。自分で試してみて、あなたの考えを教えてください。

以下は、競合なしですべてのCPUコアで並行して実行されるプロミスの図です。

約束を同時に実行します。


7
これは非常に熱心な質問のようです。どうして面倒だと思うの、あなたの考えを好まない人に尋ねましたか?
5gon12eder

26
マルチスレッドを想定していないものにスレッドを追加することは、ドライバーのedを提供せずに1車線の道路を高速道路に変換するようなものです。人々がランダムにクラッシュし始めるまで、それはほとんどの場合、かなりうまくいきます。マルチスレッドを使用すると、再現できない微妙なタイミングバグが発生するか、ほとんどの場合動作が不安定になります。それを念頭に置いて設計する必要があります。スレッドの同期が必要です。変数をアトミックにするだけでは、競合状態は解消されません。
mgw854

2
共有状態へのマルチスレッドアクセスの処理をどのように計画しますか?「アトミックとしてマークされ、アクセスを争う」では、これが実際にどのように機能するかを説明していません。このアイデアに対する否定的な態度は、あなたが実際にこの作品をどのように作成するかを人々が知らないためだと思います。あるいは、適切なミューテックスなどを使用するためにJavaやC ++などの開発者にすべての負担をかけている場合、人々はおそらく、それから解放された環境でその複雑さやプログラミングリスクを望むのかと考えているでしょう。
-jfriend00

17
スレッド間のランダムな状態を自動的に調整することはほとんど不可能な問題と見なされているため、自動的にそれを行うものを提供できるという信頼性はありません。また、JavaやC ++のように開発者に負担をかけるだけの場合、ほとんどのnode.jsプログラマーはその負担を望みません。node.jsがそのために処理する必要がないのが好きです。ほとんどの部分。より共感的な耳が必要な場合は、この点でどのように、何を提供するのか、なぜそれが良いと役立つのかを説明/表示する必要があります。
jfriend00

3
作業を続けてください。マルチスレッドのない言語をおもちゃの言語と考えています。ほとんどのJavaScript開発者は、シングルスレッドモデルを備えたブラウザを使用していると思います。
クロエ

回答:


70

1)マルチスレッドは非常に困難です。残念ながら、これまでこのアイデアを提示してきた方法は、その難しさを厳しく過小評価していることを意味します。

現時点では、単に言語に「スレッドを追加」し、後でそれを修正してパフォーマンスを向上させる方法を心配しているように思えます。特に:

2つのタスクが同時に変数にアクセスしようとすると、アトミックとしてマークされ、アクセスを求めて競合します。
...
アトミック変数がすべてを解決するわけではないことに同意しますが、同期問題の解決に取り組むことが私の次の目標です。

「同期の問題の解決策」なしでJavascriptにスレッドを追加することは、「追加の問題の解決策」なしでJavascriptに整数を追加するようなものです。それは問題の性質にとって非常に基本的であるため、どれほどひどく望むとしても、特定のソリューションを念頭に置いてマルチスレッドを追加する価値があるかどうかを議論することさえ基本的に意味がありません。

さらに、すべての変数をアトミックにすることは、マルチスレッドプログラムのパフォーマンスをシングルスレッド対応のものよりも悪化させる可能性が高い種類のことです。これにより、より現実的なプログラムで実際にパフォーマンスをテストし、何かを得ているかどうかを確認することがさらに重要になります。

また、node.jsプログラマーからスレッドを非表示にしようとしているのか、ある時点でスレッドを公開して、マルチスレッドプログラミング用のJavascriptの新しい方言を効果的に作成しようとしているのかどうかもわかりません。どちらのオプションも興味深い可能性がありますが、どちらを目指しているかまだ決めていないようです。

そのため、現時点では、プログラマーに、シングルスレッド環境から、同期の問題の解決策も実際のパフォーマンスを改善する証拠もないまったく新しいマルチスレッド環境への切り替えを検討するように求めています。

それはおそらく人々があなたを真剣に受け止めない理由です。

2)シングルイベントループのシンプルさと堅牢性は、大きな利点です。

Javascriptプログラマーは、Javascript言語が、すべての真のマルチスレッドプログラミングを悩ませている競合状態やその他の非常に潜んでいるバグから「安全」であることを知っています。彼らが安全を放棄するよう説得するために彼らが強い議論を必要とするという事実は、彼らを閉ざされたものにするのではなく、彼らを責任があるものにします。

その安全性をどうにか維持できない限り、マルチスレッドのnode.jsに切り替えたいと思う人は誰でも、マルチスレッドアプリケーション用にゼロから設計されたGoのような言語に切り替える方が良いでしょう。

3)Javascriptは、スレッド管理をプログラマに直接公開することなく、「バックグラウンドスレッド」(WebWorkers)と非同期プログラミングを既にサポートしています。

これらの機能は、単一のイベントループの安全性をあきらめることなく、現実世界のJavascriptプログラマに影響を与える一般的なユースケースの多くを既に解決しています。

これらの機能では解決できないことや、Javascriptプログラマーが解決策を求めていることを念頭に置いた特定のユースケースはありますか?その場合、その特定のユースケースのコンテキストでマルチスレッドnode.jsを提示することをお勧めします。


PSとは何でしょう説得私をマルチスレッドNode.jsの実装への切り替えをしようとしますか?

Javascript / node.jsで、本物のマルチスレッド化の恩恵を受けると思われる重要なプログラムを作成します。通常のノードとマルチスレッドノードで、このサンプルプログラムのパフォーマンステストを実行します。お使いのバージョンが、バグや不安定性を導入することなく、ランタイムのパフォーマンス、応答性、および複数コアの使用を大幅に改善することを示してください。

それができたら、このアイデアにもっと多くの人が興味を持つようになると思います。


1
1)さて、私はしばらくの間同期の問題を先送りにしたことを認めます。私は私のデザインではないこと、「2つのタスクは争うだろう」と言うとき、それは主に観察です:dl.dropboxusercontent.com/u/27714141/... -私はどのようなJavaScriptCoreにおける、ここで実行している魔法のわからないんだけど、shouldn」本質的にアトミックでない場合、この文字列は破損しますか?2)私は強く同意しません。これが、JSがおもちゃの言語と見なされる理由です。3)スレッドプールスケジューラを使用して実装した場合、ES6の約束ははるかに高性能になります。
ブードゥアタック

13
@voodooattack「これが、JSがおもちゃの言語と見なされる理由です。」いいえ、これがおもちゃの言語と考える理由です。何百万人もの人々が毎日JSを使用しており、JS、欠点、その他すべてに完全に満足しています。他の人が実際に抱えている問題を解決していることを確認してください。それは、言語を変更するだけでは解決されません。
クリスヘイズ

@ChrisHayes問題は、私がそれらを修正できるのに、なぜその欠点に耐えるのかということです。機能としての並行性はJavaScriptを改善しますか?
ブードゥアタック

1
@voodooattackそれが問題です。機能としての並行性はJavascriptを改善しますか?「いいえ」ではないというコミュニティの回答が得られる場合は、何かに取り組んでいる可能性があります。ただし、イベントループと、イベントをブロックするためのワーカースレッドへのNodeのネイティブ委任は、人々が行う必要があるほとんどのことで十分であるようです。スレッド化されたJavascriptが本当に必要な場合、Javascriptワーカーを使用すると思います。ただし、JSファイルの代わりにファーストクラスの関数を使用してワーカーを動作させる方法を見つけることができる場合は、...で、実際に何かに取り組むことができます。
lunchmeat317

7
@voodooattack JavaScriptをおもちゃの言語と呼ぶ人々は、自分が何について話しているのか知らない。それはすべてのための行き先の言語ですか?もちろんないが、却下ことがあるようにそれを確かに間違い。JSがおもちゃの言語であるという概念を払拭したい場合は、その中で自明でない実稼働アプリケーションを作成するか、既存のアプリケーションを指定します。とにかく、並行性を追加するだけでは、それらの人々の心は変わりません。
jpmc26

16

ここで推測して、アプローチの問題を示してください。どこにもリンクがないため、実際の実装に対してテストすることはできません...

これは、不変式が常に1つの変数の値で表されるわけではなく、「1つの変数」では一般的な場合のロックのスコープとなるには不十分だからです。たとえば、不変式a+b = 0(2つの口座を持つ銀行の残高)があるとします。以下の2つの関数は、各関数(シングルスレッドJSの実行単位)の最後に不変式が常に保持されるようにます。

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

さて、マルチスレッドの世界では、2つのスレッドが同時に実行されるwithdrawdepositどうなりますか?ありがとう、マーフィー...

(+ =と-=を特別に扱うコードがあるかもしれませんが、それは役に立ちません。ある時点で、関数にローカル状態があり、不変式が同時に2つの変数を 'ロック'する方法がありません。違反されます。)


編集:あなたのコードがhttps://gist.github.com/thriqon/f94c10a45b7e0bf656781b0f4a07292aのGoコードと意味的に同等である場合、私のコメントは正確です;-)


このコメントは無関係ですが、哲学者は複数のオブジェクトをロックできますが、一貫性のない順序でロックするため飢えています。
ディートリッヒエップ

3
@voodooattack「私はちょうどテストしました...」スレッドスケジューリングで一貫性のない実行順序に遭遇したことはありませんか?実行ごとに、マシンごとに異なります。操作のスケジュール方法のメカニズムを特定せずに、1つのテスト(または100のテストまで)を終了して実行することは役に立ちません。
jpmc26

4
@voodooattack問題は、並行性をテストするだけでは役に立たないことです。不変式が保持されることを証明できる必要があります。そうでない場合、本番環境でメカニズムが信頼されることはありません。
サピ

1
ただし、ロックメカニズムはまったくないため、「責任を持ってシステムを使用する」ためのツールをユーザーに提供していません。すべてをアトミックにすることは、スレッドセーフの幻想を与えます(そして、アトミックアクセスを必要としない場合でも、アトミックであるすべてのパフォーマンスヒットを取得します)が、実際には、thriqonがここで提供するようなほとんどの同時実行性の問題を解決しません。別の例として、あるスレッドで配列を反復処理し、別のスレッドで配列に要素を追加または削除します。さらに言えば、エンジンのArrayの実装がスレッドセーフであると思わせる理由は何ですか?
ザックリプトン

2
@voodooattackしたがって、ユーザーが共有データや副作用のない関数にのみスレッドを使用できる場合(そして、ここで見たように、スレッドの安全性を確保する方法がないため、他の目的には使用しない方がよい)、それでは、Web Workers(またはWeb Workersに関してより使いやすいAPIを提供する多くのライブラリの1つ)でどのような価値を提供していますか?また、Webワーカーは、ユーザーがシステムを「無責任に」使用することを不可能にするため、はるかに安全です。
ザックリプトン

15

10年ほど前、Brendan Eich(JavaScriptの発明者)はThreads Suckと呼ばれるエッセイを書きました。これは間違いなく、JavaScriptのデザイン神話の数少ない正規のドキュメントの1つです。

それが正しいかどうかは別の質問ですが、JavaScriptコミュニティが並行性についてどのように考えるかに大きな影響を与えたと思います。


31
最後に助言を求める人は、ブレンダン・アイヒです。彼のキャリア全体はJavaScriptの作成に基づいています。JavaScriptの作成は非常に悪く、その生来のがらくたを回避しようとするために作成されたツールの山があります。彼のために世界中で何時間の開発者が無駄にされているか考えてください。
フィルライト

12
一般的に彼の意見を軽視する理由、そしてJavaScriptに対する軽evenさえ理解するのは理解できますが、あなたの視点がどのように彼の専門知識を無視することを許すのか理解できません。
ビリークレイヴンズ

4
@BillyCravensハハ、Javascriptに関する標準的な本でさえあります:Crockfordによる「Javascript the good parts」はタイトルでゲームを与えます。アイヒの態度を同じように扱い、彼がいいと言っていることだけに固執してください:
gbjbaanb

13
@PhilWright:彼のJavascriptの最初の実装はLispバリアントでした。私にとってこれは彼に大きな尊敬をもたらします。Lisp構文をCに似た構文に置き換えるように強制するという上司の決定は、彼のせいではありません。コアのJavascriptは依然としてLispランタイムです。
-slebetman

7
@PhilWright:Eichのせいでこの言語のくだらないことを責めるべきではありません。初期の実装のバグであり、JSの成熟を妨げるWeb言語の下位互換性の必要性です。コアの概念は依然として素晴らしい言語を形成しています。
ベルギ

8

アトミックアクセスは、スレッドセーフな動作に変換されません。

たとえば、ハッシュマップの再ハッシュ(プロパティをオブジェクトに追加するときなど)やグローバル配列の並べ替えなど、更新中にグローバルデータ構造を無効にする必要がある場合です。その間、他のスレッドに変数へのアクセスを許可することはできません。これは基本的に、読み取り/更新/書き込みサイクル全体を検出し、それをロックする必要があることを意味します。更新が些細ではない場合、問題の領域を停止することになります。

Javascriptは最初からシングルスレッド化およびサンドボックス化されており、すべてのコードはこれらの前提を念頭に置いて記述されています。

これは、分離されたコンテキストに関して大きな利点があり、2つの独立したコンテキストを異なるスレッドで実行できます。また、javascriptを書いている人は、競合状態やその他のさまざまなマルチスレッドpitfalsに対処する方法を知る必要がないことも意味しています。


これが、スケジューラAPIがより高度な側面にあり、副作用のないプロミスと機能に内部的に使用されるべきだと思う理由です。
ブードゥアタック

6

あなたのアプローチはパフォーマンスを大幅に改善しますか?

疑わしい。あなたは本当にこれを証明する必要があります。

あなたのアプローチはコードを書くことをより簡単/より速くするつもりですか?

確かにそうではありませんが、マルチスレッドコードは、シングルスレッドコードよりも適切に動作することが何倍も困難です。

あなたのアプローチはより堅牢になりますか?

デッドロック、競合状態などを修正するのは悪夢です。


2
node.jsを使用してレイトレーサーを構築してみてください。今度はスレッドで再試行してください。マルチプロセスがすべてではありません。
ブードゥアタック

8
@voodooattack、それは比較的単純ですが、完全にコンパイルされた言語で書かれた方が良い、SIMDサポート付きのアルゴリズムであるため、スレッドの有無にかかわらずjavascriptを使用してレイトレーサーを書く人は誰もいません。JavaScriptが使用される問題の種類については、マルチプロセスで十分です。
Jan Hudec

@JanHudec:へぇ、JSは十分:-)としてSIMDのサポートを得るために起こっているhacks.mozilla.org/2014/10/introducing-simd-js
Bergi

2
@voodooattack気付いていない場合は、SharedArrayBuffersを見てください。JavaScriptはより多くの並行性構造を取得していますが、特定の問題点に対処し、長年にわたって耐えなければならない不適切な設計決定を最小限に抑えようと、極端に慎重に追加されています。
州立モニカ

2

実装は、並行性を導入することだけでなく、並行性を実装するための特定の方法、つまり共有可変状態による並行性を導入することでもあります。歴史の中で、人々はこのタイプの並行性を使用してきましたが、これは多くの種類の問題を引き起こしました。もちろん、共有可能な可変状態並行性を使用して完全に機能するシンプルなプログラムを作成できますが、メカニズムの実際のテストはそれができることではありませんが、プログラムが複雑になり、より多くの機能がプログラムに追加されるにつれてスケーリングできます。ソフトウェアは、一度構築して完成した静的なものではなく、時間の経過とともに進化し続け、メカニズムや概念が可能であれば

並行性の他のモデル(例:メッセージの受け渡し)を見て、これらのモデルが提供する利点の種類を理解するのに役立ちます。


1
ES6の約束は実装のモデルから恩恵を受けると思います。なぜなら、それらはアクセスを争わないからです。
ブードゥアタック

WebWorkers仕様をご覧ください。実装を提供するnpmパッケージがありますが、パッケージとしてではなく、エンジンのコアとして実装できます
-Ankur

JavaScriptCore(私が使用しているJSのWebkit実装)は既にそれらを実装しています。これは単なるコンパイルフラグです。
ブードゥアタック

OK。WebWorkersはメッセージの受け渡しと並行しています。レイトレーサーの例を試してみて、可変状態アプローチと比較してください。
アンクール

4
メッセージの受け渡しは、常に可変状態の上に実装されます。つまり、処理速度が遅くなります。ここであなたの主張を見ることができません。:-/
ブードゥアタック

1

これが必要です。ノードjsに低レベルの並行性メカニズムがないため、数学やバイオインフォマティクスなどの分野でのアプリケーションが制限されます。さらに、スレッドでの並行性は必ずしもノードで使用されるデフォルトの並行性モデルと競合しません。uiフレームワーク(およびnodejs)など、メインイベントループのある環境でスレッド化するためのセマンティクスはよく知られていますが、有効な用途があるほとんどの状況では明らかに過度に複雑です。

確かに、あなたの平均的なWebアプリはスレッドを必要としませんが、少し慣習的ではないことを試してみてください。そして、低レベルの同時実行プリミティブが不足していると、すぐにそれを提供する他のものに動揺します。


4
しかし、「数学とバイオインフォマティクス」は、C#、JAVA、またはC ++で記述した方がよいでしょう
イアン

実際、これらの分野ではPythonとPerlが支配的な言語です。
-dryajov

1
実際、これを実装する主な理由は、機械学習アプリケーションのためです。あなたにはポイントがあります。
ブードゥアタック

@dryajov計算科学分野の一部でFORTRANがどれほど大きいかわからないことを嬉しく思います...
cmaster

@dryajovプログラマーではないかもしれないフルタイムの人間にとってアクセスしやすいからです。ゲノムシーケンスが本質的に優れているからではなく、Rのような専用言語とFortranのようなコンパイルされた科学言語があります。

0

それは別の強力なアイデアだからだと本当に信じています。あなたは信念体系に反対しています。スタッフは、メリットに基づいてではなく、ネットワークに影響を与えるか、受け入れられます。また、誰も新しいスタックに適応したくありません。人々はあまりにも異なるものを自動的に拒否します。

ありそうにない通常のnpmモジュールにする方法を考え出すことができれば、それを使用している人がいるかもしれません。


JSプログラマーはnpmにベンダーロックされているということですか?
ブードゥアタック

3
質問は、新しいランタイムシステムに関するものであり、npmモジュールではなく、可変共有状態の同時実行性は本当に古い考えです。
アンクール

1
@voodooattack私は彼らがすでに人気のあるアプローチに頭を悩ませていることを意味し、現状のバイアスを克服することはほとんど不可能になるでしょう。
ジェイソンLivesay
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.