Go Back   ZeroC Forums > Help Center

Reply
 
LinkBack Thread Tools Rate Thread Display Modes
  #1 (permalink)  
Old 04-28-2004
brian brian is offline
Registered User
 
Name: brian whitney
Organization: boulder research and development
Project: MarketBank
 
Join Date: Oct 2003
Posts: 119
Passing Java Objects using Slice

Hi Again,

We are currently trying to convert our JNI layer to using ICE. One of our JNI routines is fairly generic in that it can take an array of the Java Object type with associated information on each object's type -- the type can be an int, double, or Map. The C++ JNI layer then processes each value in the array according to its type. The array of Object values can contain data of any of the 3 types mentioned.


Since there is no direct support for the Java Object type in Slice, was wondering if anybody had any suggestions on how to port this to ICE? The only thing we can think of at this point is to pass all data as strings and convert them on our C++ server side, but this would be an non-optimal soluation.

Thanks,

Brian
Reply With Quote
  #2 (permalink)  
Old 04-28-2004
marc's Avatar
marc marc is offline
ZeroC Staff
 
Name: Marc Laukien
Organization: ZeroC, Inc.
Project: The Internet Communications Engine
 
Join Date: Feb 2003
Location: Florida
Posts: 1,781
You could create a Slice abstraction using classes, that covers all Java data types you are using. For example:

Code:
class AnyType { };

sequence<AnyType> AnyTypeSeq;

dictonary<string, AnyType> AnyTypeDict; // Assuming your map key is a string

class IntType extends AnyType { int value; };

class DoubleType extends AnyType { double value; }

class MapType extends AnyType { AnyTypeDict value; }
You can then use operations like:

Code:
void foo(AnyTypeSeq values);
Note, however, that this code is not as efficient as if you would have a separate methods for each type, i.e., classes have some overhead. Please see the Ice manual for more details.

If you want to encode/decode the values by hand, then you should use a sequence<byte>, not a string.
Reply With Quote
  #3 (permalink)  
Old 04-30-2004
brian brian is offline
Registered User
 
Name: brian whitney
Organization: boulder research and development
Project: MarketBank
 
Join Date: Oct 2003
Posts: 119
Thanks for the reply Marc.

I agree about that I would like to avoid the overhead of using classes in this situation.

Why do you say that we should pass these as bytes instead of strings?

Is there any direct support in Ice for encoding and decoding sequences of bytes? (They only thing I found in the many is the IceUtil::Base64 class). We would have to be able to pass different data types between Windows and Unix, C++ and Java.

Brian
Reply With Quote
  #4 (permalink)  
Old 04-30-2004
mes's Avatar
mes mes is offline
ZeroC Staff
 
Name: Mark Spruiell
Organization: ZeroC, Inc.
Project: Ice Developer
 
Join Date: Feb 2003
Location: California
Posts: 971
Hi Brian,

Marc recommended a byte sequence over a string because a byte sequence is more compact and easier to encode and decode.

You can encode to a byte sequence, but you'll have to use an undocumented class (IceInternal::BasicStream). You can find examples of this in the Freeze implementation.

Of course, the decoder will need some way of determining the next type to be decoded from the stream. In other words, each byte sequence must have a fixed format, or you must embed some type identifier in the sequence in order to signal the decoder about the next type.

Are you that concerned about overhead that you're willing to go to these lengths? Perhaps you should try the technique Marc described first?

Take care,
- Mark
Reply With Quote
  #5 (permalink)  
Old 05-01-2004
brian brian is offline
Registered User
 
Name: brian whitney
Organization: boulder research and development
Project: MarketBank
 
Join Date: Oct 2003
Posts: 119
Thanks for the reply, Mark.

I do not want to use classes for the reason that Marc pointed out -- overhead.

I understand what you say about not using strings for compactness reasons, but if I am converting doubles and ints to strings and then converting them back, its seems like that "encoding and decoding" is far more straightforward than trying to use BasicStream., n'est pas? Although maybe that is a naive question: when converting between different architectures like Windows and Unix, do you need to swap bytes or something when converting a string to a double or int when "unmarshalling" it?

The other type we would pass is Map, which would just be key/value pairs that are always strings.

Anyway, I'd love to get your feedback on a couple of ways I was thinking of doing this. (I've looked at the source for BasicStream, Buffer, and EvictorI.cpp in Freeze and tried to glom as much as possible without having documentation... )

Method 1: (passing bytes -- more efficient?)

in Slice:

enum DataType { Integer, Double, Map }

struct TypedBytes
{
DataType dataType;
Ice::ByteSeq dataBytes;
}

In C++ Server:

Ice::CommunicatorPtr communicator = Ice::Current.adapter.getCommunicator();
IceInternal::InstancePtr instancePtr = IceInternal::getInstance( communicator );
IceInternal::BasicStream basicStream( instancePtr.get() );
TypedBytes typedbytes;

....

basicStream.b.clear();

switch ( native type )

case double:
double value = ...
typedBytes.dataType = DataType.Double;
basicStream.write( value );
typedBytes.dataBytes = basicStream.b;
.....


In Java Client:


TypedBytesHolder typedBytes = ....
switch ( typedBytes.DataType )

case Double:
basicStream.read( (double)typedBytes.dataBytes.value )
double value = (double)typedBytes.dataBytes.value;

I have a feeling I am way off base on usage of BasicStream here, but I gave it my best shot.


Method 2: (passing strings -- easier implementation?)


in Slice:

enum DataType { Integer, Double, Map }

struct TypedBytes
{
DataType dataType;
Ice::StringSeq dataStrings; // no type conversion needed for generating key/value Map entries
}

In C++ Server:

case Double:
double value = ...
std:stringstream os;
os << value;
typedBytes.dataStrings.push_back( os.str() );

In Java Client:

case Double:
Double.valueOf( typedbytes.dataStrings[0] )

Don't want you to write code for me, but just wondering what you thought of these implementations and if they are even on the right path.

Thanks again,

Brian
Reply With Quote
  #6 (permalink)  
Old 05-02-2004
mes's Avatar
mes mes is offline
ZeroC Staff
 
Name: Mark Spruiell
Organization: ZeroC, Inc.
Project: Ice Developer
 
Join Date: Feb 2003
Location: California
Posts: 971
Hi Brian,

Ah, now I understand what you're thinking. I was under the impression, and probably so was Marc, that you were wanting to send multiple values in a single string or byte sequence, in which case the byte sequence has several advantages.

However, in the example you provided, it does seem like your second solution is easier, and also avoids reliance on undocumented Ice internals. As long as you can live with the potential loss of precision when transmitting doubles, this looks like the simpler approach.

Another approach that avoids the string conversion is to use a struct:
Code:
struct Value
{
    DataType type;
    int i;
    double d;
    StringMap m;
};
sequence<Value> ValueSeq;
The type member indicates which data member is used. Of course, there is still some overhead:
  • 9 bytes wasted for an int
  • 5 bytes wasted for a double
  • 12 bytes wasted for a map
Hope that helps,
Mark
Reply With Quote
  #7 (permalink)  
Old 05-02-2004
brian brian is offline
Registered User
 
Name: brian whitney
Organization: boulder research and development
Project: MarketBank
 
Join Date: Oct 2003
Posts: 119
Sorry for the confusion, Mark. I should have articulated the problem better.

Why is there a loss of precision when encoding a double into a string and then decoding back into a double? (We are doing stock price manipulation, not rocket trajectories so we are probably okay with 5 or 6 digits to the right of the radix. We actually might go to regular floats. )

Brian
Reply With Quote
  #8 (permalink)  
Old 05-02-2004
brian brian is offline
Registered User
 
Name: brian whitney
Organization: boulder research and development
Project: MarketBank
 
Join Date: Oct 2003
Posts: 119
Hi Mark,

Thinking more about your suggestion of a mixed type struct...

Are you suggesting that because you think the cost of encoding/decoding doubles and int in/out of strings is more than the cost of sending the extra bytes in your solution? I know it depends on a number of factors, but just generally speaking.

Thanks again,

Brian

P.S. There is another reply I sent previous to this one.
Reply With Quote
  #9 (permalink)  
Old 05-03-2004
mes's Avatar
mes mes is offline
ZeroC Staff
 
Name: Mark Spruiell
Organization: ZeroC, Inc.
Project: Ice Developer
 
Join Date: Feb 2003
Location: California
Posts: 971
Quote:
Originally posted by brian
Why is there a loss of precision when encoding a double into a string and then decoding back into a double? (We are doing stock price manipulation, not rocket trajectories so we are probably okay with 5 or 6 digits to the right of the radix. We actually might go to regular floats. )
If you have a process that supplies enough precision for your needs, then that's fine with me. Personally I prefer the binary approach, just to know that all the bits are getting there.

Quote:
Thinking more about your suggestion of a mixed type struct...

Are you suggesting that because you think the cost of encoding/decoding doubles and int in/out of strings is more than the cost of sending the extra bytes in your solution? I know it depends on a number of factors, but just generally speaking.
I doubt that the string conversion would be much of a burden, unless the volume was large.

Here's a similar strategy that reduces the wasted space of my previous example:
Code:
sequence<int> IntSeq;
sequence<double> DoubleSeq;

struct Value
{
    DataType type;
    IntSeq i;
    DoubleSeq d;
    StringMap m;
};
sequence<Value> ValueSeq;
If you can live with the use of a sequence when you only need to transfer a single integer or double, then this strategy results in the following overhead:
  • 3 bytes wasted for an int
  • 3 bytes wasted for a double
  • 2 bytes wasted for a map
Mark
Reply With Quote
  #10 (permalink)  
Old 05-03-2004
mes's Avatar
mes mes is offline
ZeroC Staff
 
Name: Mark Spruiell
Organization: ZeroC, Inc.
Project: Ice Developer
 
Join Date: Feb 2003
Location: California
Posts: 971
Actually, you could also eliminate the DataType enumeration from my last example, because the selected member is implied by the non-empty sequence or map. That saves another byte in each Value instance.

Now it may not be critical that you save every last byte, in which case you'd have to decide whether the savings is worth a less "obvious" solution.

Take care,
- Mark
Reply With Quote
  #11 (permalink)  
Old 05-03-2004
michi's Avatar
michi michi is offline
ZeroC Staff
 
Name: Michi Henning
Organization: ZeroC
Project: Ice
 
Join Date: Feb 2003
Location: Brisbane, Australia
Posts: 912
I would strongly recommend to go with the class-based solution that Marc recommended. That solution is clean, with strong typing, and expresses the problem domain appropriately. If you go with some trick to encode the values into byte sequences (or other sequences), at the very least, that obscures the issue.

The overhead added by the class-based solution will be unnoticeable in all but the most performance-critical situations. I would convince myself first that my application really is that close to my performance limits before considering other approaches.

The encoding into byte sequences is unlikely to gain you anything whatsoever because, in effect, that bypasses the marshaling/unmarshaling code in Ice, but your application code is highly unlikely to get the marshaling/unmarshaling done any quicker than Ice.

Cheers,

Michi.
Reply With Quote
Reply



Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

Similar Threads
Thread Thread Starter Forum Replies Last Post
passing objects nicole Help Center 5 02-12-2007 10:12 PM
Why Java proxies does not implement the slice interface ? annekat Comments 12 03-24-2006 11:38 AM
passing a context to a locator robert Help Center 4 10-23-2004 12:26 PM
How to deal with existing java objects? vsonnathi Help Center 1 06-02-2004 05:41 PM


All times are GMT -4. The time now is 10:00 AM.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.0.0
(c) 2008 ZeroC, Inc.