比如以下一段java代碼:
private void performTraversals() {
// cache mView since it is used so much below...
final View host = mView;
......
}
為什么要這么寫呢耀找?
下面用一段測試程序的bytecode來解釋一下(以下bytecode是基于JVM的它改,不是基于art的):
public class TestLocal {
private int i = 1;
public void foo() {
long before = System.currentTimeMillis();
for (int j = 0; j < 10000; j++) {
System.out.print(i);
}
System.out.println();
System.out.println("TestLocal result: " + (System.currentTimeMillis() - before));
}
public static void main(String[] args) {
new TestLocal().foo();
new TestLocal2().foo();
}
}
class TestLocal2 {
private int i = 1;
public void foo() {
int k = i;
long before = System.currentTimeMillis();
for (int j = 0; j < 10000; j++) {
System.out.print(k);
}
System.out.println();
System.out.println("TestLocal2 result: " + (System.currentTimeMillis() - before));
}
}
TestLocal
的foo
方法网沾,直接讀取類變量拙毫,對(duì)應(yīng)的字節(jié)碼是
13: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
16: aload_0
17: getfield #2 // Field i:I
20: invokevirtual #5 // Method java/io/PrintStream.print:(I)V
每次都需要將this push到operand stack中,然后去堆里找對(duì)應(yīng)的field拥坛。
而TestLocal2
的foo
方法,是將類變量的值存儲(chǔ)在當(dāng)前Frame的local variable中尘分。然后每次調(diào)用只要從local variable中取用猜惋。
0: aload_0
1: getfield #2 // Field i:I
4: istore_1
.......
20: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
23: iload_1
24: invokevirtual #5 // Method java/io/PrintStream.print:(I)V
運(yùn)行時(shí)間對(duì)比:
TestLocal result: 145 ms
TestLocal2 result: 128 ms
所以將類變量緩存到方法的local variable中還是能提升運(yùn)行速度的,尤其是如果類變量會(huì)被經(jīng)常訪問培愁。