Archived

This forum has been archived. Please start a new discussion on GitHub.

Possible ice_isA Performance Improvement

My application can do many thousands or even millions of ice_isA calls. In C++, each ice_isA call generated by slice2cpp does a std::binary_search over the names of the base classes which causes operator< on a std::string to be executed several times for each such call. The deeper the inheritance graph, the more operator< calls will be made. While this isn't horrible, it does have a performance impact when it is called so many times. Consequently I removed the use of ice_isA from my program and implemented it more quickly using pointer comparison. This gave my application a significant performance boost.

Because each class is identified by a static string, it is possible to use pointer comparison on the address of the static string rather than do whole string comparisons. This would also eliminate redundant strings for the same class. Because operator< for a pointer is significantly faster than operator< for a std::string, there is a significant performance improvement in ice_isA if it compare the address of the class names rather than the class names themselves.

Implementing this would be a bit of work, but shouldn't be too bad. The main points are:
  1. Only generate one static std::string object for each class.
  2. Populate the __Class__ids array with addresses of the strings for the necessary class by making calls to Class::ice_staticId
  3. When comparing items in the _ids array make sure take the address of _s to compare against pointers.
  4. When returning items from the _ids array, dereference the pointer.

The only down side of this approach is that the user cannot specify an arbitrary string to ice_isA. That shouldn't be a problem in practice because the caller should only be passing in the result of Class::ice_staticId() calls anyway.

I have considered patching slice2cpp to implement the above. It would save me a few hundred lines of code that I've written on the side and it would work on anything I generate with slice2cpp without needing to maintain my side implementation.

Another idea is to use some template magic to achieve the same thing with very little overhead and even better performance. The mechanism I have in mind is implemented in the casting.h header of the LLVM project.

If zeroc.com is interested in either such a patch, please let me know and I'll consider contributing it.

Comments

  • bernard
    bernard Jupiter, FL
    Hi Reid,

    ice_isA is a remote operation so its parameter is usually a string passed "over the wire" from a remote client. For a non-collocated invocation, the address of this string parameter will always be different from the address of static strings in your C++ program.

    It's unusual to call ice_isA directly: typically, you call checkedCast on a proxy, and in turn the implementation of checkedCast calls ice_isA.

    Could you describe why your application calls ice_isA so often?

    Depending on your application, a better solution could be to replace some of your checkedCasts by uncheckedCasts.

    Best regards,
    Bernard
  • Hi Bernard,

    I forgot this was a remote operation so for the reasons you described my approach wouldn't work. In my case, I'm using a rather large and complicated set of Ice classes merely as data. These classes have no methods in their interface but large graphs of them are passed in calls to other interfaces. Consequently, these classes are only ever manipulated locally in my case. The ice_isA calls are made so frequently because it is typical for me to pass around graphs with thousands of nodes and then doing some intense processing on that graph. Each time I encounter a node, I need to know its type. Sure, I could use polymorphism by adding some methods to these classes, but that has downsides elsewhere.

    Anyway, I'll just keep my side implementation as it seems to do the job.

    Thanks for the quick reply!
  • bernard
    bernard Jupiter, FL
    Hi Reid,

    checkedCast and by extension ice_isA is used to transform a proxy into another proxy.

    If you have a graph of objects, you probably don't need and don't want to use checkedCast or ice_isA.

    Did you consider using xxxPtr::dynamicCast in your graph processing?

    This thread also describes an alternative dynamicCast syntax:
    http://www.zeroc.com/forums/comments/4881-addition-handle-staticcast.html

    Best regards,
    Bernard