Java 附加';如果检查';如果已经设置了值-什么更快,什么使用更多的资源?
假设我们有一个给定的接口:Java 附加';如果检查';如果已经设置了值-什么更快,什么使用更多的资源?,java,jvm,micro-optimization,premature-optimization,microbenchmark,Java,Jvm,Micro Optimization,Premature Optimization,Microbenchmark,假设我们有一个给定的接口: public interface StateKeeper { public abstract void negateWithoutCheck(); public abstract void negateWithCheck(); } 以及以下实现: class StateKeeperForPrimitives implements StateKeeper { private boolean b = true; public vo
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()
,很难说调用次数的上限是多少
- 问题是两种实现中哪种方法“更好”
根据执行速度、垃圾收集、内存分配等-
或negateWithCheck
negateWithoutCheck
- 答案是否取决于这两个建议中的哪一个 我们使用的实现还是无关紧要
- 答案是否取决于估计的呼叫数?使用one或first方法对数字的哪个计数更好
1-b)检查返回true,赋值
2) 未经检查就分配了值 据我所知,写作总是比阅读慢(一直到寄存器级别),所以最快的结果是1-a。如果您的情况是,最常见的情况是不会更改值(“超过50%”的逻辑不够好,必须根据经验计算出确切的百分比),那么您应该进行检查,因为这消除了冗余的写入操作(值分配)。另一方面,如果值与通常值的差异更大,则无需检查即可分配该值 您应该测试您的具体案例,进行一些分析,并根据结果确定最佳实现。对于这种情况,没有通用的“最佳方法”(除了“仅设置状态”)
至于布尔与布尔的比较,我会毫不犹豫地说,应该没有性能差异。直到今天,我才看到一些答案和评论重复这一点 过早优化是万恶之源 很明显,一个
如果语句更多是一件事要做,但是。。。这并不重要
以及垃圾收集和内存分配。。。这不是问题
我通常认为否定的检查要稍微慢一些,因为总是有比较。另外请注意,在StateKeeperOfObjects中,您引入了一些自动装箱true和false是基本布尔值
假设您修复了StateKeeperOfObjects以使用所有对象,那么可能是,但很可能不是显而易见的
速度将略微取决于调用的数量,但通常情况下,无论调用一次还是多次,速度都应被视为相同(忽略缓存、jit等辅助效果)
在我看来,更好的问题是性能差异是否明显。我在一个科学项目上工作,该项目涉及数百万并行的数值计算。我们开始使用对象(例如Integer、Double),但在内存和速度方面的性能都不理想。当我们将所有的计算转换为原语(例如int、double)并检查代码以确保我们没有通过自动装箱引入任何古怪的东西时,我们看到了巨大的性能提升(内存和速度)
我非常喜欢避免过早优化,除非它是“简单”实现的。只是要小心后果。例如,您是否必须在数据模型中表示空值?如果是这样,您如何使用原语来实现这一点?双打可以用楠轻松完成,但是Booleans呢? < P>NefAuthOutAuthCuffor()是最好的,因为如果我们考虑调用的次数,则否定项只有(一个)调用,也就是这个。其中as negateWithCheck()与前一个有一个额外的值。简短回答:没有检查的总是更快
与比较相比,赋值所需的计算时间要少得多。因此:IF语句总是比赋值慢
当比较两个变量时,CPU将获取第一个变量,获取第二个变量,比较这两个变量,并将结果存储到临时寄存器中。这就是2获取
es、1比较
和1存储
当您分配一个值时,您的CPU将获取“=”右侧的值并将其存储到内存中。这就是1fetch
和1store
使用带有检查的一个可能会有轻微的性能优势。我高度怀疑它在任何实际应用程序中是否重要
过早优化是万恶之源(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));
}
}
当检查总是多余的时候,我没有发现检查的任何性能损失,因为值总是需要更改的
两件事:(1)这些时间安排不可靠。(2) 这个基准远非任何实际应用程序;我必须制作一个包含1000万个元素的数组才能真正看到一些东西
我只会选择不需要检查的函数。我非常怀疑这一点
check no check
primitive 17ms 24ms
Object 21ms 24ms