web-dev-qa-db-ja.com

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

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

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

Working multithreaded node.js runtime

問題は、私がこのデザインをJavaScriptプログラマーに見せると、非常に否定的なフィードバックを受け、なぜなのかわからないことです。プライベートであっても、JavaScriptはシングルスレッドであること、既存のライブラリを書き換える必要があること、そして私がこれに取り組み続けるとグレムリンがすべての生き物を生み出して食べると彼らは言っています。

私は元々、(ブーストコンテキストを使用して)ネイティブのコルーチンの実装も行っていましたが、それを破棄する必要があり(JavaScriptCoreはスタックについて知識が豊富でした)、彼らの怒りを危険にさらしたくなかったので、言及しないことにしました。

どう思いますか? JavaScriptはシングルスレッドであることを意図していますか?それはそのままにしておくべきですか?なぜ皆が並行JavaScriptランタイムのアイデアに反対しているのですか?

編集:プロジェクトは現在 GitHub にあります。自分で試して、感想をお聞かせください。

以下は、競合なしですべてのCPUコアで並列に実行されるpromiseの図です。

Running promises concurrently.

51
voodooattack

1)マルチスレッド化は非常に困難であり、残念ながら、これまでのところこのアイデアを提示した方法では、その難しさを大幅に過小評価しています。

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

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

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

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

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

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

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

2)単一イベントループのシンプルさと堅牢性は巨大の利点です。

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

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

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

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

これらの機能では解決されず、JavaScriptプログラマーが解決策を求めているという具体的な使用例はありますか?その場合は、マルチスレッド化したnode.jsをその特定のユースケースのコンテキストで提示することをお勧めします。


追伸meがマルチスレッドのnode.js実装への切り替えを試みると、何を説得しますか?

純粋なマルチスレッディングの恩恵を受けると思われる重要なプログラムをJavaScript/node.jsで記述します。通常のノードとマルチスレッドノードでこのサンプルプログラムのパフォーマンステストを実行します。このバージョンでは、バグや不安定さを招くことなく、複数のコアのランタイムパフォーマンス、応答性、使用率が大幅に向上していることがわかります。

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

72
Ixrec

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

これは、不変条件が常に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コードと同等である場合、私のコメントは正確です;-)

16
thriqon

10年ほど前に、ブレンダンアイヒ(JavaScriptの発明者)が Threads Suck と呼ばれるエッセイを書きました。

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

15
Erik Pukinskis

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

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

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

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

8
ratchet freak

あなたのアプローチはパフォーマンスを大幅に向上させるでしょうか?

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

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

間違いなく、マルチスレッドコードは、シングルスレッドコードよりも多くの場合、正しく処理することが困難です。

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

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

6
Phil Wright

実装は、同時実行性を導入するだけではなく、同時実行性を実装する特定の方法、つまり共有された可変状態による同時実行性を導入することを目的としています。歴史の中で人々はこのタイプの並行性を使用しており、これは多くの種類の問題を引き起こしています。もちろん、共有の可変状態の同時実行性を使用して完全に機能する単純なプログラムを作成できますが、メカニズムの実際のテストはそれができることではありませんが、プログラムが複雑になり、より多くの機能がプログラムに追加されるにつれて拡張できます。ソフトウェアは、一度構築してそれで終了する静的なものではなく、時間とともに進化し続けるメカニズムであり、何らかのメカニズムや概念がソフトウェアの進化に対応できない場合、新しい問題につながるだけであり、これは正確です。共有された可変メモリの同時実行性について、どのような歴史が教えてくれましたか。

他の同時実行モデル(メッセージパッシングなど)を確認すると、それらのモデルが提供する利点の種類を理解するのに役立ちます。

2
Ankur

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

確かに、平均的なWebアプリはスレッドを必要としませんが、少し一般的ではないことを実行してみてください。低レベルの同時実行プリミティブがないと、それを提供する何かにすぐに惹きつけられます。

1
dryajov

それは別の強力なアイデアだからです。あなたは信念体系に反対しています。スタッフが受け入れられるか、ネットワーク経由で人気が高まるのではなく、影響を及ぼします。また、誰も新しいスタックに適応したくありません。人々はあまりにも違うものを自動的に拒否します。

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

0
Jason Livesay