国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

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

為JAVA性能而設計(3)

2019-11-18 12:23:11
字體:
來源:轉載
供稿:網友

  作者:eclipse
  
  為性能而設計, 第三部分: 遠程接口[/b]
  
   [b]學習怎樣在設計 java 類的時候避免性能冒險.[/b]
  
  [b][u]概述[/u][/b]
  
  許多 Java 的通常性能問題來源于設計過程早期的類設計想法中, 早在開發者開始考慮
  性能問題之前. 在這個系列中, Brian Goetz 討論了一些通常的 Java 性能的冒險, 解
  釋了怎樣在設計時間避免它們. 在這篇文章中, 它檢驗了遠程應用程序中的特定的性能
  問題.
  
  By Brian Goetz
  
  翻譯 by SuperMMX
  
  這個系列探索一些早期的設計思想對應用程序的性能產生影響的方法. 第一部分, 檢查了
  一個類的對象創建行為是如何嵌入它的接口中的. 特定的接口實際上要求一個類創建臨時
  對象, 或者需要它的調用者來創建臨時對象, 才能使用這個類. 因為臨時對象的創建對 Java
  程序來說是一個性能指標, 當你在設計時候, 能再對你的類接口做一些回顧來檢查性能冒?
  這是值得的.
  
  在第一和第二部分我集中于對象的創建, 因為對許多 Java 程序來說這是一個很大的性能侍?
  但是, 在分布式的應用程序中, 象建立在 RMI, CORBA, 或者 COM 之上的程序, 一個完全煌
  的性能問題就在眼前了. 這篇文章探索一些針對遠程程序的性能問題, 演示你怎樣才能通
  單地檢查一個類的接口來猜測到分布式應用程序中的性能問題.
  
  
  閱讀這個 "為性能而設計" 系列:
  
  第一部分: 接口事宜
  第二部分: 減少對象創建
  第三部分: 遠程接口
  
  [b][u]遠程調用的概觀[/u][/b]
  
  在分布式的應用程序中, 一個運行在一個系統中的對象可以調用另一個系統中的一個對象
  的方法. 這個通過很多使遠程對象表現為本地的結構的幫助而實現. 要訪問一個遠程對象,
  你首先要找到它, 可以通過使用目錄或者命名服務來實現, 象 RMI 注冊, JNDI, 或者 CORBA
  命名服務.
  
  當你通過目錄服務得到一個遠程對象的引用時, 你并沒有得到那個對象的實際的引用, 而
  是一個實現了和遠程對象同樣接口的stub對象的引用. 當你調用一個stub對象的方法時, 飧
  對象把方法的所有參數匯集起來 -- 把它們轉化成一個字節流的表現形式, 類似于序列化
  過程. 這個stub對象把匯集的參數通過網絡傳遞給一個skeleton對象, 把參數分解出來, 饔
  你想調用的實際的對象的方法. 然后這個方法向skeleton對象返回一個值, skeleton對象遜禱刂禱慵
  起來, 把它傳送給stub對象, stub對象把它分解出來, 傳遞給調用者. Phew! 一個單獨的椒
  調用要做這么多的工作. 很明顯, 除去表面的相似性, 一個遠程方法調用比本地方法調用
  更大.
  
  以上描述瀏覽了一些對于程序性能非常重要的細節. 當一個遠程方法返回的不是一個原類?
  而是一個對象時, 會發生什么? 不一定. 假如返回的對象是一種支持遠程方法調用的類型,
  它就創建一個中stub對象和一個skeleton對象, 在這種情況下需要在注冊表中查找一個遠潭韻?
  這顯然是一個高代價的操作. (遠程對象支持一種分布式的垃圾回收的形式, 包括了每一個
  參與的 JVM 維護一個線程來和其他 JVM 的維護線程進行通訊, 往返傳遞引用信息). 假如
  返回的對象不支持遠程調用, 這個對象所有的域和引用的對象都要匯集起來, 這也是一個
  代價的操作.
  
  [b][u]遠程和本地方法調用的性能比較[/u][/b]
  
  遠程對象訪問的性能特征和本地的不一樣:
  遠程對象的創建比本地對象創建代價要高. 不僅僅是當它不存在時要創建它, 而且stub對
  和skeleton對象也要創建, 還要互相感知.
  
  遠程方法調用還包括網絡的傳遞 -- 匯集起來的參數必須發送到遠程系統, 而且響應也需
  匯集起來, 在調用程序重新得到控制權之前發送回來. 匯集, 分解, 網絡延時, 實際的遠
  調用所導致的延遲都加在一起; 客戶端通常是等待所有這些而步驟完成. 一個遠程調用也
  大地依靠于底層網絡的延時.
  
  不同的數據類型有不同的匯集開支. 匯集原類型相對來說花費少一些; 匯集簡單的對象,
  Point 或者 String 要多一些; 匯集遠程對象要多得多, 而匯集那些引用非常多的對象的
  對象(象 collection 等)要更多. 這和本地調用完全矛盾, 因為傳遞一個簡單對象的引用槐
  一個復雜對象的引用花費多.
  
  [b][u]接口設計是要害[/u][/b]
  
  設計不好的遠程接口可能完全消除一個程序的性能. 不幸的是, 對本地對象來說好的接口
  的特性對遠程對象可能不適合. 大量的臨時對象創建, 就象在本系列的第一, 二部分討論?
  也能阻礙分布式的應用程序, 但是大量的傳遞更是一個性能問題. 所以, 調用一個在一個
  時對象(比如一個 Point)中返回多個值的方法比多次調用來分別得到它們可能更有效. (注
  意, 這和在第二部分給本地對象岢齙慕ㄒ?I 完全相反.)
  
  
  [b][u]實際遠程應用程序的一些重要的性能指導:[/u][/b]
  
  提防不必要的數據傳遞. 假如一個對象要同時得到幾個相關的項, 假如可能的話, 在一個
  遠程調用中實現可能輕易一些.
  
  當調用者可能不必要保持一個遠程對象的引用時, 提防返回遠程的對象.
  
  當遠程對象不需要一個對象的拷貝時, 提防傳遞復雜對象.
  
  幸運的是, 你可以通過簡單查看遠程對象的接口來找出所有的問題. 要求做任何高層動作
  的方法調用序列可以從類接口中明顯看到. 假如你看到一個通常的高層操作需要許多連續
  的遠程方法調用, 這就是一個警告信號, 可能你需要重新查看一下類接口.
  
  
  [b][u]減少遠程調用代價的技巧[/u][/b]
  
  一個例子, 考慮下面假定的治理一個組織目錄的應用程序: 一個遠程的 Directory 對象包
  含了 DirectoryEntry 對象的引用, 表現了電話簿的入口.
  [code]
  public interface Directory extends Remote {
   DirectoryEntry[] getEntries();
   void addEntry(DirectoryEntry entry);
   void removeEntry(DirectoryEntry entry);
  }
  public interface DirectoryEntry extends Remote {
   String getName();
   String getPhoneNumber();
   String getEmailAddress();
  }
  [/code]
  現在假設你想在一個 GUI email 程序中使用 Directory 的東西. 程序首先調用
  getEntries() 來得到入口的列表, 接著在每個入口中調用 getName(), 計算結果的列表,
  當用戶選擇一個時, 應用程序在相應的入口調用 getEmailAdress() 來得到 email 地址.
  
  在你能夠寫一封 email 之前有多少遠程方法調用必須發生? 你必須調用 getEntries() 一
  次, 地址簿中每個入口調用一次 getName(), 一次 getEmailAddress(). 所以假如在地址
  中有 N 個入口, 你必須進行 N + 2 次遠程調用. 注重你也需要創建 N + 1 個遠程對象引
  用, 也是一個代價很高的操作. 假如你的地址簿有許多入口的話, 不僅僅是打開 email 窗
  口的時候非常慢, 也造成了網絡阻塞, 給你的目錄服務程序造成高負載, 導致可擴展性的
  問題.
  
  現在考慮增強的 Directory 接口:
  [code]
  public interface Directory extends Remote {
   String[] getNames();
   DirectoryEntry[] getEntries();
   DirectoryEntry getEntryByName(String name);
   void addEntry(DirectoryEntry entry);
   void removeEntry(DirectoryEntry entry);
  }
  [/code]
  這將減少多少你的 email 程序所造成的花費呢? 現在你可以調用 Directory.getNames()
  一次就可以同時得到所有的名字, 只需要給你想要發送 email 的容器調用 getEntryByName() .
  這個過程需要 3 個遠程方法調用, 而不是 N + 2, 和兩個遠程對象, 而不是 N + 1 個.
  假如地址簿有再多一點的名字, 這個調用的減少在程序的響應和網絡負載和系統負載有很
  大的不同.
  
  用來減少遠程調用和引用傳遞的代價的技術叫做使用次要對象標識符. 使用一個對象的標
  屬性, -- 在這個例子中, 是 name -- 而不是傳回一個遠程對象, 作為對象的一個輕量級曄斗?
  次要標識符包含了它描述的對象足夠的信息, 這樣你只需要獲取你實際需要的遠程對象.
  在這個目錄系統的例子中, 一個人的名字是一個好的次要標識符. 在另一個例子中, 一個
  安全皮包治理系統, 一個采購標識號可能是一個好的次要標識符.
  
  另一個減少遠程調用數量的技巧是塊獲取. 你可以進一步給 Directory 接口加個方法, 來一
  次獲取多個需要的 DirectoryEntry 對象:
  [code]
  public interface Directory extends Remote {
   String[] getNames();
   DirectoryEntry[] getEntries();
   DirectoryEntry getEntryByName(String name);
   DirectoryEntry[] getEntriesByName(String names[]);
   void addEntry(DirectoryEntry entry);
   void removeEntry(DirectoryEntry entry);
  }
  [/code]
  現在你不僅可以得到需要的遠程 DirectoryEntry , 也可以用單獨一個遠程方法調用得到
  要的所有的入口. 雖然這并不減少匯集的代價, 但極大地較少了網絡往返的次數. 假如網
  延遲很重要的話, 就可以產生一個響應更快的系統(也能減少這個網絡的

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 镇平县| 建阳市| 册亨县| 昂仁县| 南安市| 灵石县| 内丘县| 延津县| 永新县| 明水县| 阿拉尔市| 双辽市| 兴义市| 盐山县| 邵武市| 萝北县| 诏安县| 阿图什市| 临海市| 台南市| 孝义市| 五常市| 上林县| 明水县| 双辽市| 行唐县| 榆林市| 中卫市| 凌源市| 海安县| 芜湖县| 陇川县| 平阴县| 闽清县| 衡南县| 祥云县| 赞皇县| 忻城县| 罗江县| 北安市| 额济纳旗|