与Java 6相比,Java 8的GUI性能较差 [英] Java 8 poor GUI performance compared to Java 6

查看:160
本文介绍了与Java 6相比,Java 8的GUI性能较差的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的Java 6中,代码按预期运行,但在Java 8中,它需要花费更多的时间。有趣的是,组件使用相同的方法 setEnable()来启用和禁用组件,但是禁用调用比启用调用花费的时间长得多,几乎是两倍。 Java 8中的禁用所花费的时间远远长于Java 1.6中的禁用时间。问题是为什么会发生这种情况?这是Java 8的性能问题吗?



以下是Java 6的结果:

  Sun Microsystems Inc. 1.6.0_45 
初始化GUI
GUI初始化时间为1105 ms
禁用
禁用687 ms
启用
在375 ms内启用

以下是Java 8的结果:

  Oracle Corporation 1.8.0_25 
初始化GUI
GUI初始化时间为604 ms
禁用
禁用6341 ms
启用
启用370 ms

代码:

  import java.awt.Component; 
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

公共类TestGUI扩展JFrame实现ActionListener {

private static final long serialVersionUID = 1L;

public TestGUI(){
initGUI();
}

public void actionPerformed(ActionEvent e){
String text;
if(e.getActionCommand()。equals(Enable-ALL)){
enableAll();
text =禁用全部;
}
else {
disableAll();
text =启用全部;
}
((JButton)e.getSource())。setText(text);
((JButton)e.getSource())。setEnabled(true);

}


private void initGUI(){
long m = System.currentTimeMillis();
System.out.println(初始化GUI);
setTitle(System.getProperty(java.vendor)++ System.getProperty(java.version));
setLayout(new FlowLayout());

JButton b = new JButton(Disable-ALL);
b.addActionListener(this);
add(b);

for(int i = 1; i< 10001; i ++){
b = new JButton(Button+ i);
add(b);
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600,600);
setVisible(true);
m = System.currentTimeMillis() - m;
System.out.println(GUI初始化为+ m +ms);
}

private void disableAll(){
long m = System.currentTimeMillis();
System.out.println(禁用);
for(组件c:getContentPane()。getComponents()){
c.setEnabled(false);
}

m = System.currentTimeMillis() - m;
System.out.println(禁用+ m +ms);
}

private void enableAll(){
long m = System.currentTimeMillis();
System.out.println(启用);
for(组件c:getContentPane()。getComponents()){
c.setEnabled(true);
invalidate();
}
m = System.currentTimeMillis() - m;
System.out.println(启用+ m +ms);
}

public static void main(String [] args){

EventQueue.invokeLater(new Runnable(){
public void run() {
System.out.println(System.getProperty(java.vendor)+
+ System.getProperty(java.version));
new TestGUI();
}
});
}
}


解决方案

根据对于我的分析器,操作大部分时间都花在方法 Thread.holdsLock 上,这可能确实是一个代价高昂的操作,由组件调用.checkTreeLock Component.updateCursorImmediately 间接调用。



一般来说,你可以通过在操作之前调用 getContentPane()。setVisible(false); 以及 getContentPane()来更新多个组件时,避免代价高昂的可视更新.setVisible(true ); 之后,例如

  private void disableAll(){
long m = System.currentTimeMillis的();
System.out.println(禁用);
getContentPane()。setVisible(false);
for(组件c:getContentPane()。getComponents()){
c.setEnabled(false);
}
getContentPane()。setVisible(true);

m = System.currentTimeMillis() - m;
System.out.println(禁用+ m +ms);
}

你会看到,无论哪种视觉更新,这些问题都会消失详细解决问题。



所以你不需要考虑如何在这里正确地进行基准测试,而不是在操作需要几秒钟时这很重要,但我建议学习 System.currentTimeMillis() System.nanoTime() ,因为后者是衡量经过时间的正确工具。 / p>

In Java 6 below code is running as expected but in Java 8 it is taking much more time. The interesting part is that components use the same method setEnable() for enabling and disabling components, but the disabling call takes much longer than the enabling one, almost twice as much. Disabling in Java 8 is taking much longer than the one in Java 1.6. The question is why does this happen? Is this a performance problem of Java 8?

Here are the results for Java 6:

    Sun Microsystems Inc. 1.6.0_45
    Initializing GUI
    GUI initialized in 1105 ms
    Disabling
    Disabled in 687 ms
    Enabling
    Enabled in 375 ms

Here are the results for Java 8:

    Oracle Corporation 1.8.0_25
    Initializing GUI
    GUI initialized in 604 ms
    Disabling
    Disabled in 6341 ms
    Enabling
    Enabled in 370 ms

The code:

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public class TestGUI extends JFrame implements ActionListener {

    private static final long serialVersionUID = 1L;

    public TestGUI() {
        initGUI();
    }

    public void actionPerformed(ActionEvent e) {
        String text;
        if(e.getActionCommand().equals("Enable-ALL")){
            enableAll();
            text= "Disable-ALL";
        }
        else{
            disableAll();
            text= "Enable-ALL";
        }
        ((JButton)e.getSource()).setText(text);
        ((JButton)e.getSource()).setEnabled(true);

    }


    private  void initGUI() {
        long m = System.currentTimeMillis();
        System.out.println("Initializing GUI");
        setTitle(System.getProperty("java.vendor") + " " + System.getProperty("java.version"));
        setLayout(new FlowLayout());

        JButton b = new JButton("Disable-ALL ");
        b.addActionListener(this);
        add(b);

        for (int i = 1; i < 10001; i++) {
            b = new JButton("Button " + i);
            add(b);
        }
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(600, 600);
        setVisible(true);
        m = System.currentTimeMillis() - m;
        System.out.println("GUI initialized in " + m + " ms");
    }

    private void disableAll() {
        long m = System.currentTimeMillis();
        System.out.println("Disabling");
        for (Component c : getContentPane().getComponents()) {
            c.setEnabled(false);
        }

        m = System.currentTimeMillis() - m;
        System.out.println("Disabled in " + m + " ms");
    }

    private void enableAll() {
        long m = System.currentTimeMillis();
        System.out.println("Enabling");
        for (Component c : getContentPane().getComponents()) {
            c.setEnabled(true);
            invalidate();
        }
        m = System.currentTimeMillis() - m;
        System.out.println("Enabled in " + m + " ms");
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                System.out.println(System.getProperty("java.vendor") + " "
                        + System.getProperty("java.version"));
                new TestGUI();
            }
        });
    }
}

解决方案

According to my profiler, the operation spends most of the time in the method Thread.holdsLock, which can be indeed a costly operation, which is called by Component.checkTreeLock which is called indirectly by Component.updateCursorImmediately.

Generally, you can avoid costly visual updates when updating multiple components by calling getContentPane().setVisible(false); right before the operation and getContentPane().setVisible(true); right afterwards, e.g.

private void disableAll() {
    long m = System.currentTimeMillis();
    System.out.println("Disabling");
    getContentPane().setVisible(false);
    for (Component c : getContentPane().getComponents()) {
        c.setEnabled(false);
    }
    getContentPane().setVisible(true);

    m = System.currentTimeMillis() - m;
    System.out.println("Disabled in " + m + " ms");
}

You will see, such problems will vanish, regardless of which kind of visual update causes the problem in detail.

So you don’t need to think about how to benchmark correctly here, not that it matters when the operation takes seconds, but I recommend learning the difference between System.currentTimeMillis() and System.nanoTime() as the latter is the right tool for measuring elapsed time.

这篇关于与Java 6相比,Java 8的GUI性能较差的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆