United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 4835595 PixelGrabber.grabPixels runs up to 600 times slower on JDK1.4.1 than on JDK1.3.1
4835595 : PixelGrabber.grabPixels runs up to 600 times slower on JDK1.4.1 than on JDK1.3.1

Details
Type:
Bug
Submit Date:
2003-03-20
Status:
Closed
Updated Date:
2010-09-24
Project Name:
JDK
Resolved Date:
2008-06-09
Component:
client-libs
OS:
solaris_9,solaris,solaris_8,linux,solaris_10
Sub-Component:
2d
CPU:
x86,sparc,other,generic
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.4.1,1.4.2,5.0,5.0u3,5.0u6,6
Fixed Versions:
6u10

Related Reports
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Relates:
Relates:

Sub Tasks

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
                                     
2008-05-28
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.
                                     
2008-05-23
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.
                                     
2007-06-29
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
                                     
2003-11-10



Hardware and Software, Engineered to Work Together