如何應對實際測試中的問題

大多數測試設備廠商采用通用的吞吐量測試方法,但是網絡設計人員仍需要了解在實際中解決更微妙問題時的不同考慮。以下是在實際測試中,對於吞吐量和延遲兩個測試需要多考慮的壹些因素。

  比如說,兩臺路由器通過壹條T1線路連接起來,測試人員利用1Gbits光纖線路連接到路由器。T1線路只能以1.536Mbits的速率傳送數據,而光纖路可以根 據幀的不同長度以超過900Mbps的速度傳送數據。按每秒幀數測量的64字節幀的吞吐量似乎可以精確地表示為:1536000比特每秒(64字節每幀×8比特每字節)=3000幀每秒。

  但是,實際的數字可能由於多種原因而有所不同。首先,以太網幀中的數據鏈路層信息可能沒有流過T1接口。相反,可能建立了某種類型的點對點協議(PPP)鏈路,從而從以太網幀中完全刪除了二層字節的媒介訪問控制信息,並用PPP包頭中的信息代替它。

  其次,測量算法本身可能會造成問題。如果測試人員不仔細地理解測量算法和路由器的特性的話,他們會看到比上述公式所表達的吞吐量更高的吞吐量。由於路由器在緩沖區中存儲數據幀並且在測試過程中緩存區滿了,這個問題就會突然出現。當測試設備發出的傳輸流終止於測試端時,緩沖區繼續通過T1接口傳送存儲的幀。在這種情況下,吞吐量算法必須進行修改以使實際被統計的幀嵌入到未被統計的幀系列中。

  延遲是另壹項基礎性能標準,但是隨著測試的開展問題會變得復雜起來。RFC 1242將比特轉發設備的延遲定義為“從輸入幀的第壹比特的結尾到達輸出端口時開始計時,輸出幀的第壹比特的開始出現輸出端口上時結束計時,這段的時間間隔。”這裏,延遲是針對網絡設備定義的。RFC 2544中建議的方法如下:首先確定網絡設備的最大吞吐量,然後以此吞吐量速度繼續傳送120秒的數據流,並在60秒時傳送壹幀“簽名”幀。簽名幀被用於傳送時間標記,當接收到簽名幀時,對時間標記進行檢查。收到時間標記與發送時間標記之間的間隔用於確定延遲。RFC 2544建議進行多次獨立的試驗,最終得到的數據是多次試驗結果的平均值。壹般來說,如果測試人員試圖得到在某種程度上表示網絡設備轉發幀能力的數據的話,這種方法是可行的。但是,在計算延遲時常常需要考慮更多的東西。

  如果簽名幀由於某種原因被丟棄,RFC 2544中描述的延遲測量法會出現問題。它可能會造成測試設備無限期地等待簽名幀的到達。由於數據流是以網絡設備可支持的吞吐速率發送的,因此丟棄簽名幀的現象不應當出現。然而,在實際情況可能有出入,而在發生丟棄幀的情況下,測試將是無效的。

  解決這個問題的壹種辦法是設計壹種測試算法,這種算法每秒發送壹個簽名幀,然後捕獲所有的簽名幀。當延遲幀的傳輸結束時,測試設備可以在捕獲到幀的集合的中心點挑出壹幀並執行其延遲測量。如果簽名幀被丟棄,測試仍可以利用另壹個簽名幀來代替它。這種方法提高了這種測試的強健性。

  但是,這種修改後的延遲算法可能還不能滿足要求。利用這種算法,測試人員不能測量延遲的變化,即抖動。為了準確地進行這種測試,測試人員必須實時地捕獲和分析所有的幀。然後他們可以計算時間的最小、最大和平均延遲。

  為了將此論點再向前發展壹步,測試人員可以將最小、最大和平均延遲放到壹個專門的緩存區序列中,並定期地切換到壹個新緩存區,這將產生時間變化的延遲。利用這類設備,測試人員可以在其他傳輸流模式流過設備的同時勾畫出網絡設備的延遲行為,從而在高強度條件下得到網絡設備更準確的描述。顯然,由於這類測試超出了任何處理器可跟蹤記錄的能力,因此這種測試要求測試設備必須利用優化的硬件來跟蹤記錄延遲。

CE技術融合傳統傳送網

CE融合傳送網,首先就要求CE能夠有效傳送各類業務。

  1. IP城域網

  萬兆到邊緣

  在IP接入網,局端接入設備如SW、DSLAM或ONU上行到匯聚設備時,其鏈路壹般以MSTP電路或裸纖實現。MSTP可提供10M~50M帶寬,50M以上耗資源較多,導致帶寬擴展性很差。而裸纖存在嚴重缺陷:1. 易出故障,且排障難。裸纖容易受外部環境影響而中斷,且沿途存在多個活動接頭、熔接點,衰耗大,故障後排除困難。2. 光纖資源消耗大。裸纖網最大的問題在於消耗運營商寶貴的光纖資源。

  利用CE萬兆以太環網技術,可有效解決傳統傳送網容量低下和可靠性差的問題。將CE交換機推到用戶邊緣,下掛SW、DSLAM或OLT,縮短匯聚設備到接入設備的距離,實際上減少了純光纖鏈路的故障風險,並通過共享環路提高了鏈路利用率。同時,通過RRPP+環網技術,充分保證網絡出現故障時的業務安全,使網絡具有良好的健壯性、可用性。最後,CE交換機的萬兆接入容量可使網絡具備很強的擴展性,在按需建設原則下,單次工程完成後可滿足較長時期內的升級需求(如圖1所示)。

  提升匯聚鏈路可靠性和利用率

  匯聚交換機壹般通過裸纖或波分電路雙歸方式與業務控制點如BAS、SR聯接,此方式存在缺陷。首先,匯聚點到BAS或SR其實只有壹條上行鏈路,鏈路沒有保護。其次,雙歸方式極大消耗光纖或電路資源。第三,由於匯聚點業務密度不壹,常出現各點鏈路負荷不均衡的現象。例如,設有10條鏈路,2條匯聚鏈路負載85%,8條鏈路10%,平均鏈路利用率僅為25%,但此時還需要擴容2條鏈路,無法做到帶寬資源統壹調配和統計復用。

高性能JAVA代碼之_內存管理

更甚者妳寫的代碼,GC根本就回收不了,直接系統掛掉。GC是壹段程序,不是智能,他只回收他認為的垃圾,而不是回收妳認為的垃圾。
    GC垃圾回收:
    Grabage Collection相信學過JAVA的人都知道這個是什麽意思.但是他是如何工作的呢?
    首先,JVM在管理內存的時候對於變量的管理總是分新對象和老對象。新對象也就是開發者new出來的對象,但是由於生命周期短,那麽他占用的內存並不是馬上釋放,而是被標記為老對象,這個時候該對象還是要存在壹段時間。然後由JVM決定他是否是垃圾對象,並進行回收。
    所以我們可以知道,垃圾內存並不是用完了馬上就被釋放,所以就會產生內存釋放不及時的現象,從而降低了內存的使用。而當程序浩大的時候。這種現象更為明顯,並且GC的工作也是需要消耗資源的。所以,也就會產生內存浪費。
    JVM中的對象生命周期裏談內存回收:
    對象的生命周期壹般分為7個階段:創建階段,應用階段,不可視階段,不可到達階段,可收集階段,終結階段,釋放階段。
    創建階段:首先大家看壹下,如下兩段代碼:
    test1:
    for( int i=0; i<10000; i++)
    Object obj=new Object();
    test2:
    Object obj=null;
    for( int i=0; i<10000; i++)
    obj=new Object();
    這兩段代碼都是相同的功能,但是顯然test2的性能要比test1性能要好,內存使用率要高,這是為什麽呢?原因很簡單,test1每次執行for循環都要創建壹個Object的臨時對象,但是這些臨時對象由於JVM的GC不能馬上銷毀,所以他們還要存在很長時間,而test2則只是在內存中保存壹份對象的引用,而不必創建大量新臨時變量,從而降低了內存的使用。
    另外不要對同壹個對象初始化多次。例如:
    public class A{
    private Hashtable table = new Hashtable();
    public A(){   table = new Hashtable();
    // 這裏應該去掉,因為table已經被初始化.
    }
    }
    這樣就new了兩個Hashtable,但是卻只使用了壹個。另外壹個則沒有被引用.而被忽略掉.浪費了內存.並且由於進行了兩次new操作.也影響了代碼的執行速度。
    應用階段:即該對象至少有壹個引用在維護他.
    不可視階段:即超出該變量的作用域。這裏有壹個很好的做法,因為JVM在GC的時候並不是馬上進行回收,而是要判斷對象是否被其他引用在維護.所以,這個時候如果我們在使用完壹個對象以後對其obj=null或者obj.doSomething()操作,將其標記為空,可以幫助JVM及時發現這個垃圾對象.
    不可到達階段:就是在JVM中找不到對該對象的直接或者間接的引用。
    可收集階段,終結階段,釋放階段:此為回收器發現該對象不可到達,finalize方法已經被執行,或者對象空間已被重用的時候。
    JAVA的析構方法:
    可能不會有人相信,JAVA有析構函數? 是的,有。因為JAVA所有類都繼承至Object類,而finalize就是Object類的壹個方法,這個方法在JAVA中就是類似於C++析構函數.壹般來說可以通過重載finalize方法的形式才釋放類中對象.如:
    public class A{
    public Object a;
    public A(){ a = new Object ;}
    protected void finalize() throws java.lang.Throwable{
    a = null; // 標記為空,釋放對象
    super.finalize(); // 遞歸調用超類中的finalize方法.
    }
    }
    當然,什麽時候該方法被調用是由JVM來決定的…………………..
    壹般來說,我們需要創建壹個destory的方法來顯式的調用該方法.然後在finalize也對該方法進行調用,實現雙保險的做法.
    由於對象的創建是遞歸式的,也就是先調用超級類的構造,然後依次向下遞歸調用構造函數,所以應該避免在類的構造函數中初始化變量,這樣可以避免不必要的創建對象造成不必要的內存消耗.當然這裏也就看出來接口的優勢.
    數組的創建:
    由於數組需要給定壹個長度,所以在不確定數據數量的時候經常會創建過大,或過小的數組的現象.造成不必要的內存浪費,所以可以通過軟引用的方式來告訴JVM及時回收該內存.(軟引用,具體查資料).
    例如:
    Object obj = new char[10000000000000000];
    SoftReference ref = new SoftReference(obj);
    共享靜態存儲空間:
    我們都知道靜態變量在程序運行期間其內存是共享的,因此有時候為了節約內存工件,將壹些變量聲明為靜態變量確實可以起到節約內存空間的作用.但是由於靜態變量生命周期很長,不易被系統回收,所以使用靜態變量要合理,不能盲目的使用.以免適得其反。
    因此建議在下面情況下使用:
    1,變量所包含的對象體積較大,占用內存過多.
    2,變量所包含對象生命周期較長.
    3,變量所包含數據穩定.
    4,該類的對象實例有對該變量所包含的對象的共享需求.(也就是說是否需要作為全局變量).
    對象重用與GC:
    有的時候,如數據庫操作對象,壹般情況下我們都需要在各個不同模塊間使用,所以這樣的對象需要進行重用以提高性能.也有效的避免了反復創建對象引起的性能下降.
    壹般來說對象池是壹個不錯的註意.如下:
    public abstarct class ObjectPool{
    private Hashtable locked,unlocked;
    private long expirationTime;
    abstract Object create();
    abstract void expire( Object o);
    abstract void validate( Object o);
    synchronized Object getObject(){…};
    synchronized void freeObject(Object o){…};
    }
    這樣我們就完成了壹個對象池,我們可以將通過對應的方法來存取刪除所需對象.來維護這快內存提高內存重用.
    當然也可以通過調用System.gc()強制系統進行垃圾回收操作.當然這樣的代價是需要消耗壹些cpu資源.
    不要提前創建對象:
    盡量在需要的時候創建對象,重復的分配,構造對象可能會因為垃圾回收做額外的工作降低性能.
    JVM內存參數調優:
    強制內存回收對於系統自動的內存回收機制會產生負面影響,會加大系統自動回收的處理時間,所以應該盡量避免顯式使用System.gc(),
    JVM的設置可以提高系統的性能.例如:
    java -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -Xms512m -Xmx512m
    具體可以查看java幫助文檔.我們主要介紹程序設計方面的性能提高.
    JAVA程序設計中有關內存管理的其他經驗:
    根據JVM內存管理的工作原理,可以通過壹些技巧和方式讓JVM做GC處理時更加有效.,從而提高內存使用和縮短GC的執行時間.
    1,盡早釋放無用對象的引用.即在不使用對象的引用後設置為空,可以加速GC的工作.(當然如果是返回值…..)
    2,盡量少用finalize函數,此函數是JAVA給程序員提供的壹個釋放對象或資源的機會,但是卻會加大GC工作量.
    3,如果需要使用到圖片,可以使用soft應用類型,它可以盡可能將圖片讀入內存而不引起OutOfMemory.
    4,註意集合數據類型的數據結構,往往數據結構越復雜,GC工作量更大,處理更復雜.
    5,盡量避免在默認構造器(構造函數)中創建,初始化大量的對象.
    6,盡量避免強制系統做垃圾回收.會增加系統做垃圾回收的最終時間降低性能.
    7,盡量避免顯式申請數組,如果不得不申請數組的話,要盡量準確估算數組大小.
    8,如果在做遠程方法調用.要盡量減少傳遞的對象大小.或者使用瞬間值避免不必要數據的傳遞.
    9,盡量在合適的情況下使用對象池來提高系統性能減少內存開銷,當然,對象池不能過於龐大,會適得其反.