我需要大量优化一段java代码,以至于我想知道我是否应该在方法中使用局部变量,使用私有变量的单例或者使用所有静态变量的静态类。
注意:我从未读过这些变量,我在每次方法调用时重新初始化它们,因此不会从任何形式的内存中获取。
所以我根据自己的情况进行了一些测试,结果令我困惑:
public class Test {
private int singleton;
private static int staticc;
private static Test te;
public static void main(String[] args) {
te = new Test();
for (int i = 0; i < 10; i++)
t();
}
private static void t(){
long now = System.nanoTime();
for (int i = 0; i < 1; i++){
for (int j = 0; j < 1000000000; j++){
te.singleton();
}
}
System.out.println("singleton: " + (System.nanoTime() - now));
now = System.nanoTime();
for (int i = 0; i < 1; i++){
for (int j = 0; j < 1000000000; j++){
staticc();
}
}
System.out.println("static: " + (System.nanoTime() - now));
now = System.nanoTime();
for (int i = 0; i < 1; i++){
for (int j = 0; j < 1000000000; j++){
local();
}
}
System.out.println("local: " + (System.nanoTime() - now));
now = System.nanoTime();
for (int i = 0; i < 1; i++){
for (int j = 0; j < 1000000000; j++){
overhead();
}
}
System.out.println("overhead: " + (System.nanoTime() - now));
}
private void singleton(){
singleton = 1;
singleton += singleton;
}
private static void staticc(){
staticc = 1;
staticc += staticc;
}
private static void local(){
float local = 1;
local += local;
}
private static void overhead(){
return;
}
}
这给了我结果:
singleton: 24460647
static: 41413757
local: 2630802
overhead: 2488400
singleton: 30776796
static: 19671150
local: 5132
overhead: 5131
singleton: 19669867
static: 144606898
local: 5559
overhead: 5560
singleton: 19399175
static: 143904724
local: 855
overhead: 428
singleton: 18892001
static: 143648143
local: 427
overhead: 428
singleton: 19543287
static: 145828647
local: 855
overhead: 428
singleton: 19356838
static: 145032821
local: 855
overhead: 1711
singleton: 19559965
static: 143845710
local: 427
overhead: 428
singleton: 19744275
static: 145983878
local: 428
overhead: 855
singleton: 19622399
static: 145635357
local: 428
overhead: 427
局部变量最快,这里并不奇怪。程序的本地部分也在某个阶段进行了优化(因为它没有真正做任何事情),所以它完全被跳过。令我感到困惑的是,单身人士比静态访问快10倍。
我的问题是:单身人士确实比静态课程更快,或者只是因为我的情况导致测试误导?
关于Singleton:我改为代码。添加了这个类:
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private int sing = 0;
public static Singleton getInstance(){
return INSTANCE;
}
public void single(){
sing = 1;
sing += sing;
}
}
这正是我嵌入到原始类中的原因,但只是为了澄清而做了。这是一个单身人士,不是吗?
然后我在主类中更改了这段代码:
long now = System.nanoTime();
for (int i = 0; i < 1; i++){
for (int j = 0; j < 1000000000; j++){
Singleton.getInstance().single();
}
}
System.out.println("singleton: " + (System.nanoTime() - now));
我得到了相同的结果。
答案 0 :(得分:0)
嗯,在正常情况下,static
类将提供比Singleton
模式更好的性能,因为static
方法在编译时受限制。
此外,使用static
类可避免(潜在)虚拟函数调用的开销,并且无需在使用时获取类的instance
。
它不应该使太多的差异,所以我不建议在任何情况下避免任何一个使用方便和清晰。
关于您的程序:您似乎甚至没有实现Singleton设计模式,您只是在类Test
中创建了一个名为singleton的字段,并且每次都增加它。这不是单身人士(阅读this)。
答案 1 :(得分:0)
我的猜测是它与你正在运行的Java版本以及你的JIT如何优化loopunrolling(或者在这种情况下无法使用staticc)有更多关系。这里有关于循环展开的更多信息。 https://en.wikipedia.org/wiki/Loop_unrolling
因此,例如尝试摆脱一些开销。在这个例子中
now = System.nanoTime();
for (int i = 0; i < 1; i++){
for (int j = 0; j < 1000000000; j++){
staticc();
}
}
将其更改为...
now = System.nanoTime();
for (int i = 0; i < 1; i++){
for (int j = 0; j < 250000000; j++){
staticc();
staticc();
staticc();
staticc();
}
}
直接回答编译器出现问题的原因是一个完全不同的讨论,需要更好地查看JIT代码。
如果你的价值观与此相近,我会说这是“为什么”