<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經(jīng)轉(zhuǎn)移至github,大家請訪問 http://qaseven.github.io/

    功能測試用例設(shè)計(表格)


    posted @ 2014-11-27 11:53 順其自然EVO 閱讀(617) | 評論 (0)編輯 收藏

    Linux CPU實時監(jiān)控命令mpstat介紹

    1,簡介
      mpstat是Multiprocessor  Statistics的縮寫,是實時系統(tǒng)監(jiān)控工具。其報告是CPU的一些統(tǒng)計信息,這些信息存放在/proc/stat文件中。在多CPUs系統(tǒng)里,其不但能查看所有CPU的平均狀況信息,而且能夠查看特定CPU的信息。mpstat最大的特點是:可以查看多核心cpu中每個計算核心的統(tǒng)計數(shù)據(jù);而類似工具vmstat只能查看系統(tǒng)整體cpu情況。
      2,安裝
    [root@ora10g ~]# mpstat
    -bash: mpstat: command not found
    [root@ora10g ~]# mount -o loop -t iso9660 /dev/cdrom /mnt/cdrom
    [root@ora10g ~]# cd /mnt/cdrom/Server/
    [root@ora10g Server]# rpm -ivh sysstat-7.0.2-3.el5.i386.rpm
    warning: sysstat-7.0.2-3.el5.i386.rpm: Header V3 DSA signature: NOKEY, key ID 37017186
    Preparing...                ########################################### [100%]
    1:sysstat                ########################################### [100%]
      3,實例
      用法
      mpstat -V  顯示mpstat版本信息
      mpstat -P ALL 顯示所有CPU信息
      mpstat -P n 顯示第n個cup信息,n為數(shù)字,計數(shù)從0開始
      mpstat n m  每個n秒顯示一次cpu信息,連續(xù)顯示m次,最后顯示一個平均值
      mpstat n    每個n秒顯示一次cpu信息,連續(xù)顯示下去
      查看每個cpu核心的詳細(xì)當(dāng)前運行狀況信息,輸出如下:
    [root@ora10g ~]# mpstat -P ALL
    Linux 2.6.18-194.el5 (ora10g.up.com)    11/05/14
    09:13:02     CPU   %user   %nice    %sys %iowait    %irq   %soft  %steal   %idle    intr/s
    09:13:02     all    0.62    0.01    0.54    3.48    0.00    0.02    0.00   95.32   1039.58
    09:13:02       0    0.92    0.01    1.18    8.77    0.01    0.05    0.00   89.06   1030.23
    09:13:02       1    0.27    0.00    0.31    1.46    0.00    0.01    0.00   97.96      1.00
    ....
    09:13:02      14    1.12    0.02    0.45    2.99    0.00    0.01    0.00   95.39      7.74
    09:13:02      15    0.18    0.00    0.22    0.70    0.00    0.01    0.00   98.90      0.59
      查看多核CPU核心的當(dāng)前運行狀況信息, 每2秒更新一次
      [root@ora10g ~]# mpstat -P ALL 2
      查看某個cpu的使用情況,數(shù)值在[0,cpu個數(shù)-1]中取值
      [root@ora10g ~]# mpstat -P 2
      Linux 2.6.18-194.el5 (ora10g.up.com)    11/05/14
      10:19:28     CPU   %user   %nice    %sys %iowait    %irq   %soft  %steal   %idle    intr/s
      10:19:28       2    0.08    0.00    0.04    0.22    0.00    0.01    0.00   99.64      0.55
      查看多核CPU核心的當(dāng)前運行狀況信息, 每2秒更新一次,顯示5次
      [root@ora10g ~]# mpstat -P ALL 2 5
     4,字段含義如下
      英文解釋:
      CPU:Processor number. The keyword all indicates that statistics are calculated as averages among all processors.
      %user:Show the percentage of CPU utilization that occurred while executing at the user level (application).
      %nice:Show the percentage of CPU utilization that occurred while executing at the user level with nice priority.
      %sys:Show  the  percentage  of CPU utilization that occurred while executing at the system level (kernel). Note that
      this does not include time spent servicing interrupts or softirqs.
      %iowait:Show the percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk  I/O request.
      %irq:Show the percentage of time spent by the CPU or CPUs to service interrupts.
      %soft:Show  the  percentage  of time spent by the CPU or CPUs to service softirqs.  A softirq (software interrupt) is
      one of up to 32 enumerated software interrupts which can run on multiple CPUs at once.
      %steal:Show the percentage of time spent in involuntary wait by the virtual CPU or CPUs while the hypervisor was  ser-vicing another virtual processor.
      %idle:Show  the percentage of time that the CPU or CPUs were idle and the system did not have an outstanding disk I/O request.
      intr/s:Show the total number of interrupts received per second by the CPU or CPUs.
      參數(shù)解釋 從/proc/stat獲得數(shù)據(jù)
      CPU 處理器 ID
      user 在internal時間段里,用戶態(tài)的CPU時間(%),不包含 nice值為負(fù) 進(jìn)程 (usr/total)*100
      nice 在internal時間段里,nice值為負(fù)進(jìn)程的CPU時間(%)   (nice/total)*100
      system 在internal時間段里,核心時間(%)   (system/total)*100
      iowait 在internal時間段里,硬盤IO等待時間(%) (iowait/total)*100
      irq 在internal時間段里,硬中斷時間(%)      (irq/total)*100
      soft 在internal時間段里,軟中斷時間(%)    (softirq/total)*100
      idle 在internal時間段里,CPU除去等待磁盤IO操作外的因為任何原因而空閑的時間閑置時間(%)(idle/total)*100
      intr/s 在internal時間段里,每秒CPU接收的中斷的次數(shù)intr/total)*100
      CPU總的工作時間=total_cur=user+system+nice+idle+iowait+irq+softirq
      total_pre=pre_user+ pre_system+ pre_nice+ pre_idle+ pre_iowait+ pre_irq+ pre_softirq
      user=user_cur – user_pre
      total=total_cur-total_pre
      其中_cur 表示當(dāng)前值,_pre表示interval時間前的值。上表中的所有值可取到兩位小數(shù)點。

    posted @ 2014-11-26 15:09 順其自然EVO 閱讀(1073) | 評論 (0)編輯 收藏

    PHP寫的從數(shù)據(jù)庫導(dǎo)入到EXCEL

    原理: 就是原理很分頁原理一樣! 選取一定數(shù)量的數(shù)據(jù)然后變成數(shù)組,接著直接寫入文件。接下來繼續(xù)選取后面沒選定數(shù)據(jù)在變成數(shù)組,接著在寫入文件!這個解決了內(nèi)存溢出。但是多CPU還是有個考驗! 由于本人剛剛學(xué)PHP(PHP培訓(xùn) php教程 )不久,功力不深厚!只能寫出這樣的東西!
      源碼!
      Excel類
    PHP code
    class Excel{
    var $header = "<?xml version="1.0" encoding="utf-8"?>
    <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:x="urn:schemas-microsoft-com:office:excel"
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:html="http://www.w3.org/TR/REC-html40">";
    var $footer = "</Workbook>";
    var $lines = array ();
    var $worksheet_title = "Table1";
    function addRow ($array) {
    $cells = "";
    foreach ($array as $k => $v):
    if(is_numeric($v)) {
    if(substr($v, 0, 1) == 0) {
    $cells .= "<Cell><Data ss:Type="String">" . $v . "</Data></Cell>n";
    } else {
    $cells .= "<Cell><Data ss:Type="Number">" . $v . "</Data></Cell>n";
    }
    } else {
    $cells .= "<Cell><Data ss:Type="String">" . $v . "</Data></Cell>n";
    }
    endforeach;
    $this->lines[] = "<Row>n" . $cells . "</Row>n";
    unset($arry);
    }
    function setWorksheetTitle ($title) {
    $title = preg_replace ("/[\|:|/|?|*|[|]]/", "", $title);
    $title = substr ($title, 0, 31);
    $this->worksheet_title = $title;
    }
    function generateXML ($filename) {
    // deliver header (as recommended in PHP manual)
    header("Content-Type: application/vnd.ms-excel; charset=utf-8");
    header("Content-Disposition: inline; filename="" . $filename . ".xls"");
    // print out document to the browser
    // need to use stripslashes for the damn ">"
    echo stripslashes ($this->header);
    echo "n<Worksheet ss:Name="" . $this->worksheet_title . "">n<Table>n";
    echo "<Column ss:Index="1" ss:AutoFitWidth="0" ss:Width="110"/>n";
    echo implode ("n", $this->lines);
    echo "</Table>n</Worksheet>n";
    echo $this->footer;
    exit;
    }
    function write ($filename) // 重點
    {
    $content= stripslashes ($this->header);
    $content.= "n<Worksheet ss:Name="" . $this->worksheet_title . "">n<Table>n";
    $content.= "<Column ss:Index="1" ss:AutoFitWidth="0" ss:Width="110"/>n";
    $content.= implode ("n", $this->lines);
    $content.= "</Table>n</Worksheet>n";
    $content.= $this->footer;//EXCEL文件
    //error_log($content, 3,$filename);
    if (!file_exists($filename))//判斷有沒有文件
    {
    fopen($filename,'a');
    }
    $fp = fopen($filename,'a');
    fwrite($fp, $content);//寫入文件
    fclose($fp);
    unset($this->lines);//清空內(nèi)存中的數(shù)據(jù)
    }
    }
     頁面
    PHPcode
    include_once"./include/class.excel.PHP";//調(diào)用EXCEL類
    require_once'./include/class.zipfile.PHP';//調(diào)用大包類
    $xls=newExcel;//實例化
    $w=explode("limit",$where_str);//把WHERE
    $p=6000;//分頁原理
    $a=$ip_list_count/$p;//分頁原理
    if($ip_list_count%$p==0)//分頁原理
    else//分頁原理
    for($i=0;$i<=$a;$i++)//循環(huán)寫出
    {
    $s=6000*$i;
    $ip=$_SG['db']->fetch_all("select*frommain_info".$w[0]."limit".$s.",".$p);//調(diào)用自己寫的數(shù)據(jù)庫(數(shù)據(jù)庫培訓(xùn)數(shù)據(jù)庫認(rèn)證)方法,寫出數(shù)組
    $xls->addArray($ip);//調(diào)用EXCEL類中addArray方法
    xml1=$xls->write("./".$i.".xls");//調(diào)用EXCEL類中write方法
    unset($ip);
    unset($xml1);
    sleep(1);
    }

    posted @ 2014-11-26 15:08 順其自然EVO 閱讀(470) | 評論 (0)編輯 收藏

    iOS為移動中的UIView(UIButton )添加點擊事件

     高高興興迎接新的產(chǎn)品新需求,滿心歡喜的開始工作,結(jié)果研究了一下午才發(fā)現(xiàn),是自己想的太簡單了,是我太單純呀。
      需求是這樣的類似下雪的效果,隨機(jī)產(chǎn)生一些小雪花,然后每個雪花可以點擊到下個頁面。
      接到需求之后我的首先想法就是用button實現(xiàn)不久可以了,多簡單點事情,結(jié)果實踐之后就知道自己多么的無知了,在移動中的button根本沒有辦法接收點擊事件。
      然后同事給出了一種解決辦法,通過手勢獲取點擊的位置,然后遍歷頁面上的控件,如果在這個范圍內(nèi)就點擊成功。通過這個想法我嘗試用frame來實現(xiàn)需求,然后發(fā)現(xiàn)自己又白癡了,頁面上所有的“雪花”的frame,都是動畫結(jié)束的位置,并不是實時的位置。
      但是我感到用手勢,然后通過位置,遍歷,這個思路應(yīng)該是對的,于是繼續(xù)百度,發(fā)現(xiàn)了一個好東西
      - (CALayer *)hitTest:(CGPoint)p;
      通過這個可以得到這個頁面時候覆蓋了這個點,這樣就可以解決我的問題了,把手勢加在“雪花”的父頁面上,然后點擊事件里進(jìn)行處理(當(dāng)然 用這個方法就沒有必要一定用button)
    -(void)tapClick:(UITapGestureRecognizer *)tap
    {
    CGPoint clickPoint =  [tap locationInView:self];
    for (UIImageView *imageView in [self subviews])
    {
    if ([imageView.layer.presentationLayer hitTest:clickPoint])
    {
    // This button was hit whilst moving - do something with it here
    break;
    }
    }
    }
    }
      這樣就可以解決問題,當(dāng)然應(yīng)該還有其他的方法,歡迎補充。

    posted @ 2014-11-26 15:08 順其自然EVO 閱讀(1373) | 評論 (0)編輯 收藏

    Java為什么使用抽象類和接口

     Java接口和Java抽象類代表的就是抽象類型,就是我們需要提出的抽象層的具體表現(xiàn)。OOP面向?qū)ο蟮木幊蹋绻岣叱绦虻膹?fù)用率,增加程序的可維護(hù)性,可擴(kuò)展性,就必須是面向接口的編程,面向抽象的編程,正確地使用接口、抽象類這些太有用的抽象類型做為你結(jié)構(gòu)層次上的頂層。
      1、Java接口和Java抽象類最大的一個區(qū)別,就在于Java抽象類可以提供某些方法的部分實現(xiàn),而Java接口不可以,這大概就是Java抽象類唯一的優(yōu)點吧,但這個優(yōu)點非常有用。 如果向一個抽象類里加入一個新的具體方法時,那么它所有的子類都一下子都得到了這個新方法,而Java接口做不到這一點,如果向一個Java接口里加入一個新方法,所有實現(xiàn)這個接口的類就無法成功通過編譯了,因為你必須讓每一個類都再實現(xiàn)這個方法才行.
      2、一個抽象類的實現(xiàn)只能由這個抽象類的子類給出,也就是說,這個實現(xiàn)處在抽象類所定義出的繼承的等級結(jié)構(gòu)中,而由于Java語言的單繼承性,所以抽象類作為類型定義工具的效能大打折扣。 在這一點上,Java接口的優(yōu)勢就出來了,任何一個實現(xiàn)了一個Java接口所規(guī)定的方法的類都可以具有這個接口的類型,而一個類可以實現(xiàn)任意多個Java接口,從而這個類就有了多種類型。
      3、從第2點不難看出,Java接口是定義混合類型的理想工具,混合類表明一個類不僅僅具有某個主類型的行為,而且具有其他的次要行為。
      4、結(jié)合1、2點中抽象類和Java接口的各自優(yōu)勢,具精典的設(shè)計模式就出來了:聲明類型的工作仍然由Java接口承擔(dān),但是同時給出一個Java抽象類,且實現(xiàn)了這個接口,而其他同屬于這個抽象類型的具體類可以選擇實現(xiàn)這個Java接口,也可以選擇繼承這個抽象類,也就是說在層次結(jié)構(gòu)中,Java接口在最上面,然后緊跟著抽象類,哈,這下兩個的最大優(yōu)點都能發(fā)揮到極至了。這個模式就是“缺省適配模式”。 在Java語言API中用了這種模式,而且全都遵循一定的命名規(guī)范:Abstract +接口名。
      Java接口和Java抽象類的存在就是為了用于具體類的實現(xiàn)和繼承的,如果你準(zhǔn)備寫一個具體類去繼承另一個具體類的話,那你的設(shè)計就有很大問題了。Java抽象類就是為了繼承而存在的,它的抽象方法就是為了強制子類必須去實現(xiàn)的。
      使用Java接口和抽象Java類進(jìn)行變量的類型聲明、參數(shù)是類型聲明、方法的返還類型說明,以及數(shù)據(jù)類型的轉(zhuǎn)換等。而不要用具體Java類進(jìn)行變量的類型聲明、參數(shù)是類型聲明、方法的返還類型說明,以及數(shù)據(jù)類型的轉(zhuǎn)換等。
      我想,如果你編的代碼里面連一個接口和抽象類都沒有的話,也許我可以說你根本沒有用到任何設(shè)計模式,任何一個設(shè)計模式都是和抽象分不開的,而抽象與Java接口和抽象Java類又是分不開的。
      接口的作用,一言以蔽之,就是標(biāo)志類的類別。把不同類型的類歸于不同的接口,可以更好的管理他們。把一組看如不相關(guān)的類歸為一個接口去調(diào)用.可以用一個接口型的變量來引用一個對象,這是接口我認(rèn)為最大的作用.
      自己的感想
      在平時的JAVA編程中,用JDBC連接數(shù)據(jù)庫是非常常用的.而這里面涉及到的有DriverManager,Connection,Statement,其中第一個是類,后兩者是接口.Connection用于獲取一個指定了數(shù)據(jù)庫的連接.而這個數(shù)據(jù)庫的指定是在程序的開頭或者配置文件中指定.那么通過DriverManager.getConnection就可以獲得根據(jù)指定數(shù)據(jù)庫的具體數(shù)據(jù)庫連接對象.
      那么,問題的關(guān)鍵就在這里,在以后的程序中,我門所使用的這個Connection,都是這個接口引用的一個對象.它即可以是oracle數(shù)據(jù)庫連接對象, 也可以是sql server連接對象.但光看內(nèi)部程序,我們并不知道它具體是那種類型的.因為通過接口.它展現(xiàn)給我們的都是Connection類型的.不管我們換了什么數(shù)據(jù)庫,程序中總是Connection conn=...
      但是假如我們不用Connection接口.而換用具體的類,那么如果我們只用一種數(shù)據(jù)庫比如sql server,那我們就用這個SqlserverConnection類來實例一個對象然后在程序中調(diào)用.但是假設(shè)有天我們要換成mysql數(shù)據(jù)庫呢?那么,程序用所有的SqlServerConnection是不是都要換成MysqlConnection呢,并且,方法可能都會失效.
      這就是接口的優(yōu)勢體現(xiàn),如果用接口,我們不用去管程序中具體是在調(diào)用哪個類,我只要知道是調(diào)用具有某種共同屬性的類.而這個類的指定都交給工廠類去完成.在程序內(nèi)部,我們完全只能看見的是對接口的調(diào)用.這個接口就代表著具體的實現(xiàn)類了.
      現(xiàn)在學(xué)習(xí)MVC模式。使得WEB開發(fā)以多層的方式。而再這些層中關(guān)系比較密切的就是模型層,持久化層,然后是底層數(shù)據(jù)庫。模型層中需要BO,DTO,VO。而持久化層就是DAO類啦。不過按照大型項目架構(gòu)。每層之間都應(yīng)該通過接口。
      這點比較重要。接口的作用是為了降低層之間的耦合度。這樣,下層只對上層公開接口。而封閉了內(nèi)部實現(xiàn)。這是好處1。第二呢就是當(dāng)接口的實現(xiàn)改變時。上層的調(diào)用代碼是不用改變的。最后一點呢。就是接口本身的好處了,那就是一個接口,多種實現(xiàn)。具體要用到那種實現(xiàn)由工廠指定.那么萬一實現(xiàn)改變了,也只用改工廠,不用改程序.

    posted @ 2014-11-26 14:56 順其自然EVO 閱讀(268) | 評論 (0)編輯 收藏

    如何使用Java讀寫系統(tǒng)屬性?

     如何使用Java讀寫系統(tǒng)屬性?
      讀:
    Properties props = System.getProperties();
    Enumeration prop_names = props.propertyNames();
    while (prop_names.hasMoreElements()) {
    String prop_name = (String) prop_names.nextElement();
    String property = props.getProperty(prop_name);
    System.out.println(“Property ‘” + prop_name + “‘ is ‘”+ property + “‘”);
    }
      寫:
      System.setProperties(props);
      簡述properties文件的結(jié)構(gòu)和基本用法
      結(jié)構(gòu):擴(kuò)展名為properties的文件,內(nèi)容為key、value的映射,例如”a=2″
      用法:
    public class Test {
    public static void main(String args[]) {
    try {
    String name = “test.properties”;
    InputStream in = new BufferedInputStream(new FileInputStream(name));
    Properties p = new Properties();
    p.load(in);
    System.out.println(“a的值==” + p.getProperty(“a”));
    } catch (Exception err) {
    err.printStackTrace();
    }
    }
    }

    posted @ 2014-11-26 14:55 順其自然EVO 閱讀(211) | 評論 (0)編輯 收藏

    項目管理雜談-需求無止境

    項目又延期了,老板恨恨的批評了整個項目組,投入了那么多,產(chǎn)出在哪里?查原因,發(fā)現(xiàn)是由于項目的需求不斷變更導(dǎo)致,這恐怕是很多項目經(jīng)理、程序員都經(jīng)歷過的事。
      我這里就談?wù)勴椖垦悠诘囊粋€重要因素:需求問題
      這張圖大家再熟悉不過了,我再炒一下冷飯,列一下主要可能的情況:
      客戶為何提不了真正的需求?
      1、業(yè)務(wù)部門:業(yè)務(wù)人員基本是站在自身的角度看問題,從自身負(fù)責(zé)的業(yè)務(wù)出發(fā),沒有從本部門或更高層次來分析問題,導(dǎo)致需求的著眼點比較低。在此基礎(chǔ)上形成的最終需求也就是把各部門的需求進(jìn)行匯總,簡單處理罷了。而且,業(yè)務(wù)部門對技術(shù)知識的匱乏,也導(dǎo)致其提出需求時是沒有考慮技術(shù)上方面的。
      2、技術(shù)人員:客戶方面的技術(shù)人員由于業(yè)務(wù)知識有限,無法挖掘更深層次的需求,只能是基于已有需求,或者輕度發(fā)掘部分需求,無法從根本上解決需求的問題。
      按照以上提出的需求,可想而知,項目的結(jié)局如何。也有部分項目,在需求分析階段,生成了完整的需求規(guī)格說明書,并且用戶簽字畫押,最終的結(jié)果是如果不能真正解決客戶業(yè)務(wù)的問題,即使系統(tǒng)投產(chǎn)了,也必將引來用戶的各種抱怨,勢必對公司形象、后續(xù)項目產(chǎn)生各種不利影響。
      我們在整天抱怨需求不斷變化的同時,能否換個角度來看待需求的變化,假設(shè)需求就是變化的,事實情況也是如此。從企業(yè)及業(yè)務(wù)自身的發(fā)展來看,企業(yè)是不斷發(fā)展的,而業(yè)務(wù)也是不斷發(fā)展的,為了滿足企業(yè)經(jīng)營需要及業(yè)務(wù)發(fā)展需要,需求本身就是應(yīng)該是不斷變化和發(fā)展的。
      那么,真正的需求在哪里?
      從企業(yè)運營角度看,為什么要做系統(tǒng)?其目的都是滿足企業(yè)運營的需要,只有站在企業(yè)運營的高度來審視需求,才能真正幫助需求發(fā)起人,形成完整的需求。這就需要我們:
      1、真正掌握做該系統(tǒng)的目的
      2、程序員要深入了解業(yè)務(wù),多溝通,最好有領(lǐng)域?qū)<覅f(xié)助,從上而下梳理業(yè)務(wù)需求,糾正不合理的需求,挖掘潛在的需求
      3、以技術(shù)的手段來解決需求變更的問題,做到以不變應(yīng)萬變,從而在最大程度上減少需求變更帶來程序的變化。這方面對程序員、項目設(shè)計者的要求比較高。
      需求變化不可怕、需求變更也不可怕,可怕的是我們不知道變化及變更的本質(zhì),而是停留在表象;可怕的是我們不知道去擁抱這種變化,而是一味的排斥;可怕的是我們不知道用自己的長項(技術(shù)手段)最大化的去解決這種變化,而是把自己的弱項(業(yè)務(wù))暴露在客戶面前。

    posted @ 2014-11-26 14:49 順其自然EVO 閱讀(244) | 評論 (0)編輯 收藏

    我調(diào)過的最難調(diào)的Bug

     每個程序員都有些不畏死亡決戰(zhàn)猛獸的英雄事跡。以下這些是我的。
      內(nèi)存沖突
      畢業(yè)不到半年,拿著剛到手的文憑,我在Lexmark公司的一個嵌入式Linux固件開發(fā)團(tuán)隊中負(fù)責(zé)追蹤一個內(nèi)存沖突的問題。因為內(nèi)存沖突的原因和問題表象總是相差非常大,所以這類問題很難調(diào)。有可能是因為緩存溢出,也有可能是指針未初始化,或是指針被多次free,亦或是某處的DMA錯誤,但是你所見的卻是一堆神秘的問題:掛起、指令未定義、打印錯誤,以及未處理的內(nèi)核錯誤。這些都非常頻繁,內(nèi)存沖突看上去似乎是隨機(jī)出現(xiàn)又很難重現(xiàn)。
      要調(diào)試這種問題,第一步是可重現(xiàn)問題。在我們奇跡般地找到這樣一個場景之后,故事開始變得好玩起來。
      當(dāng)時,我們發(fā)現(xiàn)在運行時因內(nèi)存沖突而產(chǎn)生的程序崩潰每幾百小時就會出現(xiàn)一次。之后有一天有人發(fā)現(xiàn)一個特別的打印任務(wù)會產(chǎn)生內(nèi)存沖突從而在幾分鐘之內(nèi)就使程序崩潰。我從來不知道為什么這個打印任務(wù)會產(chǎn)生這個問題。現(xiàn)在,我們就可以進(jìn)一步做些什么了。
      調(diào)試
      這個問題可重現(xiàn)之后,我就開始尋找崩潰中出現(xiàn)的模式。最引人注意的是未定義指令和內(nèi)核錯誤,它們差不多三分之一的時間就會發(fā)生一次。未定義指令的地址是一個合理的內(nèi)核代碼地址,但是CPU讀到的這個指令卻不是我們期望出現(xiàn)的。這就很簡單了,可能是有人不小心寫了這些指令。把這些未定義指令的句柄打印出來之后,我可以看到這些錯誤的指令所在位置的周邊內(nèi)存的狀態(tài)。
      在做了大量失敗的將更多的代碼排除出崩潰的嘗試之后,一個特殊的崩潰漸漸顯現(xiàn)。
      崩潰之王
      這個崩潰解開了所有秘密。當(dāng)時我們用了一個雙核CPU。在這個特殊的崩潰里,首先CPU1在有效的模塊地址范圍內(nèi)收到了一個未處理的內(nèi)核錯誤,而此時它正在嘗試執(zhí)行模塊代碼,這段代碼可能是一個沖突的頁表或是一個無效TLB。而正在處理這個錯誤時,CPU0在內(nèi)核地址空間內(nèi)收到了一個非法的指令陷阱。
      以下是從修改后的未定義指令句柄中打印出來的數(shù)據(jù)(已轉(zhuǎn)為物理地址,括號中是出錯地址)
      undefined instruction: pc=0018abc4
      0018aba0: e7d031a2 e1b03003 1a00000e e2822008
      0018abb0: e1520001 3afffff9 e1a00001 e1a0f00e
      0018abc0: 0bd841e6 (ceb3401c) 00000004 00000001
      0018abd0: 0d066010 5439541b 49fa30e7 c0049ab8
      0018abe0: e2822001 eafffff1 e2630000 e0033000
      0018abf0: e16f3f13 e263301f e0820003 e1510000
      以下是內(nèi)存域應(yīng)該顯示的數(shù)據(jù):
      0018aba0: e7d031a2 e1b03003 1a00000e e2822008
      0018abb0: e1520001 3afffff9 e1a00001 e1a0f00e
      0018abc0: e3310000 (0afffffb) e212c007 0afffff3
      0018abd0: e7d031a2 e1b03c33 1a000002 e3822007
      0018abe0: e2822001 eafffff1 e2630000 e0033000
      0018abf0: e16f3f13 e263301f e0820003 e1510000
      確切地來說,只有一行緩存(中間那32byte)是有沖突的。一個同事指出沖突行中0x49fa30e7這個字是一個魔術(shù)cookie,它標(biāo)記了系統(tǒng)中一個特殊環(huán)形緩沖區(qū)的入口。入口值的最后一個字永遠(yuǎn)是一個時間戳,所以0x5439541b是上一個入口的時間戳。我決定去讀取這個環(huán)形緩沖的內(nèi)容,但它現(xiàn)在掛在一個不可執(zhí)行的KGDB提示那了。機(jī)器現(xiàn)在跟死了一樣。
    冷啟動攻擊
      為獲取環(huán)形緩沖區(qū)的數(shù)據(jù),我進(jìn)行了一次冷啟動攻擊。我為正在使用的主板搞到了一份概要拷貝,然后發(fā)現(xiàn)CPU的復(fù)位線上連了一塊不受歡迎的板子。我把它短路了,重置CPU而不妨礙DRAM的完整性。然后,我把Boot掛載在引導(dǎo)程序上。
      在引導(dǎo)程序里,我dump到了問題中環(huán)形緩沖區(qū)的內(nèi)容。謝天謝地,這個緩存總是在一個固定的物理地址上被定位到,所以找到它不是問題了。
      通過分析錯誤時間戳周邊的環(huán)形緩沖區(qū),我們發(fā)現(xiàn)了兩個老的cache line。這兩個cache line里有有效數(shù)據(jù),但是在這兩個cache line里的時間戳卻是環(huán)形緩沖區(qū)里之前的時間。
      導(dǎo)致CPU0上未定義指令的cache line與環(huán)形緩沖區(qū)里那兩個老cache line之一相當(dāng)契合,但是這并不說明其他可能的地方也是這樣。我發(fā)現(xiàn)一個決定性的證據(jù)。假設(shè),另一個消失的cache line是導(dǎo)致CPU1上未處理內(nèi)核錯誤的元兇。
      錯置的cache line
      cache line應(yīng)該被寫入0x0ebd2bc0(環(huán)形緩沖區(qū)里的cache line),但是事實上卻寫入了0x0018abc0(沖突的內(nèi)核碼)。這些地址在我們CPU上屬于相同的緩存,它們的位[14:5]的值是相同的。不知為何它們有別名。
      bit   28   24   20   16   12    8    4    0
      |    |    |    |    |    |    |    |
      0x0ebd2bc0 in binary is 0000 1110 1011 1101 0010 1011 1100 0000
      0x0018abc0 in binary is 0000 0000 0001 1000 1010 1011 1100 0000
      一個地址的低5位是cache line(32字節(jié)cache line)里的索引。后10位,即位[14:5],表示緩存集。剩下的17位,即位[31:15],用來表示緩存里當(dāng)前存的是哪個cache line.
      我向我們的CPU供應(yīng)商提交了一個bug報告,之后他們制定了一個解決方案,并在下一版本CPU里修復(fù)了這個bug。
      我期望聽到更多牛掰的此類故事,也期望我自己可以再攢點這樣的。

    posted @ 2014-11-26 14:48 順其自然EVO 閱讀(248) | 評論 (0)編輯 收藏

    如何保證高質(zhì)量的—移動APP的性能最佳實踐

    加速之必要
      不考慮技術(shù),有一件事是肯定的——人們似乎總是希望可以更快。根據(jù)各種各樣的研究,現(xiàn)在用戶只愿意等待一個web應(yīng)用程序加載三秒或更短的時間,超過的話,他們就會變得越來越不耐煩或者干脆換一個應(yīng)用程序。這些高期待不斷被壓到移動web之上;現(xiàn)在還壓到移動App上。就像Web,現(xiàn)今的移動移動app都有它們自己的性能問題并需要做出一些微調(diào)。最新研究表明,過去,在手機(jī)上獲取app時,47%的移動用戶主要是抱怨速度慢且反應(yīng)遲鈍。App在蘋果的app商店上被譴責(zé)“慢得可怕”。對于Facebook的iPhone應(yīng)用程序,38,000條評論中有超過21,000的用戶只給app一星的評價。用戶多數(shù)表示app慢,死機(jī),“一直在加載”。
      “移動app根據(jù)它們在app商店的排名而生存或死亡……排名不佳,用戶采用率就降低”佛里斯特研究公司的MargoVisitacion這么說道。這或許就是為什么80%的品牌iPhone,Android和Blackberry應(yīng)用程序無法達(dá)到1,000的下載量的原因。拙劣的移動app性能直接影響用戶獲取和用戶維系。那么該做些什么以保證你的移動app性能盡可能的強大呢?
      通過捕捉現(xiàn)實中移動app性能“獲得真實信息”
      移動app性能首先,最重要的是:為了真正理解移動app性能,你必須衡量你的真正用戶正在體驗的性能。在數(shù)據(jù)中心的模擬機(jī)上進(jìn)行測試可以有所幫助但是它基本和你的真實終端用戶的真正體驗無關(guān)。你的數(shù)據(jù)中心和你的終端用戶間有許多影響性能的變量因素,包括云,第三方服務(wù)/集成,CDNs,移動瀏覽器和設(shè)備。衡量真實用戶是在巨大的復(fù)雜物上精準(zhǔn)評估性能并確定一個性能提升的基準(zhǔn)線的唯一方法。衡量你的真實用戶體驗的性能可以讓你就移動app(關(guān)鍵參數(shù)方面的,如你客戶使用的所有的地域,設(shè)備和網(wǎng)絡(luò))性能做出報告。
      現(xiàn)在,移動app測試和使用SDKs監(jiān)控以提交本地app可以讓你快速輕松地鳥瞰你所有客戶的移動app性能。
      負(fù)載測試從終端用戶角度看也很重要,尤其是在開始一個app前,綜合測試網(wǎng)絡(luò)可以讓你在不同的條件下評估性能水平。
      理解拙劣性能的商業(yè)影響
      確定移動app性能問題以及它們對轉(zhuǎn)化的影響很重要:比如,你會注意到移動app的響應(yīng)時間增加與轉(zhuǎn)化的減少息息相關(guān)。這樣你就可以進(jìn)行分類,基于一些考慮(如:我的哪些客戶,多少客戶受到影響了)按輕重緩急解決問題。如果一個地區(qū)的流量份額很高但有問題,而另一個地區(qū)的份額較少,那你就知道該優(yōu)先解決哪個性能問題了。
      確保第三方集成有效
      就像web應(yīng)用程序,許多移動app為了給終端用戶提供更豐富更滿意的體驗吸收了大量第三方服務(wù)的內(nèi)容。一個實例便是社交媒體集成,如Twitter就被集成到奧林匹克移動app中了。很不幸,如果你依賴第三方服務(wù)的話,你就會完全受限于他們的性能特點。在使用一個第三方集成的app前,你需要確保集成無縫順利且可以提供你期待的性能。此外,你還要確保一直監(jiān)控著第三方性能且你的app被設(shè)計得可以完好地降級以防第三方的問題。
      讓你的移動APP快起來
      在這個飛速運轉(zhuǎn)的移動app世界有一句格言比任何時候都真——快比慢好。你可以使用一些特定工具和技術(shù)讓你的移動app變得更快,包括以下:
      優(yōu)化緩存–讓你的app數(shù)據(jù)完全脫離網(wǎng)絡(luò)。對于內(nèi)容多的app,設(shè)備上的緩存內(nèi)容可以通過避免移動網(wǎng)絡(luò)和你的內(nèi)容基礎(chǔ)設(shè)施上的過多障礙以提升性能。
      將往返時間最小化–考慮使用一個可以提供無數(shù)能夠加快你的app服務(wù)的CDN,包括減少網(wǎng)絡(luò)延遲的邊緣緩存,網(wǎng)絡(luò)路由優(yōu)化,內(nèi)容預(yù)取,以及更多。
      將有效荷載規(guī)模最小化–專注壓縮,通過使用任意可用的壓縮技術(shù)減少你的數(shù)據(jù)的規(guī)模。確保圖像規(guī)模適合你最要的設(shè)備段。同樣,確保你利用壓縮。如果你有要花很長時間加載的內(nèi)容,那么你可以一點一點兒的加載。你的app可以在加載時使用該內(nèi)容而不是等整個加載完成后才使用它。零售app經(jīng)常使用該技術(shù)。
      優(yōu)化你的本機(jī)代碼–寫得不好或全是bug的代碼也會導(dǎo)致性能問題。在你的代碼上運行軟件或檢查代碼以找出潛在問題。
      優(yōu)化你的后端服務(wù)性能–如果對你的app進(jìn)行了性能測試后你發(fā)現(xiàn)后端服務(wù)是性能削弱的罪魁禍?zhǔn)祝敲茨憔筒坏貌贿M(jìn)行評估并決定該如何加快這些服務(wù)。
      總結(jié)
      智能手機(jī)用戶當(dāng)然也是“快比慢好”,他們期待他們的app可以飛快。幾乎每隔一段時間,移動運營商和智能手機(jī)制造商都要宣布更快的網(wǎng)和設(shè)備,但不幸的是,移動app本身的速度卻跟不上。
      最主要的原因是一組截然相反的目標(biāo)使得實現(xiàn)飛速性能變得很困難。移動app開發(fā)者總希望提升速度的同時可以提供更豐富的體驗。需要更多內(nèi)容和特點能夠快速地覆蓋寬帶,內(nèi)存和計算機(jī)能力。
      本文給出了一個簡短的本地移動app的性能最佳實踐的例子。性能調(diào)整的空間很大,但錯誤的空間同樣也很大。因此,早點測試你的app,絕不要藥聽天由命。記住——快總比慢好。

    posted @ 2014-11-26 14:25 順其自然EVO 閱讀(238) | 評論 (0)編輯 收藏

    Junit使用GroboUtils進(jìn)行多線程測試

     寫過Junit單元測試的同學(xué)應(yīng)該會有感覺,Junit本身是不支持普通的多線程測試的,這是因為Junit的底層實現(xiàn)上,是用System.exit退出用例執(zhí)行的。JVM都終止了,在測試線程啟動的其他線程自然也無法執(zhí)行。JunitCore代碼如下:
    /**
    * Run the tests contained in the classes named in the <code>args</code>.
    * If all tests run successfully, exit with a status of 0. Otherwise exit with a status of 1.
    * Write feedback while tests are running and write
    * stack traces for all failed tests after the tests all complete.
    * @param args names of classes in which to find tests to run
    */
    public static void main(String... args) {
    runMainAndExit(new RealSystem(), args);
    }
    /**
    * Do not use. Testing purposes only.
    * @param system
    */
    public static void runMainAndExit(JUnitSystem system, String... args) {
    Result result= new JUnitCore().runMain(system, args);
    system.exit(result.wasSuccessful() ? 0 : 1);
    }
    RealSystem.java:
    public void exit(int code) {
    System.exit(code);
    }
      所以要想編寫多線程Junit測試用例,就必須讓主線程等待所有子線程執(zhí)行完成后再退出。想到的辦法自然是Thread中的join方法。話又說回來,這樣一個簡單而又典型的需求,難道會沒有第三方的包支持么?通過google,很快就找到了GroboUtils這個Junit多線程測試的開源的第三方的工具包。
      GroboUtils官網(wǎng)下載解壓后 使用 GroboUtils-5\lib\core\GroboTestingJUnit-1.2.1-core.jar 這個即可
      GroboUtils是一個工具集合,里面包含各種測試工具,這里使用的是該工具集中的jUnit擴(kuò)展.
      依賴好Jar包后就可以編寫多線程測試用例了。上手很簡單:
    package com.junittest.threadtest;
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.Hashtable;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import net.sourceforge.groboutils.junit.v1.MultiThreadedTestRunner;
    import net.sourceforge.groboutils.junit.v1.TestRunnable;
    import org.junit.Test;
    public class MutiThreadTest {
    static String[] path = new String[] { "" };
    static Map<String, String> countMap = new Hashtable<String, String>();
    static Map<String, String> countMap2 = new Hashtable<String, String>();
    static Set<String> countSet = new HashSet<String>();
    static List<String> list = new ArrayList<String>();
    @Test
    public void testThreadJunit() throws Throwable {
    //Runner數(shù)組,想當(dāng)于并發(fā)多少個。
    TestRunnable[] trs = new TestRunnable [10];
    for(int i=0;i<10;i++){
    trs[i]=new ThreadA();
    }
    // 用于執(zhí)行多線程測試用例的Runner,將前面定義的單個Runner組成的數(shù)組傳入
    MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(trs);
    // 開發(fā)并發(fā)執(zhí)行數(shù)組里定義的內(nèi)容
    mttr.runTestRunnables();
    }
    private class ThreadA extends TestRunnable {
    @Override
    public void runTest() throws Throwable {
    // 測試內(nèi)容
    myCommMethod2();
    }
    }
    public void myCommMethod2() throws Exception {
    System.out.println("===" + Thread.currentThread().getId() + "begin to execute myCommMethod2");
    for (int i = 0; i <10; i++) {
    int a  = i*5;
    System.out.println(a);
    }
    System.out.println("===" + Thread.currentThread().getId() + "end to execute myCommMethod2");
    }
    }
     運行時需依賴log4j的jar文件,GroboUtils的jar包。
      主要關(guān)注3個類:TestRunnable,TestMonitorRunnable,MultiThreadedTestRunner,全部來自包:net.sourceforge.groboutils.junit.v1.MultiThreadedTestRunner.
      (1) TestRunnable 抽象類,表示一個測試線程,實例需要實現(xiàn)該類的runTest()方法,在該方法中寫自己用的測試代碼.該類繼承了jUnit的junit.framework.Assert類,所以可以在TestRunnable中使用各種Assert方法
      (可惜因為GroboUtils使用的jUnit版本較老,且久未更新,新版本的jUnit中已經(jīng)不推薦使用這個類的方法了).該類實現(xiàn)了Runnable,在run方法中調(diào)用抽象方法runTest().
      (2)   MultiThreadedTestRunner
      這個類相當(dāng)與一個ExecuteService,可以用來執(zhí)行 TestRunnable,構(gòu)造函數(shù)需要傳入TestRunnable數(shù)組,表示需要測試的線程.調(diào)用MultiThreadedTestRunner.runTestRunnables() 方法啟動測試線程,開始執(zhí)行測試.
      這個方法默認(rèn)讓測試線程TestRunnable的run方法最多運行1天,也可以調(diào)用MultiThreadedTestRunner.runTestRunnables(long maxTime) 這個方法,然測試線程TestRunnable最多執(zhí)行 maxTime 毫秒.如果超過maxTime毫秒之后,TestRunnable還沒有執(zhí)行完畢,則TestRunnable會被中斷,并且MultiThreadedTestRunner 會拋出異常,導(dǎo)致測試失敗fail("Threads did not finish within " + maxTime + " milliseconds.").每個TestRunnable中runTest需要能夠控制自己在什么時間自己結(jié)束自己,精確控制測試時間,不要利用上面的maxTime.
      (3) TestMonitorRunnable
      表示監(jiān)控線程,可以讓每一個TestRunnable對應(yīng)一個TestMonitorRunnable,在TestMonitorRunnable中監(jiān)控TestRunnable.TestMonitorRunnable是TestRunnable的子類,提供了一些方便使用的方法.

    posted @ 2014-11-26 14:24 順其自然EVO 閱讀(487) | 評論 (0)編輯 收藏

    僅列出標(biāo)題
    共394頁: First 上一頁 10 11 12 13 14 15 16 17 18 下一頁 Last 
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導(dǎo)航

    統(tǒng)計

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 永久久久免费浮力影院| 国产三级免费电影| 亚洲国产a级视频| 亚洲国产成人久久精品动漫| 亚洲精品亚洲人成在线播放| 一日本道a高清免费播放| 每天更新的免费av片在线观看| 日本一道一区二区免费看| 亚洲va久久久噜噜噜久久男同 | 亚洲国产成人精品无码区在线观看| 亚洲一区二区三区在线| 国产V片在线播放免费无码| 一二三四免费观看在线电影| 久久影视国产亚洲| 亚洲综合一区二区三区四区五区| 中文字幕a∨在线乱码免费看| 好吊妞998视频免费观看在线| 国产精一品亚洲二区在线播放| 亚洲人成未满十八禁网站| 97无码人妻福利免费公开在线视频| 成**人免费一级毛片| 亚洲午夜久久影院| 一进一出60分钟免费视频| 女人毛片a级大学毛片免费| 亚洲国产综合91精品麻豆| 免费国产高清毛不卡片基地 | 日韩亚洲AV无码一区二区不卡| 日韩久久无码免费毛片软件| 无码人妻一区二区三区免费手机| 亚洲动漫精品无码av天堂| 羞羞网站在线免费观看| 国产一卡2卡3卡4卡2021免费观看| 亚洲日韩欧洲无码av夜夜摸| 苍井空亚洲精品AA片在线播放| 国产精品免费精品自在线观看| 亚洲AV无码乱码在线观看富二代| 国产亚洲漂亮白嫩美女在线| 成人免费a级毛片| 精品亚洲成a人片在线观看 | a毛片久久免费观看| 免费国产在线观看不卡|