Performance 图纸与Swing中的SWT性能问题 为什么SWT比AWT绘制得慢?

Performance 图纸与Swing中的SWT性能问题 为什么SWT比AWT绘制得慢?,performance,swing,swt,Performance,Swing,Swt,全部, 这是一个经典的问题,但数字上的差异确实让我感到惊讶 附加了Swing和SWT的简单测试,随机字体绘制文本1000次 SWT(gc.advance off) 每绘制1000条文本约80毫秒 SWT(gc.advance on) 每绘制1000个文本约200毫秒 Swing(启用抗锯齿提示) 每绘制1000条文字约30毫秒 配置: Win7 Java 1.6_25 SWT org.eclipse.SWT.win32.win32.x86_3.7.1.v3738a.jar 谢谢大家 SWTT

全部,

这是一个经典的问题,但数字上的差异确实让我感到惊讶

附加了Swing和SWT的简单测试,随机字体绘制文本1000次

SWT(gc.advance off)

每绘制1000条文本约80毫秒

SWT(gc.advance on)

每绘制1000个文本约200毫秒

Swing(启用抗锯齿提示)

每绘制1000条文字约30毫秒

配置:

  • 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");
    }
}
}
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

}
}
import java.io.IOException;
导入org.eclipse.swt.swt;
导入org.eclipse.swt.graphics.Font;
导入org.eclipse.swt.graphics.FontData;
导入org.eclipse.swt.graphics.GC;
导入org.eclipse.swt.graphics.Rectangle;
导入org.eclipse.swt.widgets.Display;
导入org.eclipse.swt.widgets.Shell;
公共类SWTTest{
私有静态字体;
公共静态void main(字符串[]args)引发IOException{
显示=新显示();
外壳=新外壳(显示);
壳.立根(0,0,500,500);
shell.open();
字体=新字体(显示,新字体数据(“Tahoma”,int)(Math.random()*30),SWT.NORMAL));
addPaintListener(新的PaintListener(){
@凌驾
公共无效油漆控制(油漆事件e){
拉屎(e.gc);
}
});
而(!shell.isDisposed()){
如果(!display.readAndDispatch())
display.sleep();
}
font.dispose();
display.dispose();
System.in.read();
}
专用静态无效拉屎(外壳){
如果(!shell.isDisposed()){
GC=新GC(外壳);
矩形边界=shell.getBounds();
长启动=System.nanoTime();
对于(int i=0;i<1000;i++){
//在这里尝试各种不同的方法,例如绘制线条、矩形、缓存字体等。
//Font Font=新字体(gc.getDevice()、新FontData(“Tahoma”、(int)(Math.random()*30)、SWT.NORMAL));
gc.setFont(字体);
gc.drawText(“helloworld”,(int)(Math.random()*400),(int)(Math.random()*400));
font.dispose();
}
长时间停止=System.nanoTime();
gc.dispose();
System.out.println(“SWT时间:+(停止-启动)/1000000+“毫秒”);
}
}
}
AWTTest.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");
    }
}
}
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

}
}
导入java.awt.Color;
导入java.awt.Font;
导入java.awt.Frame;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.RenderingHints;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseListener;
导入java.awt.event.WindowEvent;
导入java.awt.event.WindowListener;
公共类AWTTest扩展框架实现MouseListener、WindowListener{
公共静态void main(字符串[]args){
新的AWTTest();
}
公共AWTTest(){
/*
*Label hello=新标签(“hello World”);添加(hello,“Center”);
*/
设置大小(500500);
setVisible(真);
addMouseListener(这个);
addWindowListener(此);
}
@凌驾
公共空间涂料(图g){
超级油漆(g);
Graphics2D g2d=(Graphics2D)g;
//SWT默认字体:
//[1 |塔荷马| 8.25 | 0 |窗户| 1 |-11 | 0 | 0 | 0 | 400 | 0 | 0 | 0 | 0 |塔荷马]
g2d.立根背景(颜色:灰色);
g2d.clearRect(0,0500500);
g2d.setRenderingHint(renderingHits.KEY\u TEXT\u ANTIALIAS,renderingHits.VALUE\u TEXT\u ANTIALIAS\u ON);
长启动=System.nanoTime();
对于(int i=0;i<1000;i++){
//在这里尝试各种不同的方法,例如绘制线条、矩形、缓存字体等。
setFont(新字体(“Tahoma”,Font.PLAIN,(int)(Math.random()*30));
g2d.drawString(“helloworld”,(int)(Math.random()*400),(int)(Math.random()*400));
}
长时间停止=System.nanoTime();
System.out.println(“AWT时间:+(停止-启动)/1000000+“毫秒”);
}
@凌驾
公共无效鼠标事件(鼠标事件e){
}
@凌驾
公共无效mouseClicked(MouseEvent e){
这个.paintAll(getGraphics());
}
@凌驾
公共无效mouseExited(MouseEvent e){
}
@凌驾
公共无效鼠标按下(MouseEvent e){
}
@凌驾
公共无效MouseEvent(MouseEvent e){
}
@凌驾
公共无效窗口已激活(WindowEvent e){
}
@凌驾
公共无效窗口关闭(WindowEvent e){
}
@凌驾
公共无效窗口关闭(WindowEvent e){
系统出口(0);
}
@凌驾
公共无效窗口已停用(WindowEvent e){
//TODO自动生成的方法存根
}
@凌驾
公共无效窗口取消确认(WindowEvent e){
//TODO自动生成的方法存根
}
@凌驾
公共无效窗口图标化(WindowEvent e){
//TODO自动生成的方法存根
}
@凌驾
公共无效窗口已打开(WindowEvent e){
//TODO自动生成的方法存根
}
}

正如phineas已经评论的那样,您的SWT代码不好

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

无论如何,在您的示例中,AWT文本只是抗锯齿的。SWT文本由带有的Windows绘制。如果禁用ClearType(在Windows设置中),则“SWT”的性能会大大提高(实际上是Windows的性能),即使您的基准测试存在phineas提到的问题

在另一个操作系统上运行基准测试将再次产生不同的结果

更新

我刚刚使用了你的代码,修复了当前版本明显的dispose bug,补充道

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

      @Override
      public void run() {
         drawshit(shell);
      }
   });
drawshit
的末尾,将字体大小设置为静态,因为它与性能非常相关。两个班我都用15号

启用ClearType时,SWTTest大约需要50毫秒,不启用ClearType时,每个iter大约需要17毫秒