Java Performance of Ice.Util.createInputStream

in Help Center
Hello,
I am working on an application with some very tight performance requirements.
Below are three typical lines of code for deserializing data.
The SessionStartMessage is a very small message ( 2 strings in it ).
1) Ice.InputStream inputStream = Ice.Util.createInputStream(communicator, msg);
2) SessionStartMessage sessionStart = new SessionStartMessage();
3) sessionStart.ice_read( inputStream );
When I have timed these three lines of code I get a time of 2.5 microseconds. 99 percent
of this time occurs for processing line 1 above ( Ice.Util.createInputStream ).
Is there a way to reuse this stream object as it is so expensive to create or should I be
using a different technique?
Thanks,
Glenn
I am working on an application with some very tight performance requirements.
Below are three typical lines of code for deserializing data.
The SessionStartMessage is a very small message ( 2 strings in it ).
1) Ice.InputStream inputStream = Ice.Util.createInputStream(communicator, msg);
2) SessionStartMessage sessionStart = new SessionStartMessage();
3) sessionStart.ice_read( inputStream );
When I have timed these three lines of code I get a time of 2.5 microseconds. 99 percent
of this time occurs for processing line 1 above ( Ice.Util.createInputStream ).
Is there a way to reuse this stream object as it is so expensive to create or should I be
using a different technique?
Thanks,
Glenn
0
Comments
If you follow the code that executes when you create an input stream, you will see that it doesn't do a lot: it allocates a BasicStream that, in turn, allocates a buffer. Other than that, there is just a handful of member variable initializations.
How big is the message overall? I suspect that a fair amount of the total cost might be copying the data into the internal buffer of the stream.
Cheers,
Michi.
Thank you for your quick response.
What does "different data" mean? Do you mean different slice structures?
Can I use the same stream over again by just rewinding it? If so, can I use
this for different slice structure or do it need one stream per message?
Here is the constructor for this message:
public SessionStartMessage(String username, String password)
{
this.username = username;
this.password = password;
}
So this message is very small. Perhaps 30 bytes or so.
That is why I am a little confused as to why Ice.Util.createInputStream() is taking 2.5
microseconds to execute.
Glenn
You initialize the stream as follows:
The msg parameter is the data that is parsed by the stream. That data cannot be changed after the stream is created.
If you rewind the stream, you can parse the same data again. But, for different messages, you need different streams.
Can you trace into the run time to see how that time is split among the various things that happen as part of createInputStream?
Cheers,
Michi.
Thanks again for being so responsive.
I am a little unsure of how to evaluate library software for which I do not have the source code for.
I have created a couple of methods which I hope demonstrates the issue.
I quess we are down to one remaining question as to why it takes 2.5 microseconds
to Ice.InputStream inputStream = Ice.Util.createInputStream(communicator, msg)
where msg is about 30 bytes in length.
Here are two sample methods which (I think) demonstrates the issue.
The first method attempts to determine how long it take to deserialize
data. I get an average time of 2800 nanoseconds or (2.8 microseconds) when I run this.
I have confirmed that 99 percent of the time is used in the createInputStream() method.
The second method simply creates a new ArrayList and adds an object to it.
When I run this I get an average time of 119 nanoseconds.
Glenn
private void evalSliceDecodeTCSessionStartRequest()
{
SliceMessageCreator sliceMessageCreator = new SliceMessageCreator(ByteOrder.LITTLE_ENDIAN, null);
TCSessionStartRequestMessage sessionStart = new TCSessionStartRequestMessage();
sessionStart.username = "glenn";
sessionStart.password = "kobe";
byte[] msg = sliceMessageCreator.encodeSessionStartMessage(sessionStart);
Communicator communicator = Ice.Util.initialize();
startTime = System.nanoTime();
for ( int i=0; i<TEST_COUNT; i++ )
{
Ice.InputStream inputStream = Ice.Util.createInputStream(communicator, msg);
TCSessionStartRequestMessage sessionStartParse = new TCSessionStartRequestMessage();
sessionStartParse.ice_read( inputStream );
}
System.out.println( "evalSliceDecodeTCSessionStartRequest avg execution time (in nanoSeconds)=" +
( System.nanoTime() - startTime)/TEST_COUNT );
}
private void evalCreateArrayList()
{
SliceMessageCreator sliceMessageCreator = new SliceMessageCreator(ByteOrder.LITTLE_ENDIAN, null);
TCSessionStartRequestMessage sessionStart = new TCSessionStartRequestMessage();
sessionStart.username = "glenn";
sessionStart.password = "kobe";
byte[] msg = sliceMessageCreator.encodeSessionStartMessage(sessionStart);
Communicator communicator = Ice.Util.initialize();
startTime = System.nanoTime();
for ( int i=0; i<TEST_COUNT; i++ )
{
ArrayList arrayList = new ArrayList();
arrayList.add( sessionStart );
}
System.out.println( "evalCreateArrayList avg execution time (in nanoSeconds)=" +
( System.nanoTime() - startTime)/TEST_COUNT );
}
Glenn
Perhaps I'm misunderstand what you are saying, but the full source code for Ice is available for download.
I did not know that the source code is available so thank you for the information.
Unfortunately, I do not have the time to install and configure your source code
in my environment.
I guess the question still stands should this call:
Ice.InputStream inputStream = Ice.Util.createInputStream(communicator, msg);
take 2.5 microseconds to execute with a 30 byte message? Do you see a different
number at your end? This seems way too long to me.
I would think this would be easily reproducible in your environment as well.
Again, thanks to everyone at ICE for being so responsive.
Glenn
To this point we haven't viewed this piece of code as very performance sensitive. I suspect the performance could be somewhat improved with some careful optimization. If it matters for you, you should consider contacting [email protected], and we can discuss how to help you further.
I will give this a try. To date all I have done is use the "ice.jar" file to
use your library.
I am unsure of how to do this: "Ice.CacheMessageBuffers=0". Is this a config
entry in a file? Can I do this directly in code ( preferred )?
Thanks,
Glenn
Ice.CacheMessageBuffers is a property. You can set it from the command line. You can also set it in a configuration file or programatically. See chapter 30 of the manual for more details on the ways to use properties.