绘图与Swing中的SWT性能问题

时间:2012-04-16 10:07:19

标签: performance swing swt

为什么SWT与AWT比较慢?

所有

一个经典的问题,但数字的不同让我感到惊讶。

在Swing和SWT中附加简单测试,使用随机字体绘制文本1000次。

SWT(gc.advance off)

每1000个文本绘制约80毫秒

SWT(gc.advance on)

每x 1000个文字

〜200ms

Swing(带有抗锯齿提示)

每1000个文本绘制

〜30ms

配置:

  • Win7
  • Java 1.6_25
  • SWT org.eclipse.swt.win32.win32.x86_3.7.1.v3738a.jar

谢谢大家。

SWTTest.java

import java.io.IOException;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class SWTTest {
    private static Font font;

public static void main(String[] args) throws IOException {

    Display display = new Display();
    Shell shell = new Shell(display);
    shell.setBounds(0, 0, 500, 500);
    shell.open();
            font = new Font(display, new FontData("Tahoma", (int) (Math.random() * 30), SWT.NORMAL));

    shell.addPaintListener(new PaintListener() {

        @Override
        public void paintControl(PaintEvent e) {
            drawshit(e.gc);
        }
    });

    while (!shell.isDisposed()) {
        if (!display.readAndDispatch())
            display.sleep();
    }

    font.dispose();
    display.dispose();

    System.in.read();
}

private static void drawshit(Shell shell) {

    if (!shell.isDisposed()) {
        GC gc = new GC(shell);
        Rectangle bounds = shell.getBounds();

        long start = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            // try various different things here, e.g. drawing lines, rectangles, cacheing fonts etc.
            // Font font = new Font(gc.getDevice(), new FontData("Tahoma", (int) (Math.random() * 30), SWT.NORMAL));
            gc.setFont(font);
            gc.drawText("Hello World", (int) (Math.random() * 400), (int) (Math.random() * 400));
            font.dispose();
        }
        long stop = System.nanoTime();

        gc.dispose();

        System.out.println("SWT time: " + (stop - start) / 1000000 + " ms");
    }
}
}

AWTTest.java

import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

public class AWTTest extends Frame implements MouseListener, WindowListener {

public static void main(String[] args) {
    new AWTTest();
}

public AWTTest() {
    /*
     * Label hello = new Label("Hello World"); add(hello, "Center");
     */
    setSize(500, 500);
    setVisible(true);

    addMouseListener(this);
    addWindowListener(this);
}

@Override
public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D) g;

    // SWT Default font:
    // [1|Tahoma|8.25|0|WINDOWS|1|-11|0|0|0|400|0|0|0|1|0|0|0|0|Tahoma]

    g2d.setBackground(Color.GRAY);
    g2d.clearRect(0, 0, 500, 500);
    g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

    long start = System.nanoTime();
    for (int i = 0; i < 1000; i++) {
        // try various different things here, e.g. drawing lines, rectangles, cacheing fonts etc.
        g2d.setFont(new Font("Tahoma", Font.PLAIN, (int) (Math.random() * 30)));
        g2d.drawString("Hello World", (int) (Math.random() * 400), (int) (Math.random() * 400));
    }
    long stop = System.nanoTime();

    System.out.println("AWT time: " + (stop - start) / 1000000 + " ms");

}

@Override
public void mouseEntered(MouseEvent e) {
}

@Override
public void mouseClicked(MouseEvent e) {
    this.paintAll(getGraphics());
}

@Override
public void mouseExited(MouseEvent e) {
}

@Override
public void mousePressed(MouseEvent e) {
}

@Override
public void mouseReleased(MouseEvent e) {
}

@Override
public void windowActivated(WindowEvent e) {
}

@Override
public void windowClosed(WindowEvent e) {
}

@Override
public void windowClosing(WindowEvent e) {
    System.exit(0);
}

@Override
public void windowDeactivated(WindowEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void windowDeiconified(WindowEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void windowIconified(WindowEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void windowOpened(WindowEvent e) {
    // TODO Auto-generated method stub

}
}

1 个答案:

答案 0 :(得分:1)

正如phineas已经评论过,你的SWT代码并不好。

但你也在比较两种截然不同的输出。 SWT通过设计本土绘制。操作系统负责绘图,这可能会产生与使用AWT绘图完全不同的结果。您是否希望您的应用程序与用户操作系统的其他应用程序保持一致取决于您。

无论如何,在你的例子中,AWT文本只是消除锯齿。 SWT文本由Windows ClearType绘制。如果你禁用ClearType(在Windows设置中),“SWT”的性能会大大加快(实际上它是Windows的性能),即使你的基准测试中提到了phineas的问题。

在另一个操作系统上运行基准测试将再次生成不同的数字。

<强>更新

我刚刚使用了你的代码,修复了当前版本的明显处置错误,添加了

   shell.getDisplay().asyncExec(new Runnable() {

      @Override
      public void run() {
         drawshit(shell);
      }
   });

drawshit的末尾,并使字体大小为静态,因为它与性能非常相关。我在两个班级都使用了15个大小。

启用ClearType SWTTest大约需要50毫秒,没有ClearType每次迭代大约需要17毫秒。我使用的是WinXP SP3。

AWTTest在3 ms到11 ms之间的值仍然更快。

所有这些只表明,ClearType使得文本绘制速度明显变慢。这不是SWT的错,而是因为底层操作系统而发生。在Mac上尝试使用该基准测试,您将获得完全不同的结果。