-2

なぜSWTはAWTと比較して非常にゆっくりと描画するのですか?

全て、

古典的な質問ですが、数字の違いには本当に驚いています。

SwingとSWTで簡単なテストを添付し、ランダムなフォントでテキストを1000回描画しました。

SWT(gc.advance off)

描画されるテキスト1000ごとに約80ms

SWT(gc.advance on)

描画されるテキスト1000ごとに約200ミリ秒

スイング(アンチエイリアシングのヒントがオンになっている)

描画されるテキスト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

}
}
4

1 に答える 1

1

フィニアスがすでにコメントしたように、あなたの SWT コードは良くありません。

しかし、2 つの非常に異なる出力も比較しています。SWT は設計上、ネイティブに描画します。OS が描画を担当するため、AWT での描画とは非常に異なる結果になる可能性があります。アプリケーションがユーザーの OS の他のアプリケーションと一貫性を保つことを好むかどうかは、あなた次第です。

とにかく、あなたの例では、AWT テキストは単にアンチエイリアス処理されています。SWT テキストは Windows によってClearTypeで描画されます。(Windows の設定で) ClearType を無効にすると、「SWT」のパフォーマンスは大幅に高速になります (実際には Windows のパフォーマンスです)。

別の OS でベンチマークを実行すると、再び異なる数値が生成されます。

更新

私はあなたのコードを使用し、現在のバージョンの明らかな廃棄バグを修正し、追加しました

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

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

の最後でdrawshit、フォント サイズを静的にしました。これは、パフォーマンスに非常に関連するためです。両方のクラスのサイズとして 15 を使用しました。

ClearType を有効にするSWTTestと約 50 ミリ秒かかり、ClearType を無効にすると反復ごとに約 17 ミリ秒かかります。WinXP SP3 を使用しています。

AWTTest3 ミリ秒から 11 ミリ秒の間の値では、さらに高速です。

これは、ClearType によってテキストの描画が劇的に遅くなることを示しているだけです。これは SWT のせいではありませんが、基盤となる OS が原因で発生します。そのベンチマークを Mac で試すと、まったく異なる結果が得られます。

于 2012-04-17T21:20:25.613 に答える