users@glassfish.java.net

Re: Why are Remote method calls so expensive?

From: <glassfish_at_javadesktop.org>
Date: Thu, 24 Jan 2008 21:06:09 PST

I started with a bone simple Session Bean with a remote interface. The return type is a List<SomeClass>, the class consists of 30 fields, that are a mix of Strings, Integer, and BigDecimals plus 2 internal Lists with their own domain objects, which are basically simple beans with a few properties each. Each of the items (1570ish of them) have, perhaps, 3 or 4 child items each.

So, that's the data.

As I said, it's a simple Remote EJB. Make the call, it loads from the DB, and sends the List back.

The next scenario is rather than sending the List back, I return a byte array which is created with a writeObject of the resulting list to a ByteArrayOutputStream. Then I readObject in the WAR on subsequent ByteArrayInputStream. As I also mentioned, the size of the byte array is ~1.6MB.

For the third scenario, I create a new single method Session Bean and made it a WebService. Thats the only annotation I used -- @WebService along with @Stateless. The function calls the backend to fetch the data, iterates across it to break up the parent/child links (since a webservice can only send a tree of objects and not a graph), then return the tweaked list.

I then created a very simple web service client that's pretty much 100% wizard created from NetBeans. All I changed was adding simple time code and having it print the results size, instead of the result.

I deploy my projects, and restart the server.

Then I run my test.

For the web versions, I have a break point where the code checks for the cache (since that's what this code does, is load a cache). This allows me to easily reset the cache, and this happens before the big load. The web service client doesn't cache, so I just run it again.

I run the test twice, once after the fresh server restart, and then again. The first run times include any JPA caching or startup for the queries, and any other one time costs.

I monitor the memory using jconsole, and basically eyeball it based on the values it shows on the graph. I also force a GC from JConsole before each test.

I'm running:
Server 9.1_01 (build b06-fcs)
Java 5 on a Mac Pro running Mac OS 10.4

Run with normal EJB Remote
First Run: 25s 160MB surge
Second Run: 25s 240MB(!!) surge

Run with byte array EJB Remote
First Run: 7.1s 45MB surge
Second Run: 2.6s 48MB surge

Simple WebService
First Run: 7.6s 36MB surge
Second Run: 2.8s 8MB surge

So, those are the numbers I am seeing. I did not monitor CPU at all. I'm not paging.

For now, I'm sticking with my byte array version, as it has the least impact to my system. This change will let me lower the heap size on my production instance. The system normally puts along with a heap of around 90MB, but I have it set to 384MB because this call was (apparently) smashing in to a smaller heap of 256M.

I am, frankly, shocked (SHOCKED!) by these numbers. I am shocked at the time and memory impact of the Remote EJB, and I am AMAZED at the Webservice performance.

I'd LOVE to hear an explanation behind this.
[Message sent by forum member 'whartung' (whartung)]

http://forums.java.net/jive/thread.jspa?messageID=255708