Skip to main content

Drawing 700.000 lines

6 replies [Last post]
jcmeira
Offline
Joined: 2003-08-02
Points: 0

I am drawing a map with over 700.000 polilines and polygons,
the painting time with jvm 1.5.0_03 is about 2200ms
and if I use the jvm 1.6.0-ea-b40 with -Dsun.java2d.d3d=true
the painting time is 2000ms, WHY ????...
....
with -Dsun.java2d.opengl=true is worse.

Only about 10% faster I think that is little

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
abies
Offline
Joined: 2003-06-10
Points: 0

Use GeneralPath to preconstruct your lines and paint in one big batch. If your data is static, leave the GP and reuse it later, if not, you can still use same GP to fill it with new data. Be sure to specify initial capacity to GP.

First try to do it with one big GP and check the performance improvement. Then, please try to do it in smaller batches - 16,32,64 lines per batch. I remember that few years ago, using one big batch was best for normal lines and 32-line batch was best for antialiased lines.

GP should probably give you 4-5 times speedup.

gbarton
Offline
Joined: 2003-07-08
Points: 0

I assume this same trick would work with filled rectangles? I'm working on an app that draws on the order of two million filled rectangles.

https://tilepile.dev.java.net/

The images are static, so I have a solution that draws them to VolitileImages and caches them, but this doesn't work on Apple's VM. (neither 1.4.2 nor 1.5.0) An odd out of memory error occurs when I try to create too many images. (Volitile of Buffered)

So I'd like to try the GeneralPath trick, if it would help.

jcmeira
Offline
Joined: 2003-08-02
Points: 0

I make last example but the paint time is better in offscreenbuffer

trembovetski
Offline
Joined: 2003-12-31
Points: 0

The reason you see pretty similar performance is that you're actually rendering to a BufferedImage, which is a system-memory based surface, so you're using the software loops.

If instead of using the repaint manager you just created a VolatileImage, you'd get much better results.

I've modified your test a little, but it still does pretty much the same thing.

[code]
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.VolatileImage;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToolBar;

class Java2DTest extends JFrame{
public Java2DTest() {
JToolBar jtb=new JToolBar();
JButton b=new JButton("RUN");
final Test test = new Test();
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
test.runtest();
}
});
jtb.add(b);
getContentPane().add(jtb,BorderLayout.NORTH);
getContentPane().add(test,BorderLayout.CENTER);
setSize(600,600);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}

}

public class Test extends JPanel {
int[] x,y;
int MAX=1300;

public Test() {
x=new int[MAX];
y=new int[MAX];
for(int i=0;i x[i]=(int)(Math.random()*500.0);
y[i]=(int)(Math.random()*500.0);
}
}

public void runtest(){
Toolkit.getDefaultToolkit().sync();
long ini=System.currentTimeMillis();
pintar();
Toolkit.getDefaultToolkit().sync();

paintImmediately(0, 0, getWidth(), getHeight());
long fin=System.currentTimeMillis();
System.out.println("Tiempo en realizar el test="+(fin-ini));
}

public void paintComponent(Graphics g) {
g.drawImage(img, 0, 0, null);
}

VolatileImage img;
public void pintar(){
if (img == null) {
img = createVolatileImage(getWidth(), getHeight());
}
img.validate(getGraphicsConfiguration());
/*
Image img=RepaintManager.currentManager(this).getOffscreenBuffer(this,getWidth(),getHeight());
*/
img.setAccelerationPriority(1f);
System.err.println("img:"+img);

Graphics2D g2d=(Graphics2D)img.getGraphics();
for(int i=0;i<1000;i++){
g2d.drawPolyline(x,y,MAX);
}
g2d.dispose();
}

public static void main(String[] args) {
Java2DTest testline = new Java2DTest();
testline.setVisible(true);
}
}
[/code]

There are better ways to write this, but I didn't have time..

Also, note that in some cases tests like this tend to flood the video board and you may get some funny results.

Thanks,
Dmitri
Java2D Team

jcmeira
Offline
Joined: 2003-08-02
Points: 0

The painting time in both is someone ....

public abstract class Java2DTest extends JFrame{
protected String nfile="TESTLINE2D.test";
protected JComponent canvas=new JPanel();
protected String nombreTest="NombreTest";
public Java2DTest(String nfile,String nt) {
this.nombreTest=nt;
this.nfile=nfile;
JToolBar jtb=new JToolBar();
JButton b=new JButton("RUN");
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
runtest();
}
});
jtb.add(b);
getContentPane().add(jtb,BorderLayout.NORTH);
canvas=new JPanel(){
public void paint(Graphics g){
super.paint(g);
long ini=System.currentTimeMillis();
pintar(g);
long fin=System.currentTimeMillis();
saveResultadosTest(fin-ini);
}
};
getContentPane().add(canvas,BorderLayout.CENTER);
setSize(600,600);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}

private void saveResultadosTest(long tiempo){
try{
java.io.FileWriter fw=new java.io.FileWriter(nfile,true);
String version=System.getProperty("java.vm.version");
String jhome=System.getProperty("java.home");
String comp=System.getProperty("java.compiler");
fw.write("\n");
fw.write(nombreTest+"\n");
fw.write("java.vm.version="+version+"\n");
fw.write("java.compiler="+comp);
fw.write("java.home="+jhome+"\n");
fw.write("Tiempo en realizar el test="+tiempo+"\n");
fw.write("\n");
fw.flush();
fw.close();
System.out.println("Tiempo en realizar el test="+tiempo+"\n");
}catch(IOException ioex){ioex.printStackTrace();}
}

public abstract void runtest();

public abstract void pintar(Graphics g);
}

public class TestOffScreenBuffer extends Java2DTest{
int[] x,y;
int MAX=1300;

public TestOffScreenBuffer(String f,String nt) {
super(f,nt);
x=new int[MAX];
y=new int[MAX];
for(int i=0;i x[i]=(int)(Math.random()*500.0);
y[i]=(int)(Math.random()*500.0);
}
}

public void runtest(){
this.canvas.repaint();
}

public void pintar(Graphics g){
g.setColor(Color.RED);
Image img=RepaintManager.currentManager(this).getOffscreenBuffer(this,getWidth(),getHeight());
img.setAccelerationPriority(1f);
Graphics2D g2d=(Graphics2D)img.getGraphics();
for(int i=0;i<1000;i++){
g2d.drawPolyline(x,y,MAX);
}
g2d.dispose();
g.drawImage(img,0,0,this);
//img.flush();
//img=null;
}

public static void main(String[] args) {
TestOffScreenBuffer testline = new TestOffScreenBuffer("java2dtest.logs",TestOffScreenBuffer.class.getName());
testline.setVisible(true);
}
}

neigor
Offline
Joined: 2005-06-16
Points: 0

I would suggest to file performance bug on this.
But please provide specific testcase to reproduce
this issue.