對“盡量減少對變量的重復(fù)計算”中for循環(huán)長度計算的測試、分析字節(jié)碼

說下機器環(huán)境

system_info.png
  • 機器是win10系統(tǒng),4核處理器
  • java版本是:

java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

寫個用例測試

在一個main方法里啟動兩個線程循環(huán),然后計算時間

public static void main(String[] args) throws InterruptedException {

        int count = 500000000; // 數(shù)組大小

        int arr[] = new int[count];

        Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                long start = System.currentTimeMillis();
                for (int i = 0; i < arr.length; i++) {

                }
                System.out.println("直接計算長度-time1 = " + (System.currentTimeMillis() - start));

            }
        });

        Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {
                long start = System.currentTimeMillis();
                for (int i = 0, len = arr.length; i < len; i++) {

                }
                System.out.println("一次計算長度-time2 = " + (System.currentTimeMillis() - start));

            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();

    }

多次計算后可以看到的結(jié)果是:一次計算數(shù)組長度的時間均優(yōu)于直接計算數(shù)組長度的時間
即:time2<=time1
一次計算長度-time2 = 2
直接計算長度-time1 = 3

  • 由此簡單得出透揣,通過中間變量一次性計算循環(huán)長度優(yōu)于每次循環(huán)都去計算數(shù)組長度

在for循環(huán)中,為什么每次都要去計算數(shù)組長度川抡,編譯器不會優(yōu)化嗎?

因為時間差別并不是很大须尚,每次也就0~3毫秒的影響崖堤,是不是機器差別影響的呢?
前面列舉出機器cpu數(shù)量耐床,只啟動了兩個線程去運行密幔,幾乎是并行的,可以排除機器差別撩轰。

  • 還不放心胯甩,我們反編譯看一下編譯過程

javap字節(jié)碼分析

為了編譯過期盡量清晰昧廷,我們最簡化程序

  • 1.程序1-for中直接計算數(shù)組長度
package com.maxbin.swap;

public class For1 {

    public static void main(String[] args) {

        int arr[] = new int[1000000];

        for (int i = 0; i < arr.length; i++) {

        }

    }

}
  • 2.程序2-for中使用中間變量一次計算數(shù)組長度
package com.maxbin.swap;

public class For2 {

    public static void main(String[] args) {

        int arr[] = new int[1000000];

        for (int i = 0, len = arr.length; i < len; i++) {

        }

    }

}
  • javac 編譯源碼
javac -encoding utf-8 For1.java
javac -encoding utf-8 For2.java

目錄下會生成對應(yīng)的clss字節(jié)碼文件

  • javap 查看字節(jié)碼

  • 程序1-for中直接計算數(shù)組長度的字節(jié)碼

F:\tmp\clazz>javap -c For1.class
Compiled from "For1.java"
public class com.maxbin.swap.For1 {
  public com.maxbin.swap.For1();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // int 1000000
       2: newarray       int
       4: astore_1
       5: iconst_0
       6: istore_2
       7: iload_2
       8: aload_1
       9: arraylength
      10: if_icmpge     19
      13: iinc          2, 1
      16: goto          7
      19: return
}
  • 程序2-for中使用中間變量一次計算數(shù)組長度的字節(jié)碼
F:\tmp\clazz>javap -c For2.class
Compiled from "For2.java"
public class com.maxbin.swap.For2 {
  public com.maxbin.swap.For2();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // int 1000000
       2: newarray       int
       4: astore_1
       5: iconst_0
       6: istore_2
       7: aload_1
       8: arraylength
       9: istore_3
      10: iload_2
      11: iload_3
      12: if_icmpge     21
      15: iinc          2, 1
      18: goto          10
      21: return
}

字節(jié)碼是使用匯編語言,雖然程序2的匯編源碼長度長于程序1偎箫,但是往下看:

  • 程序1
    10行:if_icmpge(如果一個int類型值大于或者等于另外一個int類型值木柬,則跳轉(zhuǎn))判斷條件,成立則跳轉(zhuǎn)19行return淹办;否則往下走眉枕,看13行;
    13行:iinc(把一個常量值加到一個int類型的局部變量上邏輯運算)對應(yīng) i++ 操作怜森;
    16行:goto跳轉(zhuǎn)到第7行速挑;
    7行:從局部變量2中裝載int類型值;
    8行:從局部變量1中裝載引用類型值
    9行:獲取數(shù)組長度
    由此副硅,可以看出每一次循環(huán)中都會去獲取一次數(shù)組長度

  • 程序2

程序2直接看18行的goto語句姥宝,跳轉(zhuǎn)到10;
在第8行即獲取了數(shù)組長度恐疲,然后在10-18行的循環(huán)中并未出現(xiàn)“arraylength”指令獲取數(shù)組長度

  • 分析字節(jié)碼可以了解程序的具體執(zhí)行指令

javap生成的匯編語言指令表

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腊满,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子流纹,更是在濱河造成了極大的恐慌糜烹,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件漱凝,死亡現(xiàn)場離奇詭異疮蹦,居然都是意外死亡,警方通過查閱死者的電腦和手機茸炒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門愕乎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人壁公,你說我怎么就攤上這事感论。” “怎么了紊册?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵比肄,是天一觀的道長。 經(jīng)常有香客問我囊陡,道長芳绩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任撞反,我火速辦了婚禮妥色,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘遏片。我一直安慰自己嘹害,他們只是感情好撮竿,可當(dāng)我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著笔呀,像睡著了一般幢踏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凿可,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天惑折,我揣著相機與錄音,去河邊找鬼枯跑。 笑死惨驶,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的敛助。 我是一名探鬼主播粗卜,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼纳击!你這毒婦竟也來了续扔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤焕数,失蹤者是張志新(化名)和其女友劉穎纱昧,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體堡赔,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡识脆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了善已。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灼捂。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖换团,靈堂內(nèi)的尸體忽然破棺而出悉稠,到底是詐尸還是另有隱情,我是刑警寧澤艘包,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布的猛,位于F島的核電站,受9級特大地震影響想虎,放射性物質(zhì)發(fā)生泄漏衰絮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一磷醋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧胡诗,春花似錦邓线、人聲如沸淌友。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽震庭。三九已至,卻和暖如春你雌,著一層夾襖步出監(jiān)牢的瞬間器联,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工婿崭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拨拓,地道東北人。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓氓栈,卻偏偏與公主長得像渣磷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子授瘦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,452評論 2 348