Wei*_*Liu 13 java performance exception try-catch
我使用以下代码来测试try块的速度有多慢.令我惊讶的是,try块使它更快.为什么?
public class Test {
int value;
public int getValue() {
return value;
}
public void reset() {
value = 0;
}
// Calculates without exception
public void method1(int i) {
value = ((value + i) / i) << 1;
// Will never be true
if ((i & 0xFFFFFFF) == 1000000000) {
System.out.println("You'll never see this!");
}
}
public static void main(String[] args) {
int i;
long l;
Test t = new Test();
l = System.currentTimeMillis();
t.reset();
for (i = 1; i < 100000000; i++) {
t.method1(i);
}
l = System.currentTimeMillis() - l;
System.out.println("method1 took " + l + " ms, result was "
+ t.getValue());
// using a try block
l = System.currentTimeMillis();
t.reset();
for (i = 1; i < 100000000; i++) {
try {
t.method1(i);
} catch (Exception e) {
}
}
l = System.currentTimeMillis() - l;
System.out.println("method1 with try block took " + l + " ms, result was "
+ t.getValue());
}
}
Run Code Online (Sandbox Code Playgroud)
我的机器运行的是64位Windows 7和64位JDK7.我得到了以下结果:
method1 took 914 ms, result was 2
method1 with try block took 789 ms, result was 2
Run Code Online (Sandbox Code Playgroud)
我已经多次运行代码,每次得到几乎相同的结果.
更新:
以下是在MacBook Pro,Java 6上运行测试十次的结果.Tre-catch使得该方法更快,与在Windows上相同.
method1 took 895 ms, result was 2
method1 with try block took 783 ms, result was 2
--------------------------------------------------
method1 took 943 ms, result was 2
method1 with try block took 803 ms, result was 2
--------------------------------------------------
method1 took 867 ms, result was 2
method1 with try block took 745 ms, result was 2
--------------------------------------------------
method1 took 856 ms, result was 2
method1 with try block took 744 ms, result was 2
--------------------------------------------------
method1 took 862 ms, result was 2
method1 with try block took 744 ms, result was 2
--------------------------------------------------
method1 took 859 ms, result was 2
method1 with try block took 765 ms, result was 2
--------------------------------------------------
method1 took 937 ms, result was 2
method1 with try block took 767 ms, result was 2
--------------------------------------------------
method1 took 861 ms, result was 2
method1 with try block took 744 ms, result was 2
--------------------------------------------------
method1 took 858 ms, result was 2
method1 with try block took 744 ms, result was 2
--------------------------------------------------
method1 took 858 ms, result was 2
method1 with try block took 749 ms, result was 2
Run Code Online (Sandbox Code Playgroud)
Pet*_*rey 19
当您在同一方法中有多个长时间运行循环时,可以在第二个循环上触发整个方法的优化,并产生不可预测的结果.避免这种情况的一种方法是:
你会看到一些变化,有时结果是不确定的.即变异高于差异.
public class Test {
int value;
public int getValue() {
return value;
}
public void reset() {
value = 0;
}
// Calculates without exception
public void method1(int i) {
value = ((value + i) / i) << 1;
// Will never be true
if ((i & 0xFFFFFFF) == 1000000000) {
System.out.println("You'll never see this!");
}
}
public static void main(String[] args) {
Test t = new Test();
for (int i = 0; i < 5; i++) {
testWithTryCatch(t);
testWithoutTryCatch(t);
}
}
private static void testWithoutTryCatch(Test t) {
t.reset();
long l = System.currentTimeMillis();
for (int j = 0; j < 10; j++)
for (int i = 1; i <= 100000000; i++)
t.method1(i);
l = System.currentTimeMillis() - l;
System.out.println("without try/catch method1 took " + l + " ms, result was " + t.getValue());
}
private static void testWithTryCatch(Test t) {
t.reset();
long l = System.currentTimeMillis();
for (int j = 0; j < 10; j++)
for (int i = 1; i <= 100000000; i++)
try {
t.method1(i);
} catch (Exception ignored) {
}
l = System.currentTimeMillis() - l;
System.out.println("with try/catch method1 took " + l + " ms, result was " + t.getValue());
}
}
Run Code Online (Sandbox Code Playgroud)
版画
with try/catch method1 took 9723 ms, result was 2
without try/catch method1 took 9456 ms, result was 2
with try/catch method1 took 9672 ms, result was 2
without try/catch method1 took 9476 ms, result was 2
with try/catch method1 took 8375 ms, result was 2
without try/catch method1 took 8233 ms, result was 2
with try/catch method1 took 8337 ms, result was 2
without try/catch method1 took 8227 ms, result was 2
with try/catch method1 took 8163 ms, result was 2
without try/catch method1 took 8565 ms, result was 2
Run Code Online (Sandbox Code Playgroud)
从这些结果来看,似乎使用try/catch稍微慢一些,但并非总是如此.
在带有Java 7更新7的Windows 7,Xeon E5450上运行.
我用Caliper Microbenchmark试了一下,我真的看不出有什么区别.
这是代码:
public class TryCatchBenchmark extends SimpleBenchmark {
private int value;
public void setUp() {
value = 0;
}
// Calculates without exception
public void method1(int i) {
value = ((value + i) / i) << 1;
// Will never be true
if ((i & 0xFFFFFFF) == 1000000000) {
System.out.println("You'll never see this!");
}
}
public void timeWithoutTryCatch(int reps) {
for (int i = 1; i < reps; i++) {
this.method1(i);
}
}
public void timeWithTryCatch(int reps) {
for (int i = 1; i < reps; i++) {
try {
this.method1(i);
} catch (Exception ignore) {
}
}
}
public static void main(String[] args) {
new Runner().run(TryCatchBenchmark.class.getName());
}
}
Run Code Online (Sandbox Code Playgroud)
这是结果:
0% Scenario{vm=java, trial=0, benchmark=WithoutTryCatch} 8,23 ns; ?=0,03 ns @ 3 trials 50% Scenario{vm=java, trial=0, benchmark=WithTryCatch} 8,13 ns; ?=0,03 ns @ 3 trials benchmark ns linear runtime WithoutTryCatch 8,23 ============================== WithTryCatch 8,13 =============================
如果我交换函数的顺序(让它们以相反的顺序运行),结果是:
0% Scenario{vm=java, trial=0, benchmark=WithTryCatch} 8,21 ns; ?=0,05 ns @ 3 trials 50% Scenario{vm=java, trial=0, benchmark=WithoutTryCatch} 8,14 ns; ?=0,03 ns @ 3 trials benchmark ns linear runtime WithTryCatch 8,21 ============================== WithoutTryCatch 8,14 =============================
我会说它们基本相同.
我做了一些实验。
首先,我完全证实了OP的发现。即使删除第一个循环,或将异常更改为一些完全不相关的异常,只要不通过重新抛出异常来添加分支,try catch 确实会使代码更快。如果代码确实必须捕获异常(例如,如果使循环从 0 而不是 1 开始),那么代码仍然会更快。
我的“解释”是,JIT 是疯狂的优化机器,有时它们的性能比其他时候更好,如果没有在 JIT 级别进行非常具体的研究,您通常无法理解。有许多可能的事情可以改变(例如寄存器的使用)。
这是在全球范围内与 C# JIT 非常相似的情况中发现的情况。
无论如何,Java 针对 try-catch 进行了优化。由于总是存在出现异常的可能性,因此您实际上并没有通过添加 try-catch 来添加太多分支,因此发现第二个循环比第一个循环长也就不足为奇了。
归档时间: |
|
查看次数: |
1039 次 |
最近记录: |