亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Java理論與實踐:再談Urban性能傳言

2019-11-18 13:33:42
字體:
來源:轉載
供稿:網友

  java? 語言遭到許多性能方面的攻擊。雖然有些攻擊可能是名符其實的,但是看看公告板和新聞組上關于這一主題的貼子,可以發現,對于 Java 虛擬機(JVM)實際的工作方式存在許多誤解。在本月的 Java 理論與實踐 中,Brian Goetz 駁斥了反復重復的有關 JVM 分配慢的傳言。請與作者和其他讀者在配套的 討論組 上分享您對這篇文章的想法。
  
  繼續,弄得一團糟
  
  沒有必要搜索眾多的 blog 或 Slashdot 貼子,去尋找像“垃圾收集永遠不會像直接內存治理一樣有效”這樣能夠說服人的陳述。而且,從某個方面來說,這些話說的是對的 ―― 動態內存治理并不一樣快 ―― 而是快得多。malloc/free 技術一次處理一個內存塊,而垃圾收集機制則采用大批量方式處理內存治理,從而形成更多的優化機會(以一些可以預見到的損失為代價)。
  
  這條“聽起來有理的意見” (以大批量清理垃圾要比一天到晚一點點兒清理垃圾更輕易)得到了數據的證實。一項研究(Zorn; 請參閱 參考資料)測量了在許多常見 C++ 應用程序中,用保守的 Boehm-Demers-Weiser(BDW)替換 malloc 的效果,結果是:許多程序在采用垃圾收集而不是傳統的分配器運行時,表現出了速度提升。(BDW 是個保守的、不移動的垃圾收集器,嚴重地限制了對分配和回收進行優化的能力,也限制了改善內存位置的能力;像 JVM 中使用的那些精確的浮動收集器可以做得更好。)
  
  在 JVM 中的分配并不總是這么快,早期 JVM 的分配和垃圾收集性能實際上很差,這當然就是 JVM 分配慢這一說法的起源。在非常早的時候,我們看到過許多“分配慢”的意見 ―― 因為就像早期 JVM 中的一切一樣,它確實慢 ―― 而性能顧問提供了許多避免分配的技巧,例如對象池。(公共服務聲明:除了對最重量的對象之外,對象池現在對于所有對象都是嚴重的性能損失,而且要在不造成并發瓶頸的情況下使用對象池也很需要技巧。)但是,從 JDK 1.0 開始已經發生了許多變化;JDK 1.2 中引入的分代收集器(generational collector)支持簡單得多的分配方式,可以極大地提高性能。
  
  分代垃圾收集
  
  分代垃圾收集器把堆分成多代;多數 JVM 使用兩代,“年輕代”和“年老代”。對象在年輕代中分配;假如它們在一定數量的垃圾收集之后仍然存在,就被當作是”長壽的“,并晉升到年老代。
  
  HotSpot 提供了使用三個年輕代收集器的選擇(串行拷貝、并行拷貝和并行清理),它們都采用“拷貝”收集器的形式,有幾個重要的公共特征??截愂占靼褍却婵臻g從中間分成兩半,每次只使用一半。開始時,使用中的一半構成了可用內存的一個大塊;分配器滿足分配請求時,返回它沒有使用的空間的前 N 個字節,并把指針(分隔“使用”部分)從“自由”部分移動過來,如清單 1 的偽代碼所示。當使用的那一半用滿時,垃圾收集器把所有活動對象(不是垃圾的那些對象)拷貝到另一半的底部(把堆壓縮成連續的),然后從另一半開始分配。
  
  清單 1. 在存在拷貝收集器的情況下,分配器的行為
  
  void *malloc(int n) {
  if (heapTop - heapStart < n)
  doGarbageCollection();
  
  void *wasStart = heapStart;
  heapStart += n;
  return wasStart;
  }
  
  從這個偽代碼可以看出為什么拷貝收集器可以實現這么快的分配 ―― 分配新對象只是檢查在堆中是否還有足夠的剩余空間,假如還有,就移動指針。不需要搜索自由列表、最佳匹配、第一匹配、lookaside 列表 ,只要從堆中取出前 N 個字節,就成功了。
  
  如何回收?
  
  但是分配僅僅是內存治理的一半,回收是另一半。對于多數對象來說,直接垃圾收集的成本為零。這是因為,拷貝收集器不需要訪問或拷貝死對象,只處理活動對象。所以在分配之后很快就變成垃圾的對象,不會造成收集周期的工作量。
  
  在典型的面向對象程序中,絕大多數對象(根據不同的研究,在 92% 到 98% 之間)“死于年輕”,這意味著它們在分配之后,通常在下一次垃圾收集之前,很快就變成垃圾。(這個屬性叫作 分代假設,對于許多面向對象語言已經得到實際測試,證實為真。)所以,不僅分配要快,對于多數對象來說,回收也要自由。
  
  線程本地分配
  
  假如分配器完全像 清單 1 所示的那樣實現,那么共享的 heapStart 字段會迅速變成顯著的并發瓶頸,因為每個分配都要取得保護這個字段的鎖。為了避免這個問題,多數 JVM 采用了 線程本地分配塊,這時每個線程都從堆中分配一個更大的內存塊,然后順序地用這個線程本地塊為小的分配請求提供服務。所以,線程花在獲得共享堆鎖的大量時間被大大減少,從而提高了并發性。(在傳統的 malloc 實現的情況下要解決這個問題更困難,成本更高;把線程支持和垃圾收集都構建進平臺促進了這類協作。)
  
  堆棧分配
  
  C++ 向程序員提供了在堆或堆棧中分配對象的選擇。基于堆棧的分配更有效:分配更便宜,回收成本真正為零,而且語言提供了隔離對象生命周期的幫助,減少了忘記釋放對象的風險。另一方面,在 C++ 中,在發布或共享基于堆棧的對象的引用時,必須非常小心,因為在堆棧幀整理時,基于堆棧的對象會被自動釋放,從而造成孤懸的指針。
  
  基于堆棧的分配的另一個優勢是它對高速緩存更加友好。在現代的處理器上,緩存遺漏的成本非常顯著,所以假如語言和運行時能夠幫助程序實現更好的數據位置,就會提高性能。堆棧的頂部通常在高速緩存中是“熱”的,而堆的頂部通常是“冷”的(因為從這部分內存使用之后可能過了很長時間)。所以,在堆上分配對象,比起在堆棧上分配對象,會帶來更多緩存遺漏。
  
  更糟的是,在堆上分配對象時,緩存遺漏還有一個非凡討厭的內存交互。在從堆中分配內存時,不管上次使用內存之后留下了什么內容,內存中的內容都被當作垃圾。假如在堆的頂部分配的內存塊不在緩存中,執行會在內存內容裝入緩存的過程中出現延遲。然后,還要用 0 或其他初始值覆蓋掉剛剛費時費力裝入緩存的那些值,從而造成大量內存活動的浪費。(有些處理器,例如 Azul 的 Vega,包含加速堆分配的硬件支持。)
  
  escape 分析
  
  Java 語句沒有提供任何明確地在堆棧上分配對象的方式,但是這個事實并不影響 JVM 仍然可以在適當的地方使用堆棧分配。JVM 可以使用叫作 escape 分析 的技術,通過這項技術,JVM 可以發現某些對象在它們的整個生命周期中都限制在單一線程內,還會發現這個生命周期綁定到指定堆棧幀的生命周期上。這樣的對象可以安全地在堆棧上而不是在堆上分配。更好的是,對于小型對象,JVM 可以把分配工作完全優化掉,只把對象的字段放入寄存器。
  
  清單 2 顯示了一個可以用 escape 分析把堆分配優化掉的示例。Component.getLocation() 方法對組件的位置做了一個保護性的拷貝,這樣調用者就無法在不經意間改變組件的實際位置。先調用 getDistanceFrom() 得到另一個組件的位置,其中包括對象的分配,然后用 getLocation() 返回的 Point 的 x 和 y 字段計算兩個組件之間的距離。
  
  清單 2. 返回復合值的典型的保護性拷貝方式
  
  public class Point {
  PRivate int x, y;
  public Point(int x, int y) {
  this.x = x; this.y = y;
  }
  public Point(Point p) { this(p.x, p.y); }
  public int getX() { return x; }
  public int getY() { return y; }
  }
  
  public class Component {
  private Point location;
  public Point getLocation() { return new Point(location); }
  
  public double getDistanceFrom(Component other) {
  Point otherLocation = other.getLocation();
  int deltaX = otherLocation.getX() - location.getX();
  int deltaY = otherLocation.getY() - location.getY();
  return Math.sqrt(deltaX*deltaX + deltaY*deltaY);
  }
  }
  
  getLocation() 方法不知道它的調用者要如何處理它返回的 Point;有可能得到一個指向 Point 的引用,比如把它放在集合中,所以 getLocation() 采用了保護性的編碼方式。但是,在這個示例中,getDistanceFrom() 并不會這么做,它只會使用 Point 很短的時間,然后釋放它,這看起來像是對完美對象的浪費。
  
  聰明的 JVM 會看出將要進行的工作,并把保護性拷貝的分配優化掉。首先,對 getLocation() 的調用會變成內聯的,對 getX() 和 getY() 的調用也同樣處理,從而導致 getDistanceFrom() 的表現會像清單 3 一樣有效。
  
  清單 3. 偽代碼描述了把內聯優化應用到 getDistanceFrom() 的結果
  
  public double getDistanceFrom(Component other) {
  Point otherLocation = new Point(other.x, other.y);
  int deltaX = otherLocation.x - location.x;
  int deltaY = otherLocation.y - location.y;
  return Math.sqrt(deltaX*deltaX + deltaY*deltaY);
  }
  
  在這一點上,escape 分析可以顯示在第一行分配的對象永遠不會脫離它的基本塊,而 getDistanceFrom() 也永遠不會修改 other 組件的狀態。(escape 指的是對象引用沒有保存到堆中,或者傳遞給可能保留一份拷貝的未知代碼。)假如 Point 真的是線程本地的,而且也清楚它的生命周期限制在分配它的基本塊內,那么它既可以進行堆棧分配,也可以完全優化掉,如清單 4 所示。
  
  清單 4. 偽代碼描述了從 getDistanceFrom() 優化掉分配后的結果
  
  public double getDistanceFrom(Component other) {<

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久国产精品首页| 欧美老女人在线视频| 欧美电影在线观看网站| 亚洲精品白浆高清久久久久久| 精品国产乱码久久久久久天美| 91精品视频网站| 久久成人免费视频| 日韩av在线免费| 96sao精品视频在线观看| 久久久久久久久亚洲| 国产91亚洲精品| 欧美夜福利tv在线| 九九精品在线视频| 日韩av在线高清| 中文字幕av日韩| 国产成人鲁鲁免费视频a| 日韩av在线免费观看| 按摩亚洲人久久| 在线日韩日本国产亚洲| 精品美女久久久久久免费| 亚洲欧美日韩一区在线| 国模视频一区二区| 自拍偷拍亚洲在线| 97国产精品视频人人做人人爱| 91精品国产成人www| 亚洲精品www久久久久久广东| 欧美精品999| 国产欧美一区二区| 色噜噜亚洲精品中文字幕| 国产精品免费一区| 乱亲女秽乱长久久久| 国外成人在线播放| 精品视频9999| 久久久久久久久久久人体| www.日韩免费| 国产免费一区二区三区香蕉精| 国产精品国产福利国产秒拍| 91视频免费网站| 精品久久久久久久久久| 亚洲九九九在线观看| 国产成人鲁鲁免费视频a| 国产欧美日韩丝袜精品一区| 欧美视频免费在线| 国产精品视频区| 一区二区三区国产在线观看| 国产在线视频欧美| 国产噜噜噜噜噜久久久久久久久| 狠狠做深爱婷婷久久综合一区| 国产男人精品视频| 九九热精品在线| 欧美日韩中文字幕综合视频| 亚洲午夜国产成人av电影男同| 久久精品国产69国产精品亚洲| 色先锋久久影院av| 国产精品久久久久久久久久久久久| 国产精品久久久精品| 精品久久久视频| 日本国产精品视频| 17婷婷久久www| 亚洲а∨天堂久久精品9966| 国产精品精品一区二区三区午夜版| 国产精品视频白浆免费视频| 富二代精品短视频| 亚洲国产成人久久| 久久国产精品免费视频| 欧美最猛性xxxxx(亚洲精品)| 欧美亚洲一区在线| 一个人看的www久久| 亚洲免费视频网站| 欧美多人爱爱视频网站| 色av中文字幕一区| 欧美贵妇videos办公室| 91精品国产91久久久久久久久| 欧美做受高潮电影o| 亚洲欧美日韩国产成人| 清纯唯美日韩制服另类| 欧美国产日本高清在线| 亚洲国产精品久久久久久| 国产日韩欧美91| 国产精品色午夜在线观看| 久久久久久久香蕉网| 久久夜精品va视频免费观看| 国产免费一区二区三区在线能观看| 亚洲男人7777| 欧美激情奇米色| 久久视频精品在线| 国产精品专区h在线观看| 国模视频一区二区三区| 欧美激情二区三区| 亚洲影视九九影院在线观看| 亚洲国产日韩欧美在线图片| 精品调教chinesegay| 日韩在线免费视频观看| 韩日欧美一区二区| 91国产美女视频| 日韩av免费在线看| 亚洲自拍另类欧美丝袜| 亚洲free性xxxx护士hd| 精品国产视频在线| 欧美日韩国产黄| 久久久伊人欧美| 国产精品日韩在线观看| 88国产精品欧美一区二区三区| 亚洲亚裔videos黑人hd| 久久99国产综合精品女同| 亚洲国产又黄又爽女人高潮的| 成人久久一区二区三区| 欧美在线性视频| 不卡av电影院| 高清亚洲成在人网站天堂| 国产女同一区二区| 欧美在线不卡区| 国产成人精品视频在线观看| 欧美—级高清免费播放| 国内外成人免费激情在线视频| 亚洲美女av电影| 久久99视频免费| 国产精品人成电影| 亚洲国内精品在线| 国语自产在线不卡| 亚洲情综合五月天| 亚洲3p在线观看| 国产精品久久久久久网站| www.精品av.com| 亚洲在线观看视频网站| 97精品一区二区视频在线观看| 亚洲少妇激情视频| 中文字幕一精品亚洲无线一区| 亚洲第一区中文字幕| 国产精品亚洲激情| 97久久久免费福利网址| 日韩av不卡电影| 欧美精品免费播放| 久99九色视频在线观看| 在线观看欧美成人| 92福利视频午夜1000合集在线观看| 国产97在线亚洲| 亚洲国产日韩一区| 亚洲国产另类久久精品| 九色成人免费视频| 欧美一区亚洲一区| 91色琪琪电影亚洲精品久久| 北条麻妃一区二区三区中文字幕| 国产一区二区三区在线| 自拍偷拍亚洲精品| 韩国精品久久久999| 91热精品视频| 亚洲人av在线影院| 91在线看www| 国产精品免费视频xxxx| 色噜噜亚洲精品中文字幕| 国产欧美亚洲视频| 欧美影院成年免费版| 色婷婷av一区二区三区久久| 亚洲福利视频二区| 国产精品亚洲综合天堂夜夜| 精品国产依人香蕉在线精品| 欧美极品少妇全裸体| 97国产精品免费视频| 欧美激情久久久久久| 成人a视频在线观看| 在线日韩日本国产亚洲| 91在线无精精品一区二区| 久久影视电视剧凤归四时歌|