Type Negotiation In Hessian
This article discusses the motivation behind a type negotiation extension to the Hessian binary web services protocol. The goal of this optional extension is to optimize the handling of type information in terms of network overhead, processing overhead and type mapping in non-reflective languages. This extension has been implemented on top of the Caucho Java Hessian implementation version 3.1.3. This article contains a preliminary benchmark and links to download the source of the extension.
Introduction: Building on Hessian 2
Version 2 of the Hessian protocol was designed in part as a performance optimization of version 1. These optimizations center around, amongst others:
- eliminating redundant retransmissions of object type definitions;
- using a more compact type representation for heavily-used primitives such as integers, longs and doubles;
- making string and binary encodings more compact.
On the one hand, these optimizations reduce the processing overhead required to encode and decode application data. On the other hand, they reduce the size of the encoded data by minimizing the number of binary symbols required to represent certain in-memory values. This reduction in the wire format speeds up transmission over a network making any Hessian 2-based interaction faster than its equivalent Hessian 1 encoding over the same network.
The goal of this article is to demonstrate a potential extension to the protocol that takes the optimization concepts behind Hessian 2 one step further.
Complex Type Encoding
When the Hessian 1 generator encodes a non-primitive object, it writes the type information for any given object instance into the encoding scope of that particular instance. Hessian 2 employs an implicit notion of a transmission context within which an object's type structure is defined once and then reused and referred to by all subsequent instances of that particular type. This is the optimization it provides over Hessian 1 with respect to complex type encoding - it eliminates the need to send the same type information multiple times.
The transmission context, although not explicitly defined in the protocol, is effectively a call or a reply, thus bounding the context to an individual request or response.
The effect this has on the wire size is significant, as the benchmark that follows later in this article will demonstrate. This effect is also observed in Daniel Gredler's performance comparison of various different remoting technologies.
Type Negotiation As A Protocol Extension
The proposed extension takes the optimizations within Hessian 2 one step further. This approach widens the context within which type references are valid. Instead of merely back-referencing types that have preceded within the current request, this extension negotiates its type mapping before any application level data is sent back or forth. To do this, the protocol extension summarizes the type mapping in the first invocation that it makes, thereby passing all type information that any subsequent interaction would require up front. There is little difference between this and the current back-referencing built into Hessian 2, except that the transmission context is widened to span multiple request/response cycles.
This forces the protocol to become quasi-stateful, which can be seen as a negative aspect due to the state maintenance that you enforce upon each peer. However, if the protocol were designed to be tolerant of discrepancies of the type mapping between each peer, this would reduce the complexity required to carry out the type negotiation. For example, if any peer were allowed to say at any point in the interaction, "I'm sorry, I don't understand the type you are talking about, can you please resend this information", then you would not even need to establish a formal session because the type information could be requested in an idempotent fashion. This eliminates the need for an explicit transport or application layer session.
The finer details of how this type negotiation would look from a protocol perspective will be pursued in the second part in this series of articles. This installment will concentrate on the motivation and the benefits of the proposed protocol extension.
Benchmark Results
The proof of concept code for this protocol extension is based on the Caucho Hessian library implemented in Java. It builds on top of the current code base to show what the proposed interaction might look like. Also, because it merely extends the current library, it provides a simple comparison without having to factor in any differences that may arise by taking a different approach to the core protocol.
The following chart illustrates the round trip time of a request/response cycle with a representative object model payload, comparing the encoding of Hessian 1, Hessian 2 and the proposed type negotiation that, for the sake of clarity, has been coined Hessian 2.1:

The diagram shows the average roundtrip time in milliseconds when using the HessianProxy and HessianServlet implementations from Caucho. The invocation is a simple test contract that receives an object graph containing six types and sends a different graph as a response. The service contract was tested 50000 times for each of the following:
- the standard Hessian 1 implementation;
- the standard Hessian 2 implementation;
- and the Hessian 2.1 patch.
The code used in this example, which can be downloaded from here, consists of:
- a patch to the Hessian 3.1.3 source tree;
- a maven project containing a test server, a test service contract, test classes and a test runner.
The quintessence of the patch is that it pre-registers the types for which subsequent instances will be sent with the sender. The sender builds a map of these types and sends it in the first call to the receiver. All subsequent calls to encode or decode type information are delegated to the original type map by referencing its keys. By doing so, you only send the type information for each class once.
For a chatty interaction, avoiding this redundancy reduces the wire size per invocation and hence you can observe the encouraging performance characteristics in the benchmark diagram.
To remain as objective as possible, it is important to reflect upon the assumptions made in devising this benchmark:
- The object graph consists of six Java types with the namespace com.squarespace.hopper.types. The relative speed-up of the negotiation is proportional to the number of different types and the string length of their fully qualified names;
- No lists of objects were used, which is why the Hessian 1 results appear to fare favourably in comparison to Hessian 2. If there were more object instances per invocation (for example, by passing lists of objects), using Hessian 2 would be far more efficient than Hessian 1;
- If a greater number of object instances per invocation were employed, the speed-up of the type negotiation would not be as significant as this benchmark indicates. This is the effect described in Daniel Gredler's benchmark;
- The benchmark measures the total round trip time from a client's perspective deploying the service on a local http server. This eliminates any effects of network latency or bandwidth. In a more realistic deployment scenario, one would presumably experience such effects. Hence it is expected that the more compact wire format of Hessian 2.1 would make it even more efficient than Hessian 2 when the effect of the network is factored in.
In summary, the efficiency gain of Hessian 2.1 over Hessian 2 will depend upon the:
- Number of different type definitions in each request/response cycle;
- Total number of object instances per invocation;
- The string length of the namespace;
- The number of separate request/response cycles;
- The latency and bandwidth of the network.
Outlook
This article demonstrates how the type negotiation extension can boost Hessian performance in chatty interaction scenarios and those that exhibit network throughput issues.
Furthermore, it gives the opportunity to establish a more explicit type negotiation that may be of benefit to Hessian implementations in non-reflective and non-OO languages. This will provide these implementations with a standardized way in which to establish type mapping that is specific to that language. In a follow up article, this aspect and the type negotiation protocol flow will be analyzed in greater detail.
I have published a second article in this series that goes into greater detail about the flow of the proposed protocol extension.
References (1)
-
Related: Java Remoting:Protocol Benchmarks

Reader Comments