From: Steve Wilson <###@###.###>
I found that with a few relatively
minor tweaks you can work around this issue in some cases. I've been
working with one large customer on this issue (with mostly positive results
so far). Here is what you need to try the work-around:
1. J2SE 1.3 (that has some Java2D and Swing fixes that are required)
2. Turn off double buffering in Swing. That means you need to add this
line of code to your app (before you create any Swing components):
3. Also, if you're using JScrollPane, you need to make the following
addition after you create any scrollpane:
This combination won't get performance quite as good as 1.1, but it's a
heck of a lot better than 1.2 or 1.2.2. FYI, you'll probably
want to put a switch in the code that only doesn't these tweaks if you tell
the app it is going to run remotely. These tweaks will hurt performance in
the local case.
This has to do with the way Java2D handles images. In the case described it will render the image on the server and then pipe the bits across. This is expensive. What you'd like it to do is pipe the drawing commands across, instead of the whole raw image. We're currently looking into ways to do this.
In JDK 1.2 we store the images on the JavaVM side of the connection whereas
they were stored on the Xserver side of the connection in JDK 1.1. As Steve
mentioned, the drawing commands for most applications take much less bandwidth
to transmit to the Xserver than the resulting image so generated.
We will need to develop better tools to better balance the tradeoff between
storing the pixels remotely in the server where the rendering is much more
restricted but the blitting is much faster and storing them on the local
side where we have much more control and flexibility for the rendering, but
where copying the pixels to the remote display is much slower.
As of 1.4 we will have a new Image type - the VolatileImage. This new
image type was created primarily to enable us to use win32 DDraw images
stored in VRAM which are not guaranteed to be stable. But, the relaxation
of the guarantees of image accessibility inherent in this new image type
also allows us to store the pixels for this new type of image inside the
X11 server for the remote case. Thus, applications using a VolatileImage
as their double buffer will see a very large speed increase in 1.4.
Swing is being modified to use the VolatileImage facility to allocate its
double buffers, and so Swing applications will run much faster over remote
X11 connections in 1.4.
Legacy applications which use createImage(w,h) to create their double buffer
images, though, will not see any of this benefit. We are looking into ways
to leverage the work done for the VolatileImage implementation to provide
similar benefits for remote use of createImage(w,h) images, but such work
is still speculative with no specific release targetted. Until then legacy
applications using createImage(w,h) for double buffering will continue to
experience 1.3 performance levels unless they are rewritten to use the
createVolatileImage method (available in 1.4) instead.
For the remote X11 display case we have enabled the regular offscreen
images (i.e. created via createImage(w,h)) to use the new pixmap surfaces
that we created for the VolatileImage case. This has led to tremendous
speedups for applications using this legacy double buffering interface.
Here are the results of some of the benchmarks I ran between 1.3 and 1.4.
Note that none of these tests are using any of the 2D rendering extensions
such as antialiasing or translucent colors. One of them fills a GeneralPath
but only with a solid color so it isn't any more complex than filling a
1.1-based Polygon object except for the presence of curves in the outline
data. Customers expecting decent Antialiasing and Alpha performance over
the network will not see any improvement until the X11 protocol and
implementations are extended to provide similar functionality.
Intended to model simple rendering (i.e. 1.1 applications) to a
back buffer and blitting it to the screen. Note that even though
a GeneralPath is a 2D feature, rendering it in solid non-AA mode
boils down to an operation similar to a Polygon fill.
Running BezierAnim with only the following options enabled:
Clear Background, Render Offscreen, Show Offscreen, Fill
And specifically the following options disabled (they would bypass
the X11 rendering pipelines):
No Antialias, No Alpha Fill Color
(Note: BezierAnim is a standalone, configurable version of the BezierAnim
pane of the Java2Demo.)
The results were:
1.3 < 3 fps
1.4 > 600 fps
For a 200x speedup.
Intended to measure simple blits of offscreen images to the screen.
Running DrawIMGPerf with options "offscr noscale ntests=3".
(Note: DrawIMGPerf is a configurable blit engine that can test the
performance of blitting various kinds of source images to various
kinds of destinations).
The results were:
237369 20x20 <Off-Screen> image pixels per second
268788 100x100 <Off-Screen> image pixels per second
251731 300x300 <Off-Screen> image pixels per second
4738230 20x20 <Off-Screen> image pixels per second
52882105 100x100 <Off-Screen> image pixels per second
94842452 300x300 <Off-Screen> image pixels per second
For a speedup of 20x, 197x, or 377x depending on the size of the
Since we have addressed both the Swing double buffering performance
and the performance of legacy (1.1-based) double buffering apps I
will be marking this bug fixed in Merlin-beta.