假如您頻繁存取變量,就需要考慮從何處存取這些變量。變量是 static 變量,還是堆棧變量,或者是類的實(shí)例變量?變量的存儲位置對存取它的代碼的性能有明顯的影響?例如,請考慮下面這段代碼:
class StackVars
{
PRivate int instVar;
private static int staticVar;
//存取堆棧變量
void stackaccess(int val)
{
int j=0;
for (int i=0; i<val; i++)
j += 1;
}
//存取類的實(shí)例變量
void instanceAccess(int val)
{
for (int i=0; i<val; i++)
instVar += 1;
}
//存取類的 static 變量
void staticAccess(int val)
{
for (int i=0; i<val; i++)
staticVar += 1;
}
}
這段代碼中的每個方法都執(zhí)行相同的循環(huán),并反復(fù)相同的次數(shù)。唯一的不同是每個循環(huán)使一個不同類型的變量遞增。方法 stackAccess 使一個局部堆棧變量遞增,instanceAccess 使類的一個實(shí)例變量遞增,而 staticAccess 使類的一個 static 變量遞增。
instanceAccess 和 staticAccess 的執(zhí)行時間基本相同。但是,stackAccess 要快兩到三倍。存取堆棧變量如此快是因?yàn)椋琂VM 存取堆棧變量比它存取 static 變量或類的實(shí)例變量執(zhí)行的操作少。請看一下為這三個方法生成的字節(jié)碼:
Method void stackAccess(int)
0 iconst_0 //將 0 壓入堆棧。
1 istore_2 //彈出 0 并將它存儲在局部分變量表中索引為 2 的位置 (j)。
2 iconst_0 //壓入 0。
3 istore_3 //彈出 0 并將它存儲在局部變量表中索引為 3 的位置 (i)。
4 goto 13 //跳至位置 13。
7 iinc 2 1 //將存儲在索引 2 處的 j 加 1。
10 iinc 3 1 //將存儲在索引 3 處的 i 加 1。
13 iload_3 //壓入索引 3 處的值 (i)。
14 iload_1 //壓入索引 1 處的值 (val)。
15 if_icmplt 7 //彈出 i 和 val。假如 i 小于 val,則跳至位置 7。
18 return //返回調(diào)用方法。
Method void instanceAccess(int)
0 iconst_0 //將 0 壓入堆棧。
1 istore_2 //彈出 0 并將它存儲在局部變量表中索引為 2 的位置 (i)。
2 goto 18 //跳至位置 18。
5 aload_0 //壓入索引 0 (this)。
6 dup //復(fù)制堆棧頂?shù)闹挡⑺鼔喝搿?BR> 7 getfield #19 <Field int instVar>
//彈出 this 對象引用并壓入 instVar 的值。
10 iconst_1 //壓入 1。
11 iadd //彈出棧頂?shù)膬蓚€值,并壓入它們的和。
12 putfield #19 <Field int instVar>
//彈出棧頂?shù)膬蓚€值并將和存儲在 instVar 中。
15 iinc 2 1 //將存儲在索引 2 處的 i 加 1。
新聞熱點(diǎn)
疑難解答
圖片精選