Java Platform, Standard Edition Troubleshooting Guide
Contents    Previous    Next

12.1 Generic Performance Issues

This topic describes generic performance issues related to Java 2D hardware accelerated rendering primitives, how to detect primitive tracing and avoid non-accelerated rendering. There could be many causes for poor rendering performance. The following topics identify the cause for your applications poor rendering performance and suggests some approaches to improve performance of software-only rendering.

This topic contains the following subsections:

12.1.1 Hardware Accelerated Rendering Primitives

In order to better understand what could be causing performance problems, take a look at what hardware acceleration means.

In general, hardware accelerated rendering could be divided into two categories.

  • Hardware-accelerated rendering to an "accelerated" destination. Examples of rendering destinations which can be hardware-accelerated are VolatileImage, screen, and BufferStrategy. If a destination is accelerated, rendering which goes to such surface may be performed by video hardware. So if you issue a drawRect call, Java 2D redirects this call to the underlying native API (such as GDI, DirectDraw, Direct3D or OpenGL, or X11), which performs the operation using hardware.

  • Caching images in accelerated memory (Video memory or pixmaps) so that they can be copied very fast to another accelerated surface. Such images are known as "managed images."

Ideally, all operations performed to an accelerated surface are hardware-accelerated. In this case the application takes the full advantage that is offered by the platform.

Unfortunately in many cases the default pipelines are not able to use the hardware for rendering. This can happen due to the pipeline limitations, or the underlying native API. For example, most X servers do not support rendering antialiased primitives, or alpha compositing.

One cause of performance issues is when operations performed are not hardware-accelerated. Even in cases when a destination surface is accelerated, some primitives may not be.

It is important to know how to detect the cases when hardware acceleration is not being used. Knowing this may help in improving performance.

12.1.2 Primitive Tracing to Detect and Avoid Non-accelerated Rendering

To detect a non-accelerated rendering, you can use Java 2D primitive tracing.

Java 2D has built-in primitive tracing. See the description of the trace property at System Properties for Java 2D Technology.

Run your application with -Dsun.java2d.trace=count. When the application exits, a list of primitives and their counts is printed to the console.

Any time you see a MaskBlit or any of the General* primitives, it typically means that some of your rendering is going through software loops. Here is the output from performing drawImage on a translucent BufferedImage to a VolatileImage on Linux:

sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgb, SrcOverNoEa, "Integer BGR Pixmap")sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntBgr)

Here are some of the common non-accelerated primitives in the default pipelines, and their signatures in the tracing output. Note: Most of this tracing was taken on Linux; you may see some differences depending on your platform and configuration.

  • Translucent images (Images with ColorModel.getTranslucency() returns Translucency.TRANSLUCENT), or with AlphaCompositing. Sample primitive tracing output:

    sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgb,SrcOverNoEa, "Integer BGR Pixmap")sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntBgr)
    
  • Use of antialiasing (by setting the antialiasing hint). Sample primitive tracing output:

    sun.java2d.loops.MaskFill::MaskFill(AnyColor, Src, IntBgr)
    
  • Rendering antialiased text (setting the text antialising hint). Sample output can be one of the following:

    • sun.java2d.loops.DrawGlyphListAA::DrawGlyphListAA(OpaqueColor, SrcNoEa, AnyInt)
      
    • sun.java2d.loops.DrawGlyphListLCD::DrawGlyphListLCD(AnyColor, SrcNoEa, IntBgr)
      
  • Alpha compositing, either by rendering with translucent Color (a Color with alpha value which is not 0xff), or by setting a non-default AlphaCompositing mode with Graphics2D.setComposite():

    sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgb, SrcOver, IntRgb)sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntRgb)
    
  • Non-trivial transforms (if the transform is more than only translation). Rendering a transformed opaque image to a VolatileImage:

    sun.java2d.loops.TransformHelper::TransformHelper(IntBgr, SrcNoEa, IntArgbPre)
    
  • Rendering a rotated line:

    sun.java2d.loops.DrawPath::DrawPath(AnyColor, SrcNoEa, AnyInt)
    

Run your application with the tracing and make sure you do not use unaccelerated primitives unless they are needed.

12.1.3 Causes of Poor Rendering Performance

Some of the possible causes of poor rendering performance and possible alternatives are described as follows:

12.1.4 Improve Performance of Software-only Rendering

If your application relies on software-only rendering (by only rendering to a BufferedImage, or changing the default pipeline to an unaccelerated one), or even if it does mixed rendering, then the following are certain approaches to improving performance:

  1. Image types or operations with optimized support:

    Due to overall platform size constraints, Java 2D has a limited number of optimized routines for converting from one image format to another. In situations where an optimized direct loop can not be found, Java 2D will do the conversion through an intermediate image format (IntArgb). This results in performance degradation.

    Java 2D primitive tracing can be used for detecting such situations.

    For each drawImage call there will be two primitives: the first one converting the image from the source format to an intermediate IntArgb format and the second one converting from intermediate IntArgb to the destination format.

    Here are two ways to avoid such situations:

    • Use a different image format if possible.

    • Convert your image to an intermediate image of one of the better-supported formats, such as INT_RGB or INT_ARGB. In this way the conversion from the custom image format will happen only once instead of on every copy.

  2. Transparency vs translucency:

    Consider using 1-bit transparent (BITMASK) images for your sprites as opposed to images with full translucency (such as INT_ARGB) if possible.

    Processing images with full alpha is more CPU-intensive.

    You can get a 1-bit transparent image using a call to GraphicsConfiguration.createCompatibleImage(w,h, Transparency.BITMASK).

Contents    Previous    Next

Copyright © 1993, 2017, Oracle and/or its affiliates. All rights reserved.