2009-09-29 15 views
20

AFAIKでは、Javaのメモリはオブジェクトに動的にメモリが割り当てられるヒープに基づいており、共有メモリの概念はありません。Javaの共有メモリの概念

共有メモリの概念がない場合、Javaプログラム間の通信には時間がかかるはずです。他の通信モードと比較して、プロセス間通信が共有メモリを介してより速くなるCでは、

私が間違っている場合は私を修正してください。また、2つのJavaプログラムが互いに話すための最も速い方法は何ですか。

+0

「共有メモリの通信がより速いCで」という意味ですか? – Will

+0

ええ、質問を修正しました –

答えて

14

共有メモリセグメントを作成するための公式のAPIはないので、共有メモリを使用して2つのJavaプロセスが互いに話すようにするには、ヘルパーライブラリ/ DDLとJNIを使​​用する必要があります。

実際には、Javaはスレッドをサポートしているので、これはほとんど問題ではないため、同じJava VMで2つの「プログラム」を実行できます。それらは同じヒープを共有するので、通信は瞬間的になります。さらに、共有メモリセグメントの問題が原因でエラーが発生することはありません。

+1

これはJava 7以降に変更されました。Javaにはメモリマップファイルがあります。 – Arkadiy

+2

@Arkadiy:メモリマップされた**ファイル**はJava 1.4 with NIOで追加されました。 Java 7はこれをNIO 2で拡張しました。しかし、OPは異なる概念である共有メモリ**について知りたいと思っています。 –

+3

共有メモリは確かに異なる概念ですが、mem-mappedファイルはIPCのためにいくぶん似た方法で使用できます。そしてはい、あなたはJava 1.4について正しいです:) – Arkadiy

7

共有メモリが高速になることがあります。時にはそうではなく、CPUキャッシュを傷つけ、同期化はしばしば痛みを伴います(ミューテックスなどに依存していると、パフォーマンスが大幅に低下することがあります)。

Barrelfishは、メッセージの受け渡しを使用するIPCが、コアの数が増えるにつれて実際に高速であることを実証するオペレーティングシステムです(従来のX86アーキテクチャでは、ターゲットとしていたよりエキゾチックなNUMA NUCAのように) 。

共有メモリが高速であると仮定すると、特定のシナリオおよびターゲットハードウェアのテストが必要です。最近の一般的な想定ではありません!

+4

これは誤解を招きます。競合した書き込みはパフォーマンスを低下させ、ロックがパフォーマンスを低下させます。共有読取りはパフォーマンスに役立ち、共有メモリーはIPCを良好に実装します(実際には、最良のIPCシステムは共有メモリーで実装されます)。だからこそ、その場を持ち、概念的には扱いが容易なのですが、パフォーマンスは絶対にIPCを使う理由ではありません! – Eloff

4

は、私は考えることができる、同等の技術のカップルがあります:

  1. 数年前JavaSpacesと呼ばれる技術がありましたが、それは本当にあなたが私に言わせれば、保持恥を取るように見えたことはありません。
  2. 今日、分散キャッシュ技術は、CoherenceTangosolのようなものです。

残念ながらどちらもありません(共有メモリのうち右側の速さを持っているが、彼らはJava NIO's FileChannelクラスまたは類似を使用して、など、同時アクセスの問題に対処memory-mapped filesを使用しているを見て

7

一つのことを行いますmap()メソッドを参照してください)。これを使って、Javaプロセスと同じマシン上のCのネイティブプロセスとの間で通信を行いました(この場合は一方向)。

私はファイルシステムの専門家ではありません(幸いなことに、スタッフがいらっしゃいます!)が、私たちのパフォーマンスは非常に驚くほど高速です。ページキャッシュのセクションをファイルとして扱い、システムコールのオーバヘッドなしで直接読み込み+書き込みができます。私は、保証と一貫性についてはわかりません。Javaには、変更を強制的にファイルに書き込むメソッドがあります。これは、実際の基礎ファイルに書き込まれることがある(通常、通常は通常はわかりません)ことを意味します。 (幾分か非常に極端に)遅れています。これは基本的にはちょうど共有メモリセグメントであることを意味します。

理論上、私が理解しているように、メモリマップファイルは実際には共有メモリセグメントによってバックアップされることができます(ファイルハンドルだけです)が、私はJavaでそうする方法は知らないJNIなし。

+0

かなり古いスレッドですが、通常のTCP/IPソケットとは対照的に、あなたのメソッドの速度(待ち時間)パフォーマンスについてコメントできるかどうか疑問に思っていましたか?私は2つのアプリケーション(1つのJava、1つのC/C++)、現在ソケットを介して通信している間の待ち時間を改善する方法を研究しています。 – Bastien

+1

メモリマップされたファイルよりも速く何かを見つけることはほとんどありません。ファイルへの書き込みは、ランダムな位置であっても、基本的にメインメモリへの書き込みです(実行可能な最速のことです)。基礎となるファイルシステムにフラッシュするときのJavaの「ルール」の問題は、私がオープンソースのファイルシステムであることを証明していないためです。ランダムな場所で毎秒ファイルに小さな(1〜4バイト)書き込みを何百、何千というように何度もやっていて、パフォーマンス上の問題のようなリモートに何も気付かなかったことが分かります。 – Cowan

+2

このスレッドはこれまでより古くなっていますが、https://github.com/peter-lawrey/Java-Chronicleで見ることができます。これにより、1秒間の待ち時間が200ns未満プロセス。私はあなたの優れたJavaのクロニクルを提案するつもりだったが、あなたはそれに私を打ちのめす...一年半で –

22

少なくとも2つの方法 - RAM DriveまたはApache APRがあります。

詳細hereおよびhereパフォーマンスの測定値はいくつかあります。

+0

+ 1の代わりに+5この回答をしたいと思います。これら2つの記事は興味深く実用的です。元の質問に答えてください。 –

9

Peter LawreyのJava Chronicleプロジェクトは価値があります。

これらは、私がいろいろなオフ・ヒープとオン・ヒープ・オプションを比較する以前に行ってきたsome testsです。

+0

また、https://github.com/OpenHFT/Chronicle-Queueとhttps://github.com/OpenHFT/Chronicle-Map共有メモリを使用してください。 –

0

Cowanから提供された情報は正しいです。しかし、共有メモリであっても、同時に複数のスレッド(および/またはプロセス)で同一であるとは限りません。主な根本的な理由は、Javaメモリモデル(ハードウェアメモリモデル上に構築されている)です。件名の説明は、Can multiple threads see writes on a direct mapped ByteBuffer in Java?を参照してください。

1

Peter LawreyのJava Chronicleと同様に、Jocketを試すことができます。

また、MappedByteBufferを使用しますが、データは保持されず、Socket/ServerSocketのドロップイン置換として使用されます。

1kBピンポンのラウンドトリップレイテンシは約0.5マイクロ秒です。

2

これを行う最も簡単な方法は、2つのプロセスが同じメモリマップファイルをインスタンス化することです。実際には、同じオフヒープメモリ空間を共有します。このメモリの物理アドレスを取得し、sun.misc.Unsafeを使用してプリミティブの書き込み/読み取りを行うことができます。 putXXXVolatile/getXXXVolatileメソッドを使用して並行性をサポートしています。 CoralQueueを見てください。これはIPCを容易に提供し、同じJVM内でスレッド間通信を提供します。

免責事項:私はCoralQueueの開発者の一人です。

1

MappedBus(http://github.com/caplogic/mappedbus)は、githubで追加したライブラリで、複数の(2つ以上の)Javaプロセス/ JVM間のメッセージの受け渡しによってIPCを有効にします。

トランスポートは、メモリマップファイルまたは共有メモリのいずれかです。共有メモリと一緒に使用するにはgithubページの例に従いますが、 "/ dev/shm /"の下にあるファイルを読者/ライターに向けてください。

オープンソースで、実装についてはgithubページで詳しく説明しています。