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

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

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

2019-11-18 11:58:32
字體:
來源:轉載
供稿:網友

  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++ 向程序員提供了在堆或堆棧中分配對象的選擇?;诙褩5姆峙涓行В悍峙涓阋耍厥粘杀菊嬲秊榱?,而且語言提供了隔離對象生命周期的幫助,減少了忘記釋放對象的風險。另一方面,在 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
国产成人一区三区| 97精品国产97久久久久久| 久久久99免费视频| 国产色婷婷国产综合在线理论片a| 国产极品精品在线观看| 98视频在线噜噜噜国产| 日韩性生活视频| 蜜臀久久99精品久久久无需会员| 久久久精品一区二区三区| 精品视频久久久| 中文字幕亚洲二区| 55夜色66夜色国产精品视频| 久久综合伊人77777尤物| 永久免费看mv网站入口亚洲| 91国产视频在线播放| 国产亚洲人成a一在线v站| 欧美激情精品久久久久久蜜臀| 日韩av影院在线观看| 精品视频在线播放色网色视频| 久久男人av资源网站| 欧美日韩ab片| 性欧美xxxx视频在线观看| 在线视频日韩精品| 久久天天躁狠狠躁夜夜躁| 精品国产1区2区| 亚洲欧洲偷拍精品| 国产v综合ⅴ日韩v欧美大片| 黑人巨大精品欧美一区免费视频| 日韩欧美在线中文字幕| 亚洲国产精品免费| 欧美日本精品在线| 亚洲午夜久久久久久久| 国产一区二区激情| 精品无人区乱码1区2区3区在线| 91精品国产91久久久| 91精品在线一区| 91亚洲精品久久久| 中文字幕日韩欧美在线| 成人免费视频网址| 久久99久久亚洲国产| 高清在线视频日韩欧美| 91精品国产高清自在线| 成人欧美在线视频| 亚洲天堂av在线免费| 日韩中文字幕在线视频| 91欧美激情另类亚洲| 永久免费毛片在线播放不卡| 91香蕉国产在线观看| 久久久国产精品视频| 国产一区二区精品丝袜| 久久视频在线看| 91精品国产91久久久久久久久| 欧美性xxxxxxxxx| 日本久久久久久久| 日韩精品欧美国产精品忘忧草| 久久91精品国产91久久跳| 亚洲人成电影在线播放| 亚洲精品成人av| 国产主播精品在线| 亚洲人精品午夜在线观看| 欧美中文字幕在线视频| 久久久久久久久91| 欧美精品video| 国内精品中文字幕| 高清一区二区三区日本久| 欧美成人免费大片| 成人美女免费网站视频| 日本欧美一二三区| 欧美有码在线观看| 欧美性猛xxx| 国产精品欧美一区二区三区奶水| 国产午夜精品一区二区三区| 国产精品毛片a∨一区二区三区|国| 精品亚洲夜色av98在线观看| 欧美精品精品精品精品免费| 456国产精品| 亚洲欧洲国产伦综合| 一区二区三区四区视频| 国产精品高潮呻吟久久av黑人| 亚洲人成欧美中文字幕| 亚洲成人av在线| 国产精品久久久久999| 亚洲欧美精品中文字幕在线| 久久久久久久久久久网站| 亚洲午夜色婷婷在线| 成人性教育视频在线观看| 欧美成人全部免费| 自拍偷拍亚洲欧美| 日韩中文字幕精品| 欧美第一黄色网| 欧美福利视频在线观看| 欧美成人性色生活仑片| 亚洲肉体裸体xxxx137| 亚洲欧美激情精品一区二区| 成人精品一区二区三区电影免费| 91精品国产高清久久久久久久久| 国内偷自视频区视频综合| 日韩在线免费观看视频| 日韩av大片免费看| 综合网日日天干夜夜久久| 国产精自产拍久久久久久| 欧美黑人狂野猛交老妇| 日韩高清人体午夜| 欧美精品亚州精品| 欧美成人亚洲成人| 色噜噜狠狠色综合网图区| 欧美大片免费观看在线观看网站推荐| 欧美福利视频在线观看| 亚洲成人动漫在线播放| 国产成人一区三区| 欧美专区在线视频| 欧美激情综合亚洲一二区| 久久久久久久国产精品视频| 日本精品久久久久久久| 国产欧美一区二区三区在线看| 欧美成人免费小视频| 国产日韩欧美在线| 欧美专区日韩视频| 欧美成年人视频网站| 亚洲桃花岛网站| 久久激情视频久久| 久久中国妇女中文字幕| 国产欧美日韩精品丝袜高跟鞋| 色偷偷综合社区| 久久久999成人| 欧美午夜片欧美片在线观看| 国产精品久久久久久久美男| 午夜精品久久久99热福利| 欧美一区二区三区……| 亚洲成人黄色在线观看| 欧美日韩中文字幕日韩欧美| 国产精品久久久久久久久粉嫩av| 狠狠色香婷婷久久亚洲精品| 国产午夜精品视频| 日韩电影大片中文字幕| 国产日韩在线亚洲字幕中文| 91视频免费在线| 日韩欧美在线中文字幕| 国产精品99久久久久久白浆小说| 91在线色戒在线| 亚洲剧情一区二区| 91沈先生作品| 日韩av电影国产| 亚洲精品综合久久中文字幕| 不卡av电影在线观看| 91高潮精品免费porn| 亚洲色图激情小说| 久久成人一区二区| 色www亚洲国产张柏芝| 日韩av成人在线观看| 在线播放日韩av| 久久九九热免费视频| 欧美洲成人男女午夜视频| 亚洲电影天堂av| 精品国产欧美一区二区三区成人| 国产精品一区二区三区毛片淫片| 亚洲精品自在久久| 日韩免费观看高清| 欧美黑人xxx| 欧洲日本亚洲国产区| 成人激情电影一区二区| 亚洲人永久免费| 亚洲午夜激情免费视频| 日韩免费av一区二区|