The short answer is unfortunately yes. There are many factors that contribute though: I have found several of them and will try to explain what I have found as thoroughly as possible.
NOTE: Actual timings don't mean a thing as they only apply to the computer you run on. Below, you will find the timings I measured on my instrumented GT3 installation running on my particular hardware with my particular version of the JVM. The important thing to remember from the figures are their RELATIVE sizes.
Timings are denoted in milliseconds throughout this document. Prefixes K
and M
denote kibi and mibi, not kilo and mega.
What hits you and accounts for the many seconds is the initialization of the underlying tooling in your client: initializing the Axis handlers and the XML security libraries account for the major part of this time.
In addition, there are many other one-time operations happening,
such as initializing the secure random number generator, loading the
proxy certificate and your trusted CA certificates from disk,
loading the WSDL defining the factory service porttype, and finally
establish a security context with the server when using
GSI-SecureConversation (which you tend to do). None of this is
performed if you were to create a second service instance in the
same security context.
The DummyService tests make use of HMAC, a lightweight form of creating a digital signature to ensure message integrity. Another alternative is full-blown encryption. The table below displays characteristics for both. The case of no encryption (plain) is shown as well.
Security | Payload (b) | SOAPsize (b) | T(engine) | T(roundtrip) |
plain | 16 | 481 | 0 | 15 |
plain | 16000 | 16465 | <10 | 23 |
plain | 160000 | 160465 | 20 | 106 |
HMAC | 16 | 1390 | 40 | 120 |
HMAC | 16000 | 17490 | 70 | 250 |
HMAC | 160000 | 161400 | 360 | 1100 |
Encr | 16 | 1570 | 30 | 75 |
Encr | 16000 | 23200 | 80 | 220 |
Encr | 160000 | 218050 | 500 | 1380 |
SOAPsize
is the average size of request/response
messages for an Service.echo(Payload)
operation: the
incoming and outgoing messages differ by only 50-60 bytes. Encrypted
data gets Base64-encoded which increases the the wire message sizes by
33%.T(engine)
is the time spent in the Axis engine itself
on the server. Time spent (de-)serializing the SOAP messages
and doing the HTTP transfer is NOT included, but can be derived
from the roundtrip time.T(roundtrip)
is the total roundtrip time, measured on the client side.Encr
and HMAC
timings do NOT include the time for establishing
a shared security context between client and server (GSI-SecureConversation).
I think this is where the DummyService tests made were WRONG: they put many clients on the same machine, expecting to create a huge load on the server. In fact, the load on the client machine was just as high, and this may attribute to the fact that the CPU utilization on the server was not 100% when it reached "max".
Notice also that the poor implementation of XML security hits you
4-fold on the roundtrip time, as you need to encrypt and decrypt on
both client and server side, in sequence. Thus, for every msec of
overhead that we can save by improving the implementation of this
library, we will gain 4.
The handshake between the client and the server is an exchange of 3
roundtrip messages in total. In my case, the size of the SOAP messages
sent were {request,response}:
{787,3275} {2606,787} {670,686}
BUT, this is for establishing a context only. In the
DummyService case, the client performs a credential delegation to the
service instance as well; This costs an additional roundtrip. The exchange
pattern and corresponding messages sizes in my case were:
{787,3275} {2606,787} {670,1131} {1322,686}
A handshake with delegation implies much more work for the involved
parties as it involves the creation and validation of a RSA key
pair: the four roundtrips takes roughly 400 msec to complete.
In the case of the secure DummyService client (source code), this means the following message pattern:
create()
echo()
getTime()
destroy()
on GridService port type
Notice the BUG in the client program: the service instance is
destroyed without any security! Furthermore, since the DummyService
does not extend the GridService port type, the client needs to grabs
a new reference to a GridService port type from the same service
locator. The new reference would need 3 additional roundtrips in
order to establish a new security context with this new port type,
before invoking destroy()
. (One can argue heavily that
all this is nothing but a good example of stupid shortcomings in the
tooling.)
The tooling works much better in scenarios where initialization cost is neglible, for instance when you perform hundreds of invocations using the same security context: The overhead can then be measured in additional 10ths of milliseconds for small payloads.
On a related note, Java Hotspot works quite well on GT3: while performing
hundreds of invocations on the same service instance, you will gradually
see improvements on both client and server side that eventually cut as
much as 40% of the roundtrip time.
In the meanwhile, I suggest we concentrate us on the XML security library and its duplicate parsing and internal use of XPath queries: any millisecond saved there will cut the roundtrip time by 4.
A study by Networkshop showed a Pentium server with Linux and Apache supporting 322 unsecured sessions, when SSL was turned on; the connects per second decreased to 2.4.
GSI Secure Conversation, especially when used with delegation, is an expensive operation. It is recommended that this mechanism not be used unless delegation is required.
For all operations not requiring delegation, GSI Secure Message would be an option which has lesser performance penalities. This currently has only integity (signature) option.
Security | Payload (b) | T(roundtrip) | ||
plain | 16 | 13.56 | ||
plain | 16000 | 53.53 | ||
HMAC | 16 | 275.51 | ||
HMAC | 16000 | 626.09 | ||
Encr | 16 | 163.58 | ||
Encr | 16000 | 603.72 |