Skip to main content

Poor Java2D scalability in server applications

1 reply [Last post]
aaime
Offline
Joined: 2003-06-10

Hi,
my name's Andrea and I'm working with the GeoTools/GeoServer
open source GIS projects.

In a number of Java open source GIS projects we heavily use
multithreaded rendering, be it because the application is
server side and producing images (maps) for a number of
client requests, or a desktop that is trying to leverage a
multicore architecture by drawing multiple map layers in
parallel.

Unfortunately due to
http://bugs.sun.com/view_bug.do?bug_id=6508591
the scalability obtained is poor.

I found a thread here on the forum suggesting to try super-sampled non antialiased rendering and then reduction via bilinear interpolation, but the quality of the output is bad, especially for map labels.

I also tried out OpenJDK, and whilst the Pisces renderer does not suffer the same scalablility issues, it's simply too slow compared to Ductus, so much that it takes tens of threads to make it become faster than Ductus (nice for heavy loads, but way not interesting for the low/medium ones where it's something like 4 times slower.)

I got the Sun JDK sources and looking into the Ductus rasterization code I have the
impression the Rasterizer and the alpha tile are considered
expensive to create and the code tries to make sure there is
at least one cached of each for the whole VM.
However, if that one is busy, new ones will be created, which results in a ton of them being created and released during typical multithreaded server side load, making the whole point of having the synchronization on the get and destroy methods a little weak. I guess the design only took into account the typical single threaded usage performed by Swing?

By the looks of it both the alpha tile and the rasterizer
could be cached per thread instead of per vm by using a
thread local storage of the both of them.
The code modifications would be quite localized, each thread
would keep on having its own cache, but separate threads
could work in parallel without the need for synchronizing
each other.

I would like to try it out. Given this would be a Sun JDK specific patch (I need the Ductus
renderer performance) I would not be able to go through OpenJDK.

As I said, I've downloaded the JDK 7 snapshot (actually, many of them during the last months).
I tried to build them, on Ubuntu Linux 32 and 64 bit and Fedora 10 32 bit, but I always stumble in the same compile error (whilst I can build OpenJDK just fine):

----------------------------------------------------------------------------------

../../../src/share/classes/java/security/Signature.java:39:
package javax.crypto does not exist
import javax.crypto.Cipher;
^
../../../src/share/classes/java/security/Signature.java:40:
package javax.crypto does not exist
import javax.crypto.CipherSpi;
^
../../../src/share/classes/java/security/Signature.java:41:
package javax.crypto does not exist
import javax.crypto.IllegalBlockSizeException;
^
../../../src/share/classes/java/security/Signature.java:42:
package javax.crypto does not exist
import javax.crypto.BadPaddingException;
^
../../../src/share/classes/java/security/Signature.java:43:
package javax.crypto does not exist
import javax.crypto.NoSuchPaddingException;
^
../../../src/share/classes/java/security/Signature.java:1194: cannot
find symbol
private final Cipher cipher;
^
symbol: class Cipher
location: class CipherAdapter
../../../src/share/classes/java/security/Signature.java:1198: cannot
find symbol
CipherAdapter(Cipher cipher) {
^
symbol: class Cipher
location: class CipherAdapter
../../../src/share/classes/java/security/KeyStore.java:33:
package javax.crypto does not exist
import javax.crypto.SecretKey;
^
../../../src/share/classes/java/security/KeyStoreSpi.java:35: package
javax.crypto does not exist
import javax.crypto.SecretKey;
^
../../../src/share/classes/java/security/KeyStore.java:475:
cannot find symbol
private final SecretKey sKey;
^
symbol: class SecretKey
location: class SecretKeyEntry
../../../src/share/classes/java/security/KeyStore.java:486:
cannot find symbol
public SecretKeyEntry(SecretKey secretKey) {
^
symbol: class SecretKey
location: class SecretKeyEntry
../../../src/share/classes/java/security/KeyStore.java:498:
cannot find symbol
public SecretKey getSecretKey() {
^
symbol: class SecretKey
location: class SecretKeyEntry
../../../src/share/classes/java/security/KeyRep.java:34:
package javax.crypto does not exist
import javax.crypto.SecretKeyFactory;
^
../../../src/share/classes/java/security/KeyRep.java:35:
package javax.crypto.spec does not exist
import javax.crypto.spec.SecretKeySpec;
^
../../../src/share/classes/java/security/Signature.java:401:
cannot find symbol
Cipher c = Cipher.getInstance(RSA_CIPHER, p);
^
symbol: class Cipher
location: class Signature
../../../src/share/classes/java/security/Signature.java:401:
cannot find symbol
Cipher c = Cipher.getInstance(RSA_CIPHER, p);
^
symbol: variable Cipher
location: class Signature
../../../src/share/classes/java/security/Signature.java:950:
cannot find symbol
Cipher c =
Cipher.getInstance(RSA_CIPHER, s.getProvider());
^
symbol: class Cipher
location: class Delegate
../../../src/share/classes/java/security/Signature.java:950:
cannot find symbol
Cipher c =
Cipher.getInstance(RSA_CIPHER, s.getProvider());
^
symbol: variable Cipher
location: class Delegate
../../../src/share/classes/java/security/Signature.java:952:
cannot find symbol
} catch (NoSuchPaddingException e) {
^
symbol: class NoSuchPaddingException
location: class Delegate
../../../src/share/classes/java/security/Signature.java:1204: cannot
find symbol
cipher.init(Cipher.DECRYPT_MODE, publicKey);
^
symbol: variable Cipher
location: class CipherAdapter
../../../src/share/classes/java/security/Signature.java:1214: cannot
find symbol
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
^
symbol: variable Cipher
location: class CipherAdapter
../../../src/share/classes/java/security/Signature.java:1220: cannot
find symbol
cipher.init(Cipher.ENCRYPT_MODE, privateKey,
random);
^
symbol: variable Cipher
location: class CipherAdapter
../../../src/share/classes/java/security/Signature.java:1244: cannot
find symbol
} catch (IllegalBlockSizeException e) {
^
symbol: class IllegalBlockSizeException
location: class CipherAdapter
../../../src/share/classes/java/security/Signature.java:1246: cannot
find symbol
} catch (BadPaddingException e) {
^
symbol: class BadPaddingException
location: class CipherAdapter
../../../src/share/classes/java/security/Signature.java:1258: cannot
find symbol
} catch (BadPaddingException e) {
^
symbol: class BadPaddingException
location: class CipherAdapter
../../../src/share/classes/java/security/Signature.java:1262: cannot
find symbol
} catch (IllegalBlockSizeException e) {
^
symbol: class IllegalBlockSizeException
location: class CipherAdapter
../../../src/share/classes/java/security/KeyStoreSpi.java:477:
cannot find symbol
} else if (key instanceof SecretKey) {
^
symbol: class SecretKey
location: class KeyStoreSpi
../../../src/share/classes/java/security/KeyStoreSpi.java:478:
cannot find symbol
return new
KeyStore.SecretKeyEntry((SecretKey)key);
^
symbol: class SecretKey
location: class KeyStoreSpi
../../../src/share/classes/java/security/KeyRep.java:171:
cannot find symbol
return new SecretKeySpec(encoded, algorithm);
^

-----------------------------------------------------------

It seems the jca jars are not added in the classpath during the build, unfortunately my "make" skills are quite weak.

Can anyone:
- provide some feedback on the idea of caching the rasterizer/alpha tile per thread as opposed to per VM
- hint on why the build is failing? Is there anyone outside of Sun able to build the Sun JDK 7 from sources on a Linux box?

Thanks for the attention

Cheers
Andrea

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
linuxhippy
Offline
Joined: 2004-01-07

Hi,

I am working on an Ductus replacement based on Cairo.
If you're interested in trying it out, I would be glad to hear your thoughts: http://linuxhippy.blogspot.com/2010/04/prebuilt-jre-image-available.html

PS: Single-Threaded performance is expected to be somewhat slower than Ductus, however it should scale quite well.
I have to admit however, its not ready for production use and I haven't done extensive multi-threaded testing.

Thanks, Clemens