web-dev-qa-db-ja.com

スクリプト言語の実装にマルチスレッド/同時実行性が必要

これが取引です:私は楽しみのために私自身のスクリプト/インタープリター言語を設計することを考えています。私は現在、計画段階にあります。コーディングを開始する前に、すべてをどのように実装するかを正確に把握していることを確認したいと思います。

私が現在苦労しているのは並行性です。ガベージコレクションに伴う予測できないパフォーマンスを回避する簡単な方法は、ガベージコレクターを独自のスレッドに配置し、インタープリター自体と同時に実行することだと思います。 (明確にするために、スクリプト自体をマルチスレッド化することを許可する予定はありません。ガベージコレクターをインタープリターとは異なるスレッドで動作させるだけです。)これは、多くの一般的な人々にとって一般的な戦略ではないようです。おそらく移植性の理由から、スクリプト言語。おそらく、最初にUNIX/POSIXスレッドフレームワークでインタープリターを作成し、必要に応じて他のプラットフォーム(Windowsなど)に移植します。

この問題について誰かが何か考えを持っていますか?並行性を利用することで得られる利益は、必然的に発生する移植性の問題によって無効になりますか? (その点で、同時ガベージコレクターを使用するとパフォーマンスが大幅に向上するという私の仮定は本当に正しいですか?)この戦略を進めるか、それとも離れるべきですか?

1
Ricky Stewart

マルチスレッドで何かを書くのは難しい

私はあなたが知っておく必要がある私の頭のてっぺんの少なくとも1つの競合状態を考えることができます:

  • フィールドAを持つオブジェクトfooがあります
  • gCはマークフェーズを開始したばかりで、フィールドA.fooを調べており、現在、オブジェクトツリーの他の部分を調べています。
  • その間、インタプリタは新しいオブジェクトBを割り当て、スクリプトはそれをA.fooに割り当て、それが含まれていたローカル変数はスコープ外になります(Bへの他の参照を削除します)
  • gCが終了し、A.fooへの変更に気付かないため、Bは有効とマークされません。
  • Bがクリーンアップされ、A.fooにダングリングポインタがあります

これは割り当てである必要はありません(まだマークされていないBの唯一の所有者になり、すでに調べられたフィールドに割り当てる方法は問題を引き起こします)

これは、インタプリタによって処理されたオブジェクト(スイープでまだ有効とマークされていない)を検査対象リストに入れて、スイープ中に有効とマークされるようにすることで解決できます。

したがって、基本的に各オブジェクトには、「アライブ」フラグと「インタプリタによって処理される」フラグのあるビットフィールドがあります。

そして、各オブジェクトで、スクリプトがインタプリタを使用する必要があります

if(!obj.alive && !obj.alreadyHandled){
     obj.alreadyHandled=true;
     GC.addToQueue(obj);
}

これにより、一部のオブジェクトのクリーンアップが遅れますが、それは許容されます

物事を難しくする(単純なメモリの可視性の影響など)他にも多くの注意事項があると確信しています。これが、並行GCがまれである大きな理由です。

1
ratchet freak

同時ガベージコレクターを使用するとパフォーマンスが大幅に向上するという私の仮定は本当に正しいですか?

そうは思いません。

まず第一に、完全にコストのかからないGCを構築できたとしても、現在のスレッド内GCが優れたパフォーマンスシンクである場合にのみ、「優れたパフォーマンスの向上」が得られます。最新のGC実装の​​経験は、そうではないことを示しています。それらのいくつかは非常に軽いです。

第2に、本質的に、他のスレッドが処理している間、GCは大量のメモリにアクセスするため、非常に厄介な競合状態を回避するために本当に注意する必要があります。そこに置いたロックはかなり満足され、高価な操作になります。ロックフリー構造を使用することに成功したとしても(気弱な人向けではありません!)、GCスレッドとインタープリターの間の緊密な結合により、各CAS操作がキャッシュトラッシングポイントになります。

私の意見では、アウトオブスレッドGCに必要な余分な複雑さにより、完全なマルチスレッドを使用しない限り、GCは実用的ではありません。その場合、競合コストのほとんどはすでに支払われているので、スレッドをGC専用にするのは理にかなっています。

ほとんどのマルチスレッドJVM実装( Azul の実装など)にはスレッド外のGCがありますが、失敗と再試行のパターンを回避するために、ほとんどの管理をスレッド内で実行しようとすることに注意してください。ロックフリー構造は高負荷になりがちです。

0
Javier

これは古い質問ですが、まだ興味がある場合は、 Qore を参照してください。これは、マルチスレッドを基本的にサポートするインタープリター型言語であり、独自のガベージコレクションアプローチもあります( プロンプトコレクション )これにより、オブジェクトの循環指向グラフの場合でも、言語がRAIIイディオム(リソース管理および例外セーフプログラミング用のc ++のようなデストラクタ)をサポートできるようになります。

言語をマルチスレッド化する予定がない(または質問が古いためにそうしなかった!)ので、決定論的グラフ分析ははるかに簡単になります。これは、マルチスレッド化の性質により、Qoreのデッドロック回避と通知の側面があるためです。 'プロンプト収集アルゴリズムは、すでに複雑な課題にかなりの複雑さを追加します。

そうすれば、個別のガベージコレクションスレッドは必要なく、RAIIイディオムをサポートするために言語でC++のようなデストラクタのサポートを実装できます(該当する場合)。

0
David Nichols