10

アプリケーションのプロファイリングとプロファイリングを行って、レイテンシーを可能な限り削減しました。私たちのアプリケーションは 3 つの個別の Java プロセスで構成され、すべてが同じサーバー上で実行され、TCP/IP ソケットを介して互いにメッセージを渡しています。

最初のコンポーネントの処理時間を 25 μs に短縮しましたが、次のコンポーネントへの TCP/IP ソケットの書き込み (localhost 上) には常に約 50 μs かかることがわかります。もう 1 つの異常な動作が見られます。接続を受け入れているコンポーネントは、より高速に書き込むことができます (つまり、50 μs 未満)。現在、ソケット通信を除いて、すべてのコンポーネントが 100 μs 未満で動作しています。

TCP/IP の専門家ではないので、これを高速化するために何ができるかわかりません。Unix ドメイン ソケットの方が高速ですか? MemoryMappedFiles? ある Java プロセスから別の Java プロセスにデータを渡すためのより高速な方法として、他にどのようなメカニズムがあるでしょうか?

更新 2011 年 6 月 21 日 2 つのベンチマーク アプリケーションを作成しました。1 つは Java で、もう 1 つは C++ で、TCP/IP をより厳密にベンチマークし、比較します。Java アプリは NIO (ブロッキング モード) を使用し、C++ は Boost ASIO tcp ライブラリを使用しました。結果はほぼ同等で、C++ アプリは Java よりも約 4 マイクロ秒高速でした (ただし、テストの 1 つで Java は C++ を上回りました)。また、どちらのバージョンもメッセージあたりの時間に大きなばらつきがありました。

共有メモリの実装が最も高速になるという基本的な結論に同意していると思います。(ただし、予算に適合する場合は、インフォマティカ製品も評価したいと考えています。)

4

5 に答える 5

4

JNI 経由でネイティブ ライブラリを使用するオプションがある場合は、通常どおり IPC を実装することを検討します (IPC、mmap、shm_open などを検索します)。

JNI の使用には多くのオーバーヘッドが伴いますが、少なくとも、ソケットやパイプを使用して何かを行うために必要なシステム コール全体よりもわずかに少なくなります。JNI を介したポーリング共有メモリ IPC 実装を使用すると、一方向のレイテンシを約 3 マイクロ秒まで下げることができる可能性があります。(必ず -Xcomp JVM オプションを使用するか、コンパイルのしきい値も調整してください。そうしないと、最初の 10,000 サンプルがひどいものになります。大きな違いが生じます。)

TCP ソケットの書き込みに 50 マイクロ秒かかることに少し驚いています。ほとんどのオペレーティング システムは、TCP ループバックをある程度最適化しています。実際、Solaris はTCP Fusionと呼ばれるものを使用して、かなりうまく機能します。また、ループバック通信の最適化があったとしても、通常は TCP 用です。UDP は無視される傾向があるため、この場合は気にしません。また、パイプ (stdin/stdout または独自の名前付きパイプなど) も気にしません。パイプはさらに遅くなるからです。

そして一般的に、あなたが目にしているレイテンシーの多くは、ソケットの場合の select() のような IO セレクターを待っているか、セマフォを待っているか、何かを待っているシグナルから来ている可能性があります。レイテンシを可能な限り低くしたい場合は、新しいデータをポーリングするタイトなループに座っているコアを焼き尽くす必要があります。

もちろん、商用の既製のルートは常にあります-私はたまたま、あなたの問題を急いで解決することを確実に知っています-しかし、もちろんそれにはお金がかかります. そして、完全な開示のために、私は Informatica の低遅延メッセージング ソフトウェアで働いています。(そして、エンジニアとしての私の正直な意見は、これは非常に素晴らしいソフトウェアであり、このプロジェクトをチェックする価値があるということです。)

于 2011-05-10T00:24:18.940 に答える
2

「NIO に関する O'Reilly の本 (Java NIO、84 ページ) は、メモリ マッピングがメモリ内にとどまるかどうかについて曖昧なようです。おそらく、他のメモリと同様に、物理メモリが不足すると、これはスワップ バックされると言っているだけです。ディスクに保存しますが、それ以外はできませんか?"

Linux。mmap()呼び出しは、OS ページ キャッシュ領域にページを割り当てます (定期的にディスクにフラッシュされ、LRU アルゴリズムの概算である Clock-PRO に基づいて削除できますか?) したがって、質問に対する答えは - はい。メモリ マップド バッファは、mlocke ( mlock() ) されていない限り、(理論的には) メモリから削除できます。これは理論上です。実際には、システムがスワッピングしていない場合はほとんど不可能だと思います。この場合、最初の被害者はページ バッファです。

于 2011-10-26T00:22:22.773 に答える
1

Java と C/C++ の間のプロセス間通信のための最速 (低レイテンシ) の方法に対する私の回答を参照してください- メモリ マップ ファイル (共有メモリ) を使用すると、Java 間のレイテンシを 0.3 マイクロ秒に短縮できます。

于 2011-06-21T09:09:26.833 に答える
1

MemoryMappedFiles は、低レイテンシ IPC の実行可能なソリューションではありません。メモリのマップされたセグメントが更新されると、最終的にはディスクに同期されるため、少なくともミリ秒単位で測定される予測不可能な遅延が発生します。待ち時間を短くするには、共有メモリ + メッセージ キュー (通知)、または共有メモリ + セマフォの組み合わせを試すことができます。これはすべての Unix、特に System V バージョン (POSIX ではない) で動作しますが、Linux でアプリケーションを実行する場合、POSIX IPC でかなり安全です (ほとんどの機能は 2.6 カーネルで利用可能です) はい、これを行うには JNI が必要です。

UPD: これが JVM であることを忘れていました - JVM IPC であり、完全には制御できない GC が既に存在するため、OS ファイル バッファーがディスクにフラッシュするために追加の数ミリ秒の一時停止を導入することは許容される場合があります。

于 2011-10-09T21:26:50.857 に答える