Java TCP / IP套接字延迟-停留在50μs(微秒)? (用于Java IPC)

| 我们一直在对应用程序进行性能分析,以尽可能减少延迟。我们的应用程序由3个独立的Java进程组成,所有这些进程都运行在同一服务器上,它们通过TCP / IP套接字相互传递消息。 我们已经将第一个组件中的处理时间减少到25μs,但是我们看到(在localhost上)TCP / IP套接字写入下一个组件的时间大约为50μs。我们看到了另一种异常行为,因为接受连接的组件可以更快地写入(即<50μs)。目前,除套接字通信外,所有组件的运行时间均小于100μs。 由于不是TCP / IP专家,我不知道该怎么做才能加快速度。 Unix域套接字会更快吗? MemoryMappedFiles?还有哪些其他机制可能是将数据从一个Java进程传递到另一个Java进程的更快方法? 更新6/21/2011 我们创建了2个基准应用程序,其中1个使用Java,1个使用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或您自己的命名管道,等等),因为它们会变得更慢。 通常,您看到的很多延迟可能来自信令-在套接字的情况下,等待诸如select()之类的IO选择器,或者等待信号量,或者等待某些东西。如果您希望将延迟降到最低,则必须烧掉位于紧密循环轮询中的核心以获取新数据。 当然,总是有商业现货供应的路线-我碰巧可以肯定地知道这会很快解决您的问题-但当然会花钱。为了完全公开:我为Informatica的低延迟消息传递软件工作。 (作为工程师,我的诚实意见是,它是一款非常出色的软件-确实值得对该项目进行检查。)     
  \“关于NIO的O''Reilly书(Java NIO,第84页)似乎含糊不清   内存映射是否保留在内存中。也许只是在说   就像其他内存一样,如果物理用完了,就会被交换   回到磁盘,但否则不?\“ Linux。 mmap()调用在OS页面缓存区域中分配页面(这些页面会定期刷新到磁盘,并且可以基于Clock-PRO(这是LRU算法的近似值)被逐出)。因此,您的问题的答案是-是的。从理论上讲,可以将内存映射的缓冲区从内存中逐出,除非对其进行了mlocke(mlock())。从理论上讲。实际上,我认为如果您的系统不交换几乎是不可能的。在这种情况下,第一个受害者是页面缓冲区。     
请参阅我对Java和C / C ++之间的进程间通信最快(低延迟)方法的回答-使用内存映射文件(共享内存),Java到Java的延迟可以减少到0.3微秒     
MemoryMappedFiles根本不是低延迟IPC的可行解决方案-如果内存的映射段得到更新,则它最终将被同步到磁盘,从而引入了至少以毫秒计的不可预测的延迟。对于低延迟,可以尝试共享内存+消息队列(通知)或共享内存+信号量的组合。这适用于所有Unix,尤其是System V版本(不是POSIX),但是如果您在Linux上运行应用程序,则可以使用POSIX IPC相当安全(大多数功能在2.6内核中可用),是的,您将需要JNI来完成。 UPD:我忘记了这是JVM-JVM IPC,并且我们已经无法完全控制GC,因此可以接受由于操作系统文件缓冲区闪存到磁盘而造成的另外几毫秒的暂停。     
查看https://github.com/pcdv/jocket 它是使用共享内存的本地Java套接字的低延迟替代品。 在现代CPU上,两个进程之间的RTT延迟远低于1us。     

要回复问题请先登录注册