I have a c process which needs to send a lot of c structs (roughly 10,000 per second) to a java process that needs to put the data into a matching class.
The size of the data that needs to be sent will be around 50-100 Byte per packet.
Latency is a concern as the data needs to be displayed in real time, which is why i am looking for alternatives to my current solution.
Currently im doing this with JNI and a POSIX message queue. Is there a better way than using JNI and message queues/pipes? I read somewhere that calling JNI methods often has a lot of overhead. Could this become a problem when a lot of data has to be sent?
Another solution i had in mind was to just write the data to a UNIX Socket and parse it in java.
-
Is there a need for the code in Java and the one in C to run in two distinct processes?Samuel Audet– Samuel Audet2015年12月24日 05:38:41 +00:00Commented Dec 24, 2015 at 5:38
-
@SamuelAudet Yes, the data comes from a plugin for an IDS which has to process network packets as fast as possible. After processing a packet we send the decoded data to another process which does the graph handling. Furthermore the c process runs as a service while the java program should be independently startet or stopped when one desires to, without influencing the running c program.Mark G– Mark G2015年12月24日 11:40:50 +00:00Commented Dec 24, 2015 at 11:40
-
So, I'm guessing a memory mapped file would be the most efficiency way to do to this, and that appears to be the case: stackoverflow.com/a/6412333/523744Samuel Audet– Samuel Audet2015年12月25日 08:51:52 +00:00Commented Dec 25, 2015 at 8:51
3 Answers 3
If you must process the data eventually using Java, then remove as many intermediate steps as possible.
If you can read the data directly into Java ( bypassing JNI and the C code ), then do so. Avoid the JNI, message queue and (presumably) a stage where C receives the data. The queue can't be helping latency either.
If the data starts in a C-friendly form that is unfriendly to Java, then I;d consider switching entirely to C or C++ rather than processing in Java at all.
3 Comments
You can achieve high throughput by avoiding unnecessary copying of memory. Transfer data between C and Java through direct byte buffers. From the Java side, you can then read the data in the byte buffers and copy values into the object fields. For two processes talking to each other, you could use a memory mapped file to do this (you would use a MappedByteBuffer for this).
For something simpler but with a bit more overhead, you could simply use the stdin/stdout of each process to communicate and send data that way. Or, as you suggested, a socket is another option.
With 10,000 structs at 100 bytes each, this will be 1 MB / second of data processed. This really shouldn't be a problem on modern hardware (for one of my projects I have managed easily over 1GB / second between direct buffers and Java objects with primitive + array fields, but this was all in one process between JNI and Java).
You might want to use the simpler approach first (stdin/stdout) and see is that fast enough first before digging into using memory mapped files.
1 Comment
This, I think, can be solved using typical IPC methods. I would use pipes over a message queue and sockets. The overhead of message queue is going to slow the processing. And pipes are faster than sockets but not by much.
For your issue, 10,000 structs at 100 bytes per packet comes to 1 MB/s. A modern multicore processor will handle this without a problem.