gpt4 book ai didi

java - 使用日期和&&时的性能问题

转载 作者:行者123 更新时间:2023-11-30 04:12:09 26 4
gpt4 key购买 nike

在评估一些非常具体的 if 条件时,我遇到了一些非常奇怪的性能行为。

基本上我发现我可以构造两个条件 a 和 b 使得 if(a)if(a && b) 快 10 倍即使a总是 false,这似乎与 Java 应该对条件进行惰性求值的事实直接冲突。

当我有 a 时就会发生这种情况成为someDate.after(startdate)b成为someDate.before(enddate) - 即相当标准的范围条件。

下面我附上了用于显示此特定问题的代码。我已经在 Windows 7 上使用 Java 7 运行了代码,我的一位同事也在 Windows 7 上使用 java 6,7 和 8 运行了代码 - 都得到了相同的结果。

谁能解释一下为什么会发生这种情况?

import java.util.Date;

public class DateWeirdness {
public static void main(String[] args) {
Date start = new Date();
System.out.println("if(a) - a always false");
System.out.println(timeBasic(2000000000, start, start.getTime() - 4000000000L));
start = new Date();
System.out.println("if(a && b) - a always false, a and b both date method");
System.out.println(timeAdv(2000000000, start, start.getTime() - 4000000000L, new Date()));
start = new Date();
System.out.println("if(a && b) - a always false, b is condition on longs not date");
System.out.println(timeAdv2(2000000000, start, start.getTime() - 4000000000L, new Date().getTime()));
start = new Date();
System.out.println("if(a) - a always false - condition on long");
System.out.println(timeBasicL(2000000000, start.getTime(), start.getTime() - 4000000000L));
start = new Date();
System.out.println("if(a && b) - a always false, a and and b both conditions on long");
System.out.println(timeAdvL(2000000000, start.getTime(), start.getTime() - 4000000000L, new Date().getTime()));
start = new Date();
System.out.println("if(a && b) - a always false, b always true");
System.out.println(timeAdv(2000000000, start, start.getTime() - 4000000000L, new Date()));
start = new Date();
System.out.println("if(a && b) - both true");
System.out.println(timeAdv(2000000000, start, start.getTime() + 1, new Date(start.getTime() + 4000000000L)));
start = new Date();
System.out.println("if(a && b) - a always true, b always false");
System.out.println(timeAdv(2000000000, start, new Date(start.getTime() + 4000000001L).getTime(), new Date(start.getTime() + 4000000000L)));
}

private static int timeBasic(int size, Date start, long l) {
long begin = System.currentTimeMillis();
int c = 0;
for (int i = 0; i < size; i++) {
Date date = new Date(l++);
if (start.before(date)) {
c++;
}
}
System.out.println(System.currentTimeMillis() - begin);
return c;
}

private static int timeAdv(int size, Date start, long l, Date end) {
long begin = System.currentTimeMillis();
int c = 0;
for (int i = 0; i < size; i++) {
Date date = new Date(l++);
if (start.before(date) && end.after(date)) {
c++;
}
}
System.out.println(System.currentTimeMillis() - begin);
return c;
}

private static int timeAdv2(int size, Date start, long l, long end) {
long begin = System.currentTimeMillis();
int c = 0;
for (int i = 0; i < size; i++) {
Date date = new Date(l++);
if (start.before(date) && end > l) {
c++;
}
}
System.out.println(System.currentTimeMillis() - begin);
return c;
}

private static int timeBasicL(int size, long start, long l) {
long begin = System.currentTimeMillis();
int c = 0;
for (int i = 0; i < size; i++) {
l++;
if (start < l) {
c++;
}
}
System.out.println(System.currentTimeMillis() - begin);
return c;
}

private static int timeAdvL(int size, long start, long l, long end) {
long begin = System.currentTimeMillis();
int c = 0;
for (int i = 0; i < size; i++) {
l++;
if (start < l && end > l) {
c++;
}
}
System.out.println(System.currentTimeMillis() - begin);
return c;
}
}

在本地运行它时,我得到以下输出。有趣的测试是前三个测试。 640是以毫秒为单位执行 if(a) 的性能, 7079是做if(a && b)的表现,其中ab如上所述。 710是做if(a && b)的表现哪里bsomeDateAsLong < endDateAsLong .

if(a) - a always false
640
0
if(a && b) - a always false, a and b both date method
7079
0
if(a && b) - a always false, b is condition on longs not date
710
0
if(a) - a always false - condition on long
639
0
if(a && b) - a always false, a and and b both conditions on long
708
0
if(a && b) - a always false, b always true
6873
0
if(a && b) - both true
11995
2000000000
if(a && b) - a always true, b always false
13746
0

最佳答案

当您运行的代码没有做任何有用的事情时,您取决于 JIT 是否可以消除什么。在您的情况下,代码似乎正在被消除。

在快速情况下,每个循环需要 0.32 纳秒,这对于现实来说太短了。即大约一个时钟周期。较慢的情况是 3.6 ns,这更现实,但这可能意味着它只是大部分被优化掉了。

当您将行为从始终为假切换为始终为真(反之亦然)时,必须重新优化代码,并且您可能会计算检测到这一点并替换代码所需的时间,而不是实际执行所需的时间.

我建议您添加一个外循环来运行 main() 中的所有代码三次,您应该会看到更加显着的差异。

关于java - 使用日期和&&时的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19358515/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com