繁体   English   中英

额外的'if checks'如果已经设置了值 - 什么更快,什么使用更多资源?

[英]Additional 'if checks' if the value is already set up - what is faster, what uses more resources?

假设我们有一个给定的接口:

public interface StateKeeper {

    public abstract void negateWithoutCheck();

    public abstract void negateWithCheck();

}

以及以下实现:

class StateKeeperForPrimitives implements StateKeeper {
    private boolean b = true;

    public void negateWithCheck() {
        if (b == true) {
            this.b = false;
        }
    }

    public void negateWithoutCheck() {
        this.b = false;
    }
}

class StateKeeperForObjects implements StateKeeper {
    private Boolean b = true;

    @Override
    public void negateWithCheck() {
        if (b == true) {
            this.b = false;
        }
    }

    @Override
    public void negateWithoutCheck() {
        this.b = false;
    }
}

此外,假设方法negate*Check()可以被多次调用1次,很难说调用次数的上限是多少。

  • 问题是根据执行速度,垃圾收集,内存分配等,两种实现中的哪种方法“更好” - negateWithChecknegateWithoutCheck

  • 答案取决于我们使用的两个提议的实现中的哪个或无关紧要?

  • 答案取决于估计的通话次数吗? 对于使用一种一种方法更好的数量?

通常,如果需要设置某个状态,只需设置状态即可。 另一方面,如果你需要做更多的事情 - 比如记录变更,告知变更等等 - 那么你应该首先检查旧值。

但是,在非常强烈地调用您提供的方法之类的方法的情况下,检查与非检查的性能可能有所不同(新值是否有所不同)。 可能的结果是:

1-a)检查返回false
1-b)检查返回true,分配值
2)没有检查就分配了价值

据我所知,写入总是慢于读取(一直到注册级别),因此最快的结果是1-a。 如果您的情况是最常见的情况是该值不会被更改(“超过50%”的逻辑就不够好,必须凭经验确定确切的百分比)-那么您应该检查一下,因为这消除了多余的写入操作(值分配)。 另一方面,如果价值不同于经常的不同 - 分配它而不检查。

您应该测试具体案例,进行一些分析,然后根据结果确定最佳实施。 在这种情况下,没有通用的“最佳方法”(除了“仅设置状态”之外)。

至于这里的布尔值与布尔值,我会(不屑一顾)说应该没有性能差异。

简答:无检查总是会更快。

与比较相比,分配花费的计算时间少得多。 因此:IF语句总是比赋值慢。

comparing 2个变量时,CPU将获取第一个变量,获取第二个变量,比较这些变量并将结果存储到临时寄存器中。 那是2 fetch 1 store es, 1 compare1 store

assign值时,CPU将获取'='右侧的值并将其存储到内存中。 那是1 fetch1 store

使用支票时可能会有轻微的性能优势。 我非常怀疑这对任何现实生活中的应用都至关重要。

过早优化是万恶之源(Donald Knuth)


你可以测量两者之间的差异。 让我强调一点, 这类事情难以可靠地衡量。

这是一种简单的方法。 如果检查发现不必更改该值,则可以期望获得性能上的好处,从而节省了写入内存的昂贵开销。 所以我相应地更改了你的代码。

interface StateKeeper {

    public abstract void negateWithoutCheck();

    public abstract void negateWithCheck();

}

class StateKeeperForPrimitives implements StateKeeper {

    private boolean b = true;

    public void negateWithCheck() {
        if (b == false) {
            this.b = true;
        }
    }

    public void negateWithoutCheck() {
        this.b = true;
    }
}

class StateKeeperForObjects implements StateKeeper {

    private Boolean b = true;

    public void negateWithCheck() {
        if (b == false) {
            this.b = true;
        }
    }

    public void negateWithoutCheck() {
        this.b = true;
    }
}

public class Main {

    public static void main(String args[]) {

        StateKeeper[] array = new StateKeeper[10_000_000];

        for (int i=0; i<array.length; ++i)
            //array[i] = new StateKeeperForObjects();
            array[i] = new StateKeeperForPrimitives(); 

        long start = System.nanoTime();

        for (StateKeeper e : array)
            e.negateWithCheck();
            //e.negateWithoutCheck();

        long end = System.nanoTime();

        System.err.println("Time in milliseconds: "+((end-start)/1000000));
    }
}

我得到以下内容:

           check  no check
primitive   17ms    24ms
Object      21ms    24ms

当检查总是多余的时候,我没有发现检查任何性能损失,因为总是需要更改该值。

两件事:(1)这些时间不可靠。 (2)此基准远非任何实际应用; 我不得不制作一个包含1000万个元素的数组来实际看到的东西。

我只是选择没有检查的功能。 我高度怀疑在任何实际应用程序中,具有该检查功能的功能是否会获得任何可衡量的性能优势,但是该检查易于出错并且更难阅读。

直到今天,我才看到很少的答案和评论重复这一点

过早优化是万恶之源

好吧,显然, if多说几句是一件要做的事,但是...这并不重要。

垃圾收集和内存分配......这里不是问题。

  1. 我通常会认为negateWithCheck稍微慢一点,因为总是有比较。 另请注意,在StateKeeperOfObjects中,您正在引入一些自动装箱。 “ true”和“ false”是原始布尔值。

  2. 假设您修复了StateKeeperOfObjects以使用所有对象,则可能,但是很可能不会引起注意。

  3. 速度将略微取决于呼叫的数量,但一般来说,无论您是呼叫一次还是多次,速度都应该被认为是相同的(忽略辅助效果,如缓存,jit等)。

在我看来,一个更好的问题是性能差异是否明显。 我正在研究一项涉及数百万并行数值计算的科学项目。 我们从使用对象(例如Integer,Double)开始,在内存和速度方面都没有令人满意的性能。 当我们将所有计算切换为基元(例如int,double)并查看代码以确保我们没有通过自动装箱引入任何时髦时,我们看到了巨大的性能提升(内存和速度)。

我非常喜欢避免过早优化,除非它是“简单”实现的东西。 只是要警惕后果。 例如,您是否必须在数据模型中表示空值? 如果是这样,您如何使用原语呢? 使用NaN可以轻松完成双打,但是布尔值呢?

negateWithoutCheck()是可取的,因为如果我们考虑调用次数,则negateWithoutCheck()仅具有一个调用,即this.b = false;。 其中negateWithCheck()与上一个有一个额外的区别。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM