我刚刚写了一个关于我是如何达到这一点的完整的宣传,但是我认为发布代码并将其留在那里更容易:)
据我所知,test3()的性能应该与test1()相同-唯一的区别是在捕获异常的地方(在test1()的调用方法中,在test3()的调用方法中)
为什么test3()经常在test1()和test2()之间花费时间来完成?
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class Test {
public static void main(String[] args) {
warmup();
test1(2500000); // Exception caught inside the loop
test2(2500000); // Exception caught outside the loop
test3(2500000); // Exception caught "inside" the loop, but in the URLEncoder.encode() method
}
private static void warmup() {
// Let URLEncoder do whatever startup it needs before we hit it
String encoding = System.getProperty("file.encoding");
try {
URLEncoder.encode("ignore", encoding);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void test1(int count) {
String encoding = System.getProperty("file.encoding");
long start = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
try {
URLEncoder.encode("test 1 " + i, encoding);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("Performed " + count + " encodings trying to catch each in " + (end - start) + "ms");
}
private static void test2(int count) {
String encoding = System.getProperty("file.encoding");
long start = System.currentTimeMillis();
try {
for (int i = 0; i < count; i++) {
URLEncoder.encode("test 2" + i, encoding);
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("Performed " + count + " encodings trying to catch all in " + (end - start) + "ms");
}
private static void test3(int count) {
long start = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
URLEncoder.encode("test 3 " + i);
}
long end = System.currentTimeMillis();
System.out.println("Performed " + count + " encodings with a deprecated method in " + (end - start) + "ms");
}
}
运行它会给我(Windows XP上的JDK 1.6.0_)输出:
Performed 2500000 encodings trying to catch each in 4906ms
Performed 2500000 encodings trying to catch all in 2454ms
Performed 2500000 encodings with a deprecated method in 2953ms
所以,反应非常接近(我们说的是一些无关紧要的事情,这是不相关的),btu我很好奇!
后来…
有人建议说有一些JVM优化阻碍了这一点——我同意。所以,我将每个测试分解成它自己的类/主方法,并分别进行测试。结果如下:
1 - Performed 2500000 encodings trying to catch each in 5016ms
1 - Performed 5000000 encodings trying to catch each in 7547ms
1 - Performed 5000000 encodings trying to catch each in 7515ms
1 - Performed 5000000 encodings trying to catch each in 7531ms
2 - Performed 2500000 encodings trying to catch all in 4719ms
2 - Performed 5000000 encodings trying to catch all in 7250ms
2 - Performed 5000000 encodings trying to catch all in 7203ms
2 - Performed 5000000 encodings trying to catch all in 7250ms
3 - Performed 2500000 encodings with a deprecated method in 5297ms
3 - Performed 5000000 encodings with a deprecated method in 8015ms
3 - Performed 5000000 encodings with a deprecated method in 8063ms
3 - Performed 5000000 encodings with a deprecated method in 8219ms
有趣的观察:
-
在它自己的JVM中,捕捉每个调用与捕捉循环之外的所有内容之间的差距减小了(我假设在一种情况下,由于已经执行的其他迭代,优化不会在所有测试中全力以赴)
-
我这边的try/catch和urlencoder.encode()里面的try/catch之间的差距现在小得多(超过5000000次迭代的半秒),但仍然一致存在…