C++ 和 Java 之间的低延迟 IPC
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6175209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Low-latency IPC between C++ and Java
提问by Tony the Pony
What is the best way to implement C++/Java IPC for the following situation?
在以下情况下实现 C++/Java IPC 的最佳方法是什么?
(Someone recently asked a similar question, but my requirements are more specific)
(最近有人问了类似的问题,不过我的要求比较具体)
I have two programs -- one written in C++, the other in Java -- that need to communicate with each other. Both are running on the same machine.
The programs send messages to each other. Messages are typically short (less than a few hundred bytes), but could potentially be 100KB or more in size.
Messages do not need to be acknowledged (i.e., not a request/response model like HTTP). For example, the C++ program sends a message to the Java program, and the Java program may reply by sending a message to the C++ program at a later time -- and vice versa.
An ideal solution would have a) very low latency, b) no security hassles (user does not have to authorize ports to be opened etc.) and c) will be platform-agnostic.
我有两个程序——一个用 C++ 编写,另一个用 Java 编写——它们需要相互通信。两者都在同一台机器上运行。
这些程序相互发送消息。消息通常很短(少于几百字节),但大小可能达到 100 KB 或更大。
消息不需要被确认(即,不是像 HTTP 这样的请求/响应模型)。例如,C++ 程序向 Java 程序发送一条消息,Java 程序稍后可能会通过向 C++ 程序发送一条消息来回复——反之亦然。
理想的解决方案将具有 a) 非常低的延迟,b) 没有安全问题(用户不必授权打开端口等)并且 c) 与平台无关。
My first thought was using sockets-- each program would act as a server to the other. Sockets have more overhead than other forms of IPC, and I don't know how the server would inform the client of the port number if I let the system auto-assign port numbers. I've also considered named pipes, but they are not supported (at least not consistently) across different platforms. JNIlooks like an option, but can it cross process boundaries?
我的第一个想法是使用套接字——每个程序都充当另一个程序的服务器。套接字比其他形式的 IPC 有更多的开销,如果我让系统自动分配端口号,我不知道服务器如何将端口号通知客户端。我也考虑过命名管道,但它们在不同平台上不受支持(至少不是一致)。 JNI看起来是一个选项,但它可以跨越进程边界吗?
Any suggestions?
有什么建议?
Thanks!
谢谢!
FOLLOW-UP QUESTIONS
后续问题
- If I go with sockets, would I need to open twosockets to allow for asynchronous communication as described above?
- 如果我使用套接字,是否需要打开两个套接字以允许如上所述的异步通信?
采纳答案by gd1
I'd suggest you to use TCP sockets.
我建议你使用TCP sockets。
The actual overhead of TCP sockets, as of my experience, is very very low compared to the other tasks' workload of the applications, at least the ones I use to develop. I mean, sometimes even if sockets' latency is twice as the latency of other IPC mechanisms, in the overall workflow they have very little impact. And it saves you the hassle of making IPC between a Java application and a C++ one, that will eventually require you to use a specific Java library that uses JNI, with the overhead of JNI and the one of the library itself.
根据我的经验,TCP 套接字的实际开销与应用程序的其他任务的工作负载相比非常低,至少是我用来开发的那些任务。我的意思是,有时即使套接字的延迟是其他 IPC 机制的延迟的两倍,在整个工作流程中它们的影响也很小。它为您省去了在 Java 应用程序和 C++ 应用程序之间进行 IPC 的麻烦,这最终将要求您使用使用 JNI 的特定 Java 库,以及 JNI 和库本身的开销。
I've actually measured, in my Java applications, that Garbage Collector impact is far more important than the latency caused by "loopback" TCP sockets.
我在我的 Java 应用程序中实际测量过,垃圾收集器的影响远比“环回”TCP 套接字引起的延迟重要。
Moreover, TCP sockets are more scalable (and portable!) than traditional IPC. What if in the future you'll have to run the client and the server on different machines? In the 'TCP sockets' scenario, you'll have to do a 5-minute hack, in the 'traditional IPC' scenario, you'll have to rewrite the whole IPC stuff.
此外,TCP 套接字比传统 IPC 更具可扩展性(和便携性!)。如果将来您必须在不同的机器上运行客户端和服务器怎么办?在“TCP 套接字”场景中,您必须进行 5 分钟的破解,在“传统 IPC”场景中,您将不得不重写整个 IPC 内容。
However, what is the general workflow of your application?
但是,您的应用程序的一般工作流程是什么?
Even if the acknowledgement is not required, I'd suggest to use TCP (and not UDP) to avoid unsorted delivery (which leads to pain in the ass when it comes to rearrange the stuff you received - some of your messages are 100KB and this doesn't fit in a UDP packet).
即使不需要确认,我也建议使用 TCP(而不是 UDP)来避免未分类的传递(这会在重新排列您收到的内容时导致痛苦 - 您的一些消息是 100KB 而这不适合 UDP 数据包)。
In reply to your last question, for the server to inform the client about the port, you can just make the server launch the client with a specific 'port' command line parameter, or make the server save a small file under /tmp (or another temporary directory) with the port number written inside.
回答你上一个问题,为了让服务器通知客户端端口,你可以让服务器使用特定的'port'命令行参数启动客户端,或者让服务器在/tmp下保存一个小文件(或另一个临时目录),里面写有端口号。
回答by Sanjay T. Sharma
回答by Wouter Simons
An alternative is using memory mapped files and keeping it portable by checking compiler settings if you are posix or not. POSIX OS's have mmap()
and in windows you would use CreateFileMapping()
另一种方法是使用内存映射文件并通过检查编译器设置来保持它的可移植性,无论您是否为 posix。POSIX 操作系统有mmap()
并且在 Windows 中你会使用CreateFileMapping()
In the boost library is a portable implementation for C++ and in java you should be able to use FileChannel()
.
在 boost 库中是 C++ 的可移植实现,在 java 中你应该能够使用FileChannel()
.
This page does a good job of explaining how this can be used for IPC http://en.wikipedia.org/wiki/Memory-mapped_file
该页面很好地解释了如何将其用于 IPC http://en.wikipedia.org/wiki/Memory-mapped_file
回答by Peter Lawrey
When you say very low latency, you need to qualify that. You can send messages over a Socket loop back with a RTT of 20 microsecond. If this is fast enough, I would do that.
当您说非常低的延迟时,您需要对其进行限定。您可以使用 20 微秒的 RTT 通过 Socket 循环发送消息。如果这足够快,我会这样做。
If this is not fast enough I would just place the C++ inside the Java application and call it via JNI. This would give you about 30 nano-second RTT.
如果这还不够快,我会将 C++ 放在 Java 应用程序中并通过 JNI 调用它。这将为您提供大约 30 纳秒的 RTT。
The problem with using memory mapped data is getting the interlocking right. You might find a solution which works on one system, but might not work on others.
使用内存映射数据的问题是获得正确的互锁。您可能会找到适用于一个系统但可能不适用于其他系统的解决方案。
回答by James Kanze
Using JNI would allow access to all of the possiblities in the system, not just those supported directly in Java; it would be necessary, for example, if you used shared memory. JNI is, itself, rather expensive, however.
使用 JNI 将允许访问系统中的所有可能性,而不仅仅是 Java 直接支持的那些;例如,如果您使用共享内存,这将是必要的。然而,JNI 本身相当昂贵。
The question of latency is tricky, because none of the mechanisms I know given any guarantees. All in all, the fastest would probably be some form of shared memory, using signals to wake up the other process when data is present. This would require using JNI on the Java side, but done correctly, would probably still give the lowest latency—doing it correctly (ensuring that no messages get lost) can be far from trivial, however. Unix based platforms do support queueing signals, and handling them as events in a separate thread; I don't know about Windows.
延迟问题很棘手,因为我所知道的机制都没有提供任何保证。总而言之,最快的可能是某种形式的共享内存,当数据存在时使用信号唤醒另一个进程。这将需要在 Java 端使用 JNI,但如果正确完成,可能仍会提供最低的延迟——然而,正确执行(确保没有消息丢失)可能远非微不足道。基于 Unix 的平台确实支持排队信号,并将它们作为单独线程中的事件处理;我不知道 Windows。
Other than that, a named pipe is generally pretty effective; the latency can be as good as shared memory, but it takes more time to get the data through (since it must be copied through the system). And it should be possible to access it directly from Java, without using JNI. Under Unix, it's also possible to configure sockets to respond just as quickly (in fact, this is what a named pipe is under the hood); I don't know if the Java interface supports these configuration options, however, and again, I don't know whether they're available under Windows.
除此之外,命名管道通常非常有效。延迟可以与共享内存一样好,但需要更多时间来获取数据(因为它必须通过系统复制)。而且应该可以直接从 Java 访问它,而无需使用 JNI。在 Unix 下,也可以配置套接字以同样快地响应(实际上,这就是命名管道的内幕);我不知道 Java 接口是否支持这些配置选项,但是,同样,我不知道它们在 Windows 下是否可用。
回答by Raj
An alternative would be to use an embedded DB (since you're considering multiple IPCs, I assume both the applications are on the same machine).
另一种方法是使用嵌入式数据库(因为您正在考虑多个 IPC,我假设两个应用程序都在同一台机器上)。
I use to work on an application earlier where the c++ application fetches data from all sorts of channels and put it in the DB (an in-memory database; TimesTen). In order to display that data to the user, the Java application would query it from the DB.
我以前在一个应用程序上工作,其中 c++ 应用程序从各种渠道获取数据并将其放入数据库(内存数据库;TimesTen)。为了向用户显示该数据,Java 应用程序将从数据库中查询它。
For your use, I don't know if you'd be willing to consider Oracle's Timesten, but you could as well use Berkeley's embedded DB.
对于您的使用,我不知道您是否愿意考虑 Oracle 的 Timesten,但您也可以使用 Berkeley 的嵌入式 DB。