I posted some ideas for a new CLIPC feature that I am currently calling "shared memory FIFOs". For those who are interested, please take a look at the posting on the SourceForge site and post any thoughts, concerns, etc.
The link is:
http://sourceforge.net/apps/wordpress/clipc/2009/06/29/smfifos/
(Note: this link previously pointed to a page that asked you for a password. It has been updated so that it no longer does that.)
Showing posts with label Shared Memory. Show all posts
Showing posts with label Shared Memory. Show all posts
Sunday, June 28, 2009
Thursday, March 12, 2009
JRE and Shared Memory Overhead
Shared memory access in Java appears to be about 3 times slower than it could be.
In another post, I mentioned that ByteBuffer and its related classes provide a way for Java developers to access shared memory without having to resort to JNI. The problems come in when you try to perform operations on that segment.
One approach is to get a reference to an array of bytes that represents the data in the segment and then use the regular array syntax to access the data. The ByteBuffer.array() method appears to be the the way to do this, but unfortunately it does work.
Here is an example of what I mean:
After looking around a bit, I came to the conclusion that this was the intention of the original developers --- if you want to mess with the data in the segment, then you are supposed to use ByteBuffer.get/put.
This would be fine if get/put were about the same cost as using a straight byte array, but they appear to be 2 to 3 times slower. Here is a simple program that highlights the issue I'm running into. The basic difference is that one version uses:
And the other that uses
The program performs these operations millions of times and then prints out the time (in milliseconds) they took to run. An example output:
One thing this shows is that I really need to upgrade my system.
The basic point is that using get/put is a lot slower than using simple arrays. A program that reads and writes a lot of data in shared memory would be a lot faster if it could simply use an array rather than get/put.
Is there a way around this?
In another post, I mentioned that ByteBuffer and its related classes provide a way for Java developers to access shared memory without having to resort to JNI. The problems come in when you try to perform operations on that segment.
One approach is to get a reference to an array of bytes that represents the data in the segment and then use the regular array syntax to access the data. The ByteBuffer.array() method appears to be the the way to do this, but unfortunately it does work.
Here is an example of what I mean:
// DOES NOT WORK!!
MappedByteBuffer mbb;
// code to initialize mbb omitted
byte[] ba = mbb.array(); // throws UnsupportedOperationException
After looking around a bit, I came to the conclusion that this was the intention of the original developers --- if you want to mess with the data in the segment, then you are supposed to use ByteBuffer.get/put.
This would be fine if get/put were about the same cost as using a straight byte array, but they appear to be 2 to 3 times slower. Here is a simple program that highlights the issue I'm running into. The basic difference is that one version uses:
b1 = bb.get(0);
bb.put(0, b2);
And the other that uses
b1 = bb[0];
bb[0] = b2;
The program performs these operations millions of times and then prints out the time (in milliseconds) they took to run. An example output:
Using get/put: 11578
Using array access: 3234
One thing this shows is that I really need to upgrade my system.
The basic point is that using get/put is a lot slower than using simple arrays. A program that reads and writes a lot of data in shared memory would be a lot faster if it could simply use an array rather than get/put.
Is there a way around this?
Wednesday, March 11, 2009
Shared Memory Using MappedByteBuffer
Java developers can access shared memory using the NIO class MappedByteBuffer. Here is an example:
The segment can be changed or read using the get/put methods defined by the ByteBuffer class. A different Java process that uses the same set of of calls will get the same shared memory: if they change their instance you will see the changes and vice versa. What's more, this also applies to non-java processes that use the same file name and memory mapped system calls.
I have tried this on Windows and Linux and I have also taken a look at the implementation code on java.net It appears that both platforms are using memory mapped files.
As an aside, "memory mapped files" are an approach to using shared memory that appear to have originated with Unix. Unix tries to make most things look like files, so representing shared memory that way is pretty consistent with the Unix philosophy.
For those who are interested, here is a more complete example.
RandomAccessFile rac = new RandomAccessFile("<some file name>", "rw");
FileChannel channel = rac.getChannel();
MappedByteBuffer buf = channel.map(MapMode.READ_WRITE, 0, 1024);
This will create a shared memory segment with the name of the file passed to RandomAccessFile. The segment will start out with the contents of that file, if it exists. If the file does not exist, then it will be created.The segment can be changed or read using the get/put methods defined by the ByteBuffer class. A different Java process that uses the same set of of calls will get the same shared memory: if they change their instance you will see the changes and vice versa. What's more, this also applies to non-java processes that use the same file name and memory mapped system calls.
I have tried this on Windows and Linux and I have also taken a look at the implementation code on java.net It appears that both platforms are using memory mapped files.
As an aside, "memory mapped files" are an approach to using shared memory that appear to have originated with Unix. Unix tries to make most things look like files, so representing shared memory that way is pretty consistent with the Unix philosophy.
For those who are interested, here is a more complete example.
Subscribe to:
Posts (Atom)