Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Design for performance, Part 3: Remote interfaces - JavaWorld March 2001

Design for performance, Part 3: Remote interfaces - JavaWorld March 2001

Tutorial Details:

Design for performance, Part 3: Remote interfaces
Design for performance, Part 3: Remote interfaces
By: By Brian Goetz
Learn to avoid performance hazards when designing Java classes
his 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:
Part 1: Interfaces matter
Part 2: Reduce object creation
Part 3: Remote interfaces
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.
Performance comparison between remote and local method invocation
The performance characteristics of remote object access differ from those of local access:
Remote object creation is more expensive than local object creation. Not only does the object need to be created if it does not already exist, but the stub and skeleton objects need to be created, and they have to be made aware of each other.
Remote method invocations involve a network round-trip -- the marshaled parameters must be sent to the remote system and the response must be marshaled and sent back before the calling program regains control. The delays from marshaling, unmarshaling, network latency, and the actual remote invocation are additive; the client generally waits while all of those steps are being accomplished. The costs of a remote invocation also vary depending on the latency of the underlying network.
Different data types have different marshaling overhead. Marshaling primitive types is relatively inexpensive; marshaling simple objects like Point or String is slightly more expensive; marshaling remote objects is much more expensive, and marshaling objects that reference many other objects (like collections) can be even more expensive. That is in stark contrast to local invocations, for which passing a reference to a simple object is no less expensive than passing a reference to a complex object.
Interface design is critical
A poorly designed remote interface can kill a program's performance. Unfortunately, the characteristics that make for a good interface design for local objects can prove inappropriate for remote objects. Excessive temporary object creation, as discussed in parts 1 and 2 of this series, can hamper distributed applications too, but excessive round-trips are an even bigger performance problem. Therefore, calling a remote method that returns multiple values contained in a temporary object (such as a Point ) rather than making multiple consecutive method calls to retrieve them individually is likely to be more efficient. (Note that this is exactly the opposite of the advice I offered in Part 2 for local objects.)
Some important performance guidelines for designing remote applications:
Watch out for unnecessary round-trips. If a caller wants to retrieve several related items simultaneously, make it easy to do so in one remote invocation, if possible.
Watch out for returning remote objects when the caller may not need to hold a reference to the remote object.
Watch out for passing complex objects to remote methods when the remote object doesn't necessarily need to have a copy of the object.
Fortunately, you can spot all of these problems simply by looking at the remote object's interface. The sequence of method calls required to perform any high-level action is usually obvious from the class interface. If you see that a common high-level operation requires many consecutive remote method calls, this should be a warning sign that perhaps you need to revisit the class's interface.
Techniques for reducing remote invocation overhead
As an example, consider the following hypothetical application for managing a corporate directory: A remote Directory object dispenses references to DirectoryEntry objects, which represent entries in a phone book:
public interface Directory extends Remote {
DirectoryEntry[] getEntries();
void addEntry(DirectoryEntry entry);
void removeEntry(DirectoryEntry entry);
}
public interface DirectoryEntry extends Remote {
String getName();
String getPhoneNumber();
String getEmailAddress();
}
Now, suppose you want to use the Directory facility in a GUI email application. The application first calls getEntries() to retrieve a list of entries, and then calls getName() on each entry, populating a list box with the results. When the user selects a recipient, the application then calls getEmailAddress() on the corresponding entry to retrieve the email address.
How many remote method invocations must occur before you can compose an email? You must call getEntries() once, getName() once for each entry in your address book, and then getEmailAddress() once. So if there are N entries in your address book, you have to make N+2 remote invocations. Note that you also must create N+1 remote object references, which is also an expensive operation. Not only would that slow the process of opening an email window if you had numerous names in your address book, but it would also create heavy network traffic and place a high load on your directory server application, leading to scalability problems.
Now consider this improved interface for Directory :
public interface Directory extends Remote {
String[] getNames();
DirectoryEntry[] getEntries();
DirectoryEntry getEntryByName(String name);
void addEntry(DirectoryEntry entry);
void removeEntry(DirectoryEntry entry);
}
How much will this reduce the overhead imposed on your email application? Now you can call Directory.getNames() once and retrieve all the names simultaneously, and you only have to call getEntryByName() for the recipient to which you actually wish to send email. This process requires three remote invocations, instead of N+2 , and two remote objects, instead of N+1 . If the address book has more than a few names, this invocation reduction will make a huge difference in application responsiveness and in total network and system load.
This technique used to reduce remote invocation and reference-passing overhead is called using a secondary object identifier . Instead of passing back a remote object, use an identifying attribute of the object -- in the case of the email application, the name -- to act as a lightweight identifier for the object. The secondary identifier conveys enough information about the object it describes so that you only need to fetch the remote objects you actually need. In the case of a directory system, a person's name is usually a good secondary identifier. As another example, in a securities portfolio management system, a stock's ticker symbol could be a good secondary identifier.
Another useful technique for reducing the number of remote invocations is bulk retrieval. You could further improve the Directory interface by adding another method to retrieve multiple desired DirectoryEntry objects at once:
public interface Directory extends


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Design for performance, Part 3: Remote interfaces - JavaWorld March 2001

View Tutorial:
Design for performance, Part 3: Remote interfaces - JavaWorld March 2001

Related Tutorials:

3D graphics programming in Java, Part 3: OpenGL
3D graphics programming in Java, Part 3: OpenGL
 
I want my AOP!, Part 1
I want my AOP!, Part 1
 
A birds-eye view of Web services
A birds-eye view of Web services
 
Cache SOAP services on the client side
Cache SOAP services on the client side
 
Step into the J2EE architecture and process
Step into the J2EE architecture and process
 
Business process automation made easy with Java, Part 2
Business process automation made easy with Java, Part 2
 
Check out three collections libraries
Check out three collections libraries
 
Sun boosts
Sun boosts enterprise Java
 
Get the inside track on J2EE architect certification
Get the inside track on J2EE architect certification
 
Unwrap the package statement's potential
Unwrap the package statement's potential
 
Create client-side user interfaces in HTML, Part 2
Create client-side user interfaces in HTML, Part 2
 
Worth reading
Worth reading
 
Maybe the future UI design of choice
Maybe the future UI design of choice
 
XStream
XStream is a simple library to serialize objects to XML and back again.
 
JLAN Server v3.3
JLAN Server v3.3 JLAN Server is a high performance JavaTM based file server supporting Windows file sharing (SMB/CIFS), NFS and FTP protocols. Write your own virtual filesystems with the core server handling all protocol exchanges with the client. Incl
 
Access Windows Performance Monitor counters from Java, Part 1
Access Windows Performance Monitor counters from Java, Part 1 Use a simple Java API to gather valuable performance statistics Summary Windows NT, 2000, 2003, and XP contain a utility called the Performance Monitor that provides a rich array of perform
 
Dynamic Delegation and Its Applications
Dynamic Delegation and Its Applications The Proxy pattern is an important and widely used design pattern in object-oriented programming. Do you ever use Proxy in Java since its introduction in JDK 1.3? A dynamic proxy class is a class that implements a l
 
A well-behaved Jetspeed portlet
This article presents a working example of how to construct a Jetspeed portlet that runs efficiently, adheres to the Model 2 architecture, and, by not interfering with additional portlets, plays well with others. In addition, I demonstrate some simple way
 
What is Persistence Framework?
What is Persistence Framework? What is Persistence Framework? A persistence framework moves the program data in its most natural form (in memory objects) to and from a permanent data store the database. The persistence framework manages the
 
Solaris 10 OS Certification Beta Exams
If you are an expert in system and network administration, you can get involved in the creation of three new Solaris 10 certification exams. These Beta exams count toward official Solaris Certification and allow you to provide comments and technical feedb
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.