Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Design for performance, Part 3: Remote interfaces

Learn to avoid performance hazards when designing Java classes

  • Print
  • Feedback
This series explores some of the ways in which early design decisions can significantly affect application performance. Part 1, examined how a class's object-creational behavior can be embedded in its interface. Certain interface constructs virtually require that a class create temporary objects, or that its callers create temporary objects in order to use the class. Because temporary object creation is a significant performance issue for Java programs, it pays to review your class interfaces for performance hazards while you can still do something about it -- at design time.

I focused on object creation in Parts 1 and 2 because it is a significant performance problem for many Java programs. However, in distributed applications, such as those built on RMI, CORBA, or COM, an entirely different set of performance issues comes into play. This article explores some of the performance issues specific to remote applications and shows how you can predict many distributed application performance problems simply by examining a class's interface.

Read the whole "Design for Performance" series:



An overview of remote invocation

In distributed applications, an object running on one system can invoke methods on objects running in another system. That is accomplished with the aid of a great deal of machinery that makes the remote objects appear local. To access a remote object, you first need to find it, which can usually be accomplished through the use of a directory or naming service, such as the RMI registry, JNDI, or the CORBA naming service.

When you obtain a reference to a remote object through a directory service, you don't receive an actual reference to that object, but rather a reference to a stub object that implements the same interface as the remote object. When you invoke a method on the stub object, the stub has to marshal the method parameters -- convert them into a byte-stream representation, a process similar to serialization. The stub sends the marshaled parameters over the network to a skeleton object, which unmarshals them and invokes the actual remote method you wanted to invoke. Then the method returns a value to the skeleton, the skeleton marshals the return value and ships it to the stub, and the stub unmarshals it and returns the value to the caller. Phew! That's a lot of work for a single method call. Clearly, despite an outward similarity, a remote method invocation is a more expensive operation than a local method invocation.

The above description glosses over some important details that are significant for program performance. What happens when a remote method returns not a primitive type, but an object? That depends. If the returned object is a type that supports remote method invocation, then it creates a stub and skeleton object, as is the case when looking up a remote object in the registry. That is clearly an expensive operation. (Remote objects support a form of distributed garbage collection, which involves each of the participating JVMs maintaining a thread for talking to the remote garbage collection thread of other JVMs, and sending reference status information back and forth.) If the returned object doesn't support remote invocation, then all of the object's fields and any objects referenced by the returned object have to be marshaled, which could also be an expensive operation.

  • Print
  • Feedback

Resources
  • Books on Java performance:
  • Distributed application design
  • Read more from Brian Goetz: