JDK-4835595 : PixelGrabber.grabPixels runs up to 600 times slower on JDK1.4.1 than on JDK1.3.1
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.4.1,1.4.2,5.0,5.0u3,5.0u6,6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS:
    linux,solaris,solaris_8,solaris_9,solaris_10 linux,solaris,solaris_8,solaris_9,solaris_10
  • CPU: generic,other,x86,sparc
  • Submitted: 2003-03-20
  • Updated: 2010-09-24
  • Resolved: 2008-06-09
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6
6u10 b26Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
Name: rmT116609			Date: 03/20/2003


FULL PRODUCT VERSION :
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)

versus

java version "1.3.1_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_03-b03)
Java HotSpot(TM) Client VM (build 1.3.1_03-b03, mixed mode)


FULL OS VERSION :
SunOS trust 5.8 Generic_108528-18 sun4u sparc SUNW,Sun-Blade-100

EXTRA RELEVANT SYSTEM CONFIGURATION :
24-bit color

A DESCRIPTION OF THE PROBLEM :
The sample program below takes about 93 seconds to execute the grabPixels() call under JDK 1.4.1 on a Solaris 8, Blade 100.  It takes 0.16 seconds
under JDK 1.3.1.  (For systems with 8-bit color, the time is about 0.1 seconds under both JDKs.)


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the code on a 24-bit color Blade 100, Solaris 8 under JDK1.4.1 and JDK1.3.1.  The output to standard out shows the times for the grabPixels call

EXPECTED VERSUS ACTUAL BEHAVIOR :
execution time of about 200 milliseconds in all cases
JDK 1.4.1 output is about 93000 milliseconds
JDK 1.3.1 output is about     160 millseconds

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;

public class Pixel implements ActionListener {

   private JButton b;
   private JFrame f;

   public Pixel () {
  
	    f = new JFrame("Copy Frame");
	    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    f.setSize(700,500);
	    Container cp = f.getContentPane();
	    JPanel p = new JPanel();
	    cp.add(p);
	    b = new JButton("Copy It");
	    b.addActionListener (this);
	    p.add(b);
	    f.setVisible( true);
   }

   public void actionPerformed (ActionEvent e) {

	if (e.getSource() == b) {
	    Dimension size = f.getSize();
	    Image im = f.createImage(size.width,size.height);
	    Graphics gr = im.getGraphics();
	    f.printAll(gr);

	    int [] pixels = new int[size.width*size.height];
	    PixelGrabber pg = new PixelGrabber (im, 0, 0,
			size.width, size.height, pixels, 0, size.width);
	    try {
	    	long start = System.currentTimeMillis();
		System.out.println("starting");
		pg.grabPixels();
		long end = System.currentTimeMillis();
		System.out.println("end after "+ (end-start) + " ms");
	    } catch (InterruptedException ie) {
		System.out.println("grab exception="+ie);
	    }
	}
   }

   public static void main (String[] args) {
	new Pixel();
   }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Replace

Image im = f.createImage(size.width,size.height);

with

BufferedImage im = new BufferedImage(size.width,size.height, BufferedImage.TYPE_INT_RGB);
(Review ID: 182843) 
======================================================================

Name: jk109818			Date: 07/23/2003


FULL PRODUCT VERSION :
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)

FULL OPERATING SYSTEM VERSION :
SunOS brooke 5.9 Generic_112233-01 sun4u sparc SUNW,Ultra-1

ADDITIONAL OPERATING SYSTEMS :
Linux gescher 2.4.19-PMC-SMP #3 SMP Mon Sep 9 22:33:11 CEST 2002 i686 unknown

A DESCRIPTION OF THE PROBLEM :
PixelGrabber + setenv DISPLAY slower in java 1.4

PixelGrabber is too slow in version 1.4 when I'm running a program in a remote machine but displaying the windows in my workstation

REGRESSION.  Last worked in version 1.3

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Log in on another machine; setenv DISPLAY to the machine you are
2. Run the given program (on the machine you've just logged in) with java 1.2/1.3 and 1.4.

EXPECTED VERSUS ACTUAL BEHAVIOR :
PixelGrabber should be so fast as in version 1.3.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
output, v.1.3.0:
Starting
9
output, v.1.4.1:
Starting
27074

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.image.*;

public class Foo {


    public static void main(String[] args) throws Exception {
        String s = "DonaudampfschifffahrtsgesellschaftskapitM-^O����n";
        Frame f = new Frame();
        f.setSize(300, 300);
        f.show();

        Thread.sleep(1500);

        Font font = f.getFont();
        FontMetrics fm = f.getFontMetrics(font);
        int h = fm.getMaxAscent() + fm.getMaxDescent() + 2;
        long sum = 0;

        for(int i = 0; i < 10; i++) {
            int w = fm.stringWidth(s) + 2;
            PixelGrabber pg = new PixelGrabber(f.createImage(w, h), 0, 0, w, h, new int[w*h], 0, w);

            long start = System.currentTimeMillis();
            pg.grabPixels();
            long end = System.currentTimeMillis();
            sum += end - start;
        }

        System.out.println(sum);
        System.exit(0);
    }

}



---------- END SOURCE ----------
(Review ID: 166897)
======================================================================

Comments
SUGGESTED FIX http://sa.sfbay.sun.com/projects/java2d_data/6u10/4835595.0
28-05-2008

EVALUATION We will do the work around for this release: do not put images created with createImage or createCompatibleImage into Pixmaps. Originally these images were created in Pixmaps to help applications which do double buffering using createImage - mostly Swing apps. Since then Swing's painting mechanism changed to use BufferStrategy or VolatileImage as back-buffer, so it is not as important to create these images in Pixmaps. Note that the managed images will continue to be cached in pixmaps.
23-05-2008

EVALUATION This bug is mostly addressed in JDK7, since with the fix for data buffer tracking we no longer put "component" images (those created with GC.createCompatibleImage and Component.createImage) into the pixmaps. We could do similar "fix" in some 6ux release.
29-06-2007

EVALUATION Image processing is generally handled by 2D. ###@###.### 2003-03-20 Can't reproduce this on my Solaris 7 box. Times with 1.4.2, 1.4.1, 1.4, 1.3.1 are all about .3 ms. ###@###.### 2003-03-20 I am able to reproduce this bug: 1. Ultra-5_10 witch M640 jdk1.4.1 332196 ms jdk1.5.0b02 296381 ms jdk1.3.1 306 ms 2. Ultra-5_10 withc Raptor GFX: jdk1.4.1 135474 ms jdk1.5.0b02 122419 ms jdk1.3.1 238 ms ###@###.### 2003-03-21 I am able to reproduce this on my system (Solaris 8, running through VNC) and see something like: jdk1.3.1 181 ms jdk1.5 16 seconds The key here is our use of pixmaps, starting in the 1.4 release. For example, if I run with pixmaps disabled (-Dsun.java2d.pmoffscreen=false), then I see something more like jdk1.5 243 ms While still slower than 1.3.1, this obviously represents much greater performance than with pixmaps enabled.... The different numbers above are probably due to running on configurations that do or do not have DGA enabled; when DGA is enabled, we use DGA instead of pixmaps (and thus the user would not see the problem there). Presumably, we are getting bottlenecked in per-pixel transactions through X asking for the pixel values, whereas we used to simply run through cached memory reading the pixel values (in 1.3.1, or in a DGA-enabled system). The fix would seem to be either doing block transfers of the pixels from pixmaps to avoid the per-pixel overhead, or possibly punting a pixmap image into a faster memory location when this type of read operation is detected. ###@###.### 2003-09-30 There are several reasons for the slowdown. The main is, of course, getting each pixel through X via XGetImage(1x1) request (DataBufferNative.getElem). Even though we notice the read operations and punt a Pixmap to a shared memory pixmap, it's still very slow. On a remote display it'd be even slower, since we won't be able to punt, and the pixels will have to get over the wire. So, on my system: jdk1.3.1 30ms jdk1.5 3418ms // 100x slowdown jdk1.5 J2D_PIXMAPS=server 23406ms // 800x slowdown: worst case, no punting (server pixmaps forced) jdk1.5 J2D_PIXMAPS=shared 625ms // 20x slowdown: by eliminating X overhead (forcing shared memory pixmaps) jdk1.5 return from native getElem 325ms // 10x slowdown: immediate return from native getElem, no X or JNI calls jdk1.5 return from java getElem 85ms // 3x slowdown: immediate return from DBN.getElem in java This means that we have 300ms in JNI-only overhead, which is the main concern of another bug (4740695), then we have ~50ms of what appears to be a new pipeline overhead. But we spend the most time dealing with X11. We can probably eliminate some of it with more aggressive punting strategy (punt to a shared memory pixmap earlier, or if we notice that there's a lot of single-pixel reads), but this still won't address the remote-X case, where we really want to have the pixels locally. Another approach is, as mentioned above, to attempt block transfers,and cache the pixels at native level (too much trouble to do it in java, say, CachingDataBufferNative class, since it'll be hard to to detect if the cache has been invalidated by other thread's writing to the image). Will need further investigation. ###@###.### 2003-11-10
10-11-2003