讀古今文學網 > Java程序員修煉之道 > 分佈式網絡計時 >

分佈式網絡計時

我們對性能調優的大部分討論都是以單機上的系統為中心的。但你應該知道,當涉及網絡上的系統調優時,會有一些特別的問題。網絡上的同步和計時並不容易,而且不僅僅是在互聯網上,即便是以太網也會出現這些問題。

詳細講解分佈式網絡計時超出了本書的範圍,但你應該知道,通常來說,很難得到用於跨越幾台機器的工作流的準確時序。另外,即便NTP這樣的標準協議對於高精度工作來說準確度也不夠。

在開始討論垃圾收集之前,我們先看一個前面提到過的例子——緩存對代碼性能的影響。

6.4.4 案例研究:理解緩存未命中

對於很多吞吐量較高的代碼來說,影響性能的一個主要因素就是一級緩存未命中的數量。

代碼清單6-2中的代碼操作1MB的數組,並輸出執行兩個循環中之一所用的時間。在第一個循環中,每隔16個條目對int數組中的元素加1。一級緩存的一個緩存行中通常有64個字節(在32位JVM上,Java的int是4個字節),所以這意味著每次會讀取一個緩存行(64=16*4)。

代碼清單6-2 理解緩存未命中

public class CacheTester {
  private final int ARR_SIZE = 1 * 1024 * 1024;
  private final int arr = new int[ARR_SIZE];

  private void doLoop2 {
      for (int i=0; i<arr.length; i++) arr[i]++; //處理每個條目
  }

  private void doLoop1 {
      for (int i=0; i<arr.length; i += 16) arr[i]++;//處理每個緩存行
  }

  private void run {
      for (int i=0; i<10000; i++) {//代碼熱身
        doLoop1;
        doLoop2;
        }
      for (int i=0; i<100; i++) {
        long t0 = System.nanoTime;
        doLoop1;
        long t1 = System.nanoTime;
        doLoop2;
        long t2 = System.nanoTime;
        long el = t1 - t0;
        long el2 = t2 - t1;
        System.out.println("Loop1: "+ el +" nanos ; Loop2: "+ el2);
        }
    }
    public static void main(String args) {
      CacheTester ct = new CacheTester;
      ct.run;
    }
}
  

注意,在你得到準確結果之前應該讓代碼熱熱身,以便讓JVM對你感興趣的方法進行編譯。我們會在6.6節討論更多與代碼熱身相關的內容。

第二個循環,doLoop2給數組中的每個元素加1,所以看起來它做的工作是doLoop1的16倍。下面是在筆記本上運行這段代碼得到的結果:

Loop1: 634000 nanos ; Loop2: 868000
Loop1: 801000 nanos ; Loop2: 952000
Loop1: 676000 nanos ; Loop2: 930000
Loop1: 762000 nanos ; Loop2: 869000
Loop1: 706000 nanos ; Loop2: 798000
  

計時子系統的疑難雜症

結果中的所有納秒值都很整齊,全是一千的整數倍。這表明底層系統調用(System.nanoTime最終所調用的)僅僅返回了一個微秒整數值——一微秒是1000納秒。因為這個結果是在Mac筆記本上得到的,所以我們猜測在OS X的底層系統調用只有微秒級的精度,實際上,它調用的是gettimeofday

從這個結果來看,doLoop2所用的時長不是doLoop1的16倍。這表明內存訪問在總體性能配置中佔有支配性地位。doLoop1doLoop2讀取緩存行的次數相同,而修改數據所用的CPU週期只佔整體時間的一小部分。

我們先來回顧下Java時間系統的要點。

  • 大多數系統內部都有幾個不同的時鐘。
  • 毫秒計時器是安全可靠的。
  • 更高精度的時間需要仔細處理以防止出現偏離。
  • 你需要知道計時測量的精確度和準確度。

我們下一個將要討論的是Java平台的垃圾收集子系統。這是性能的決定性因素中非常重要的一部分,並且它有很多可調節的部分,對於做性能分析的開發人員來說都可以成為非常重要的工具。