English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
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ù)點。
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
原理: 就是原理很分頁原理一樣! 選取一定數(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); } |
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
高高興興迎接新的產(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)該還有其他的方法,歡迎補充。
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
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)改變了,也只用改工廠,不用改程序.
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
如何使用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 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(); } } } |
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
項目又延期了,老板恨恨的批評了整個項目組,投入了那么多,產(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ù))暴露在客戶面前。
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
每個程序員都有些不畏死亡決戰(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。
我期望聽到更多牛掰的此類故事,也期望我自己可以再攢點這樣的。
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
加速之必要
不考慮技術(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,絕不要藥聽天由命。記住——快總比慢好。
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
寫過
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的子類,提供了一些方便使用的方法.
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters