10

我们一直在分析和分析我们的应用程序以尽可能减少延迟。我们的应用程序由 3 个独立的 Java 进程组成,它们都运行在同一台服务器上,它们通过 TCP/IP 套接字相互传递消息。

我们已将第一个组件的处理时间减少到 25 μs,但我们看到 TCP/IP 套接字写入(在 localhost 上)到下一个组件总是需要大约 50 μs。我们看到另一种异常行为,即接受连接的组件可以更快地写入(即 < 50 μs)。目前,所有组件的运行时间均小于 100 μs,套接字通信除外。

不是 TCP/IP 专家,我不知道可以做些什么来加快速度。Unix 域套接字会更快吗?内存映射文件?还有哪些其他机制可能是将数据从一个 Java 进程传递到另一个进程的更快方法?

2011 年 6 月 21 日更新 我们创建了 2 个基准测试应用程序,一个使用 Java,一个使用 C++ 来更严格地对 TCP/IP 进行基准测试并进行比较。Java 应用程序使用 NIO(阻塞模式),而 C++ 使用 Boost ASIO tcp 库。结果或多或少相当,C++ 应用程序比 Java 快约 4 μs(但在其中一项测试中,Java 击败了 C++)。此外,两个版本在每条消息的时间上都显示出很大的变化。

我认为我们同意共享内存实现将是最快的基本结论。(尽管我们也想评估 Informatica 产品,但前提是它符合预算。)

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

“O'Reilly 关于 NIO 的书(Java NIO,第 84 页)似乎对内存映射是否保留在内存中含糊其辞。也许它只是说像其他内存一样,如果你用完了物理内存,这会被交换回来到磁盘,否则不是?”

Linux。mmap()调用在 OS 页面缓存区域中分配页面(这些页面会定期刷新到磁盘,并且可以根据接近 LRU 算法的 Clock-PRO 被驱逐?)所以你的问题的答案是 - 是的。内存映射缓冲区可以(理论上)从内存中被驱逐,除非它是 mlocke'd ( mlock() )。这是理论上的。在实践中,我认为如果您的系统没有交换,这是几乎不可能的。在这种情况下,第一个受害者是页面缓冲区。

于 2011-10-26T00:22:22.773 回答
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 回答
1

查看https://github.com/pcdv/jocket

它是使用共享内存的本地 Java 套接字的低延迟替代品。

在现代 CPU 上,两个进程之间的 RTT 延迟远低于 1us。

于 2013-09-10T20:52:18.997 回答
1

请参阅我对Java 和 C/C++ 之间进程间通信的最快(低延迟)方法的回答- 使用内存映射文件(共享内存)java 到 java 延迟可以减少到 0.3 微秒

于 2011-06-21T09:09:26.833 回答