Sam*_*erg 10 java tcp ipc interprocess low-latency
我们一直在分析和分析我们的应用程序,以尽可能减少延迟.我们的应用程序由3个独立的Java进程组成,它们都运行在同一台服务器上,它们通过TCP/IP套接字相互传递消息.
我们将第一个组件的处理时间缩短到25μs,但我们发现TCP/IP套接字(在本地主机上)写入下一个组件总是需要大约50μs.我们看到另一个异常行为,因为接受连接的组件可以写得更快(即<50μs).目前,除套接字通信外,所有组件的运行时间均小于100μs.
不是TCP/IP专家,我不知道可以做些什么来加快这个速度.Unix Domain Sockets会更快吗?MemoryMappedFiles?什么其他机制可能是一种更快的方式将数据从一个Java进程传递到另一个Java进程?
更新6/21/2011我们创建了2个基准测试应用程序,一个用Java编写,一个用C++编写,用于更紧密地比较TCP/IP并进行比较.Java应用程序使用NIO(阻塞模式),而C++使用Boost ASIO tcp库.结果或多或少相当,C++应用程序比Java快约4μs(但在其中一项测试中,Java胜过C++).此外,两个版本的每条消息的时间都有很多变化.
我认为我们同意共享内存实现最快的基本结论.(虽然我们也想评估Informatica产品,只要它符合预算.)
如果可以选择通过 JNI使用本机库,我会考虑照常实现 IPC(搜索 IPC、mmap、shm_open 等)。
使用 JNI 会产生大量开销,但至少比使用套接字或管道执行任何操作所需的完整系统调用要少一些。使用通过 JNI 的轮询共享内存 IPC 实现,您可能能够将单向延迟降至约 3 微秒。(确保使用 -Xcomp JVM 选项或调整编译阈值;否则你的前 10,000 个样本将很糟糕。这会产生很大的差异。)
我有点惊讶 TCP 套接字写入需要 50 微秒 - 大多数操作系统都会在某种程度上优化 TCP 环回。实际上,Solaris 通过TCP Fusion做得很好。如果说对环回通信有任何优化的话,那通常是针对 TCP 的。UDP 往往会被忽视 - 所以在这种情况下我不会打扰它。我也不会打扰管道(stdin/stdout 或您自己的命名管道等),因为它们会更慢。
一般来说,您看到的许多延迟可能来自信号发送 - 要么等待 IO 选择器(如套接字的 select()),要么等待信号量,要么等待某些东西。如果您想要尽可能低的延迟,则必须烧毁处于紧密循环中轮询新数据的核心。
当然,总是有商业现成的路线 - 我碰巧知道它肯定会很快解决你的问题 - 但当然它确实要花钱。为了充分披露,我确实为 Informatica 的低延迟消息传递软件工作。(作为一名工程师,我的诚实观点是,它是非常棒的软件 - 当然值得为这个项目检查。)