考虑以下两个代码示例:
示例1。
public void setValue(int value)
{
mValue = value;
}
示例2。
public void setValue(int value)
{
if (mValue != value)
{
mValue = value;
}
}
假装你的任务是将一些Java代码优化到绝对最大值,超越所有常识。
第二个代码示例是第一个的优化吗?我的意思是,在最低级别的Java或JVM中if条件检查和int赋值之间是否存在任何差异(无论多么微小)?
答案 0 :(得分:9)
第二种可能是反优化,因为在现代处理器上,分支往往很昂贵(主要是因为branch misprediction成本极高)。
确定的唯一方法是在代表性输入上分析您的代码。有关如何设置有意义的微观基准的一些指示,请参阅How do I write a correct micro-benchmark in Java?。
请记住,如果相关代码不占整个CPU时间的很大一部分,那么全世界的所有优化都不会对应用程序的整体性能产生很大影响。
答案 1 :(得分:3)
NPE有很好的建议。我要添加的一条评论可能还取决于mValue
是否是易变的,以及您正在运行它的硬件。对于挥发性物质,写入可能比读取数倍贵。一些硬件(我相信许多移动设备,例如)易失性读取相当便宜,因此差异可能会下降。
答案 2 :(得分:1)
您可以尝试编译两者,然后使用java字节码反汇编程序来检查差异。 Wikipedia JVM instruction listings可能是一个很好的起点。
根据我对我使用过的编译器和虚拟机的理解,由于额外的比较操作,第二个代码片段可能会慢一点(。微小)。
如果您的JVM实现有一个优化器,它可能会将您的第一个代码示例减少到一个操作,而第二个代码段将需要至少一个或两个操作来考虑比较操作。
答案 3 :(得分:0)
良好的编码实践说:“在最后一刻之前延迟优化”
但代码测试说:
比较&设置不是更好。
// Test Code
public class CompareAndSet {
int mValue;
// 1
public void setValue1(int value) {
mValue = value;
}
// 2
public void setValue2(int value) {
if (mValue != value) {
mValue = value;
}
}
public static void main(String[] args) {
final int TOTAL = (int) 1e9;
long ts;
for (int j = 0; j < 3; j++) {
// 1
{
ts = System.currentTimeMillis();
CompareAndSet cs = new CompareAndSet();
for (int i = 0; i < TOTAL; i++) {
cs.setValue1(i);
}
System.out.println("TOTAL(1)=" + TOTAL + " "
+ (System.currentTimeMillis() - ts) + "ms");
}
// 2
{
ts = System.currentTimeMillis();
CompareAndSet cs = new CompareAndSet();
for (int i = 0; i < TOTAL; i++) {
cs.setValue2(i);
}
System.out.println("TOTAL(2)=" + TOTAL + " "
+ (System.currentTimeMillis() - ts) + "ms");
}
}
}
}