2.1 查看機器 cpu 的負載html
top -b -n 1 |grep java|awk '{print "VIRT:"$5,"RES:"$6,"cpu:"$9"%","mem:"$10"%"}'
2.2 查找 cpu 佔用率高的線程java
top -p 25603 -H printf 0x%x 25842 jstack 25603 | grep 0x64f2 cat /proc/interrupts
(1)CPU
(2)Memory
(3)IO
(4)Networklinux
能夠從如下幾個方面監控CPU的信息:
(1)中斷;
(2)上下文切換;
(3)可運行隊列;
(4)CPU 利用率。ios
3.1 系統內存nginx
free 命令面試
[root@server ~]# free total used free shared buffers cached Mem: 3266180 3250000 10000 0 201000 3002000 -/+ buffers/cache: 47000 3213000 Swap: 2048276 80160 1968116
這裏的默認顯示單位是 kb。redis
各項指標解釋算法
什麼是buffer/cache?數據庫
page cache數組
page cache 主要用來做爲文件系統上的文件數據的緩存來用,尤爲是針對當進程對文件有 read/write 操做的時候。
若是你仔細想一想的話,做爲能夠映射文件到內存的系統調用:mmap是否是很天然的也應該用到 page cache?在當前的系統實現裏,page cache 也被做爲其它文件類型的緩存設備來用,因此事實上 page cache 也負責了大部分的塊設備文件的緩存工做。
buffer cache
buffer cache 主要用來在系統對塊設備進行讀寫的時候,對塊進行數據緩存的系統來使用。這意味着某些對塊的操做會使用 buffer cache 進行緩存,好比咱們在格式化文件系統的時候。
通常狀況下兩個緩存系統是一塊兒配合使用的,好比當咱們對一個文件進行寫操做的時候,page cache 的內容會被改變,而 buffer cache 則能夠用來將 page 標記爲不一樣的緩衝區,並記錄是哪個緩衝區被修改了。這樣,內核在後續執行髒數據的回寫(writeback)時,就不用將整個 page 寫回,而只須要寫回修改的部分便可。
在當前的內核中,page cache 是針對內存頁的緩存,說白了就是,若是有內存是以page進行分配管理的,均可以使用page cache做爲其緩存來管理使用。
固然,不是全部的內存都是以頁(page)進行管理的,也有不少是針對塊(block)進行管理的,這部份內存使用若是要用到 cache 功能,則都集中到 buffer cache中來使用。(從這個角度出發,是否是buffer cache更名叫作block cache更好?)然而,也不是全部塊(block)都有固定長度,系統上塊的長度主要是根據所使用的塊設備決定的,而頁長度在X86 上不管是 32位仍是 64位都是 4k。
3.2 進程內存
3.2.1 進程內存統計
/proc[pid]status
經過/proc/status能夠查看進程的內存使用狀況,包括虛擬內存大小(VmSize),物理內存大小(VmRSS),數據段大小(VmData),棧的大小(VmStk),代碼段的大小(VmExe),共享庫的代碼段大小(VmLib)等等。
Name: gedit /*進程的程序名*/ State: S (sleeping) /*進程的狀態信息,具體參見http://blog.chinaunix.net/u2/73528/showart_1106510.html*/ Tgid: 9744 /*線程組號*/ Pid: 9744 /*進程pid*/PPid: 7672 /*父進程的pid*/ TracerPid: 0 /*跟蹤進程的pid*/ VmPeak: 60184 kB /*進程地址空間的大小*/ VmSize: 60180 kB /*進程虛擬地址空間的大小reserved_vm:進程在預留或特殊的內存間的物理頁*/ VmLck: 0 kB /*進程已經鎖住的物理內存的大小.鎖住的物理內存不能交換到硬盤*/ VmHWM: 18020 kB /*文件內存映射和匿名內存映射的大小*/ VmRSS: 18020 kB /*應用程序正在使用的物理內存的大小,就是用ps命令的參數rss的值 (rss)*/ VmData: 12240 kB /*程序數據段的大小(所佔虛擬內存的大小),存放初始化了的數據*/ VmStk: 84 kB /*進程在用戶態的棧的大小*/ VmExe: 576 kB /*程序所擁有的可執行虛擬內存的大小,代碼段,不包括任務使用的庫 */ VmLib: 21072 kB /*被映像到任務的虛擬內存空間的庫的大小*/ VmPTE: 56 kB /*該進程的全部頁表的大小*/ Threads: 1 /*共享使用該信號描述符的任務的個數*/
3.2.2 JVM 內存分配
java內存組成介紹:堆(Heap)和非堆(Non-heap)內存
按照官方的說法:「Java 虛擬機具備一個堆,堆是運行時數據區域,全部類實例和數組的內存均今後處分配。堆是在 Java 虛擬機啓動時建立的。」 「在JVM中堆以外的內存稱爲非堆內存(Non-heap memory)」。
能夠看出JVM主要管理兩種類型的內存:堆和非堆。
簡單來講堆就是Java代碼可及的內存,是留給開發人員使用的;非堆就是JVM留給本身用的。
因此方法區、JVM內部處理或優化所需的內存(如JIT編譯後的代碼緩存)、每一個類結構(如運行時常數池、字段和方法數據)以及方法和構造方法 的代碼都在非堆內存中。
-XX:+UseConcMarkSweepGC -X:+CMSPermGenSweepingEnabled -X:+CMSClassUnloadingEnabled,若是不須要移除而Perm Generation空間不夠,能夠加大一點:-X:PermSize=256M -X:MaxPermSize=512M
1.方法區
也稱」永久代」 、「非堆」,它用於存儲虛擬機加載的類信息、常量、靜態變量、是各個線程共享的內存區域。默認最小值爲 16 MB,最大值爲 64 MB,能夠經過-XX: PermSize 和 -XX: MaxPermSize 參數限制方法區的大小。
運行時常量池:是方法區的一部分,Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項信息是常量池,用於存放編譯器生成的各類符號引用,這部份內容將在類加載後放到方法區的運行時常量池中。
2.虛擬機棧
描述的是java 方法執行的內存模型:每一個方法被執行的時候 都會建立一個「棧幀」用於存儲局部變量表(包括參數)、操做棧、方法出口等信息。
每一個方法被調用到執行完的過程,就對應着一個棧幀在虛擬機棧中從入棧到出棧的過程。聲明週期與線程相同,是線程私有的。
局部變量表存放了編譯器可知的各類基本數據類型(boolean、byte、char、short、int、float、long、double)、對象引用(引用指針,並不是對象自己),其中64位長度的long和double類型的數據會佔用2個局部變量的空間,其他數據類型只佔1個。
局部變量表所需的內存空間在編譯期間完成分配,當進入一個方法時,這個方法須要在棧幀中分配多大的局部變量是徹底肯定的,在運行期間棧幀不會改變局部變量表的大小空間。
3.本地方法棧
與虛擬機棧基本相似,區別在於虛擬機棧爲虛擬機執行的java方法服務,而本地方法棧則是爲Native方法服務。
4.堆
也叫作java 堆、GC堆是java虛擬機所管理的內存中最大的一塊內存區域,也是被各個線程共享的內存區域,在JVM啓動時建立。
該內存區域存放了對象實例及數組(全部 new 的對象)。其大小經過 -Xms (最小值) 和 -Xmx (最大值) 參數設置,-Xms爲 JVM 啓動時申請的最小內存,默認爲操做系統物理內存的 1/64 但小於 1G;
-Xmx 爲 JVM 可申請的最大內存,默認爲物理內存的1/4但小於 1G,默認當空餘堆內存小於 40% 時,JVM 會增大 Heap 到 -Xmx 指定的大小,可經過 -XX:MinHeapFreeRation= 來指定這個比列;
當空餘堆內存大於70%時,JVM 會減少 heap 的大小到 -Xms 指定的大小,可經過XX:MaxHeapFreeRation= 來指定這個比列,對於運行系統,爲避免在運行時頻繁調整 Heap 的大小,一般 -Xms 與 -Xmx 的值設成同樣。
因爲如今收集器都是採用分代收集算法,堆被劃分爲新生代和老年代。新生代主要存儲新建立的對象和還沒有進入老年代的對象。老年代存儲通過屢次新生代GC(Minor GC)任然存活的對象。
5.程序計數器
是最小的一塊內存區域,它的做用是當前線程所執行的字節碼的行號指示器,在虛擬機的模型裏,字節碼解釋器工做時就是經過改變這個計數器的值來選取下一條須要執行的字節碼指令,分支、循環、異常處理、線程恢復等基礎功能都須要依賴計數器完成。
3.2.3 直接內存
直接內存並非虛擬機內存的一部分,也不是Java虛擬機規範中定義的內存區域。jdk1.4中新加入的NIO,引入了通道與緩衝區的IO方式,它能夠調用Native方法直接分配堆外內存,這個堆外內存就是本機內存,不會影響到堆內存的大小。
3.2.4 JVM 內存分析
查看 JVM 堆內存狀況
jmap -heap [pid]
[root@server ~]$ jmap -heap 837 Attaching to process ID 837, please wait... Debugger attached successfully. Server compiler detected. JVM version is 24.71-b01 using thread-local object allocation. Parallel GC with 4 thread(s)//GC 方式 Heap Configuration: //堆內存初始化配置 MinHeapFreeRatio = 0 //對應jvm啓動參數-XX:MinHeapFreeRatio設置JVM堆最小空閒比率(default 40) MaxHeapFreeRatio = 100 //對應jvm啓動參數 -XX: MaxHeapFreeRatio設置JVM堆最大空閒比率(default 70) MaxHeapSize = 2082471936 (1986.0MB) //對應jvm啓動參數-XX: MaxHeapSize=設置JVM堆的最大大小 NewSize = 1310720 (1.25MB)//對應jvm啓動參數-XX:NewSize=設置JVM堆的‘新生代’的默認大小 MaxNewSize = 17592186044415 MB//對應jvm啓動參數-XX:MaxNewSize=設置JVM堆的‘新生代’的最大大小 OldSize = 5439488 (5.1875MB)//對應jvm啓動參數-XX:OldSize=<value>:設置JVM堆的‘老生代’的大小 NewRatio = 2 //對應jvm啓動參數-XX:NewRatio=:‘新生代’和‘老生代’的大小比率 SurvivorRatio = 8 //對應jvm啓動參數-XX:SurvivorRatio=設置年輕代中Eden區與Survivor區的大小比值 PermSize = 21757952 (20.75MB) //對應jvm啓動參數-XX:PermSize=<value>:設置JVM堆的‘永生代’的初始大小 MaxPermSize = 85983232 (82.0MB)//對應jvm啓動參數-XX:MaxPermSize=<value>:設置JVM堆的‘永生代’的最大大小 G1HeapRegionSize = 0 (0.0MB) Heap Usage://堆內存使用狀況 PS Young Generation Eden Space://Eden區內存分佈 capacity = 33030144 (31.5MB)//Eden區總容量 used = 1524040 (1.4534378051757812MB) //Eden區已使用 free = 31506104 (30.04656219482422MB) //Eden區剩餘容量 4.614088270399305% used //Eden區使用比率 From Space: //其中一個Survivor區的內存分佈 capacity = 5242880 (5.0MB)used = 0 (0.0MB)free = 5242880 (5.0MB) 0.0% used To Space: //另外一個Survivor區的內存分佈 capacity = 5242880 (5.0MB) used = 0 (0.0MB)free = 5242880 (5.0MB) 0.0% used PS Old Generation //當前的Old區內存分佈 capacity = 86507520 (82.5MB) used = 0 (0.0MB) free = 86507520 (82.5MB) 0.0% used PS Perm Generation//當前的 「永生代」 內存分佈 capacity = 22020096 (21.0MB) used = 2496528 (2.3808746337890625MB) free = 19523568 (18.619125366210938MB) 11.337498256138392% used 670 interned Strings occupying 43720 bytes.
關於這裏的幾個generation網上資料一大把就不細說了,這裏算一下求和能夠得知前者總共給Java環境分配了644M的內存,而ps輸出的VSZ和RSS分別是7.4G和2.9G,這究竟是怎麼回事呢?
前面jmap輸出的內容裏,MaxHeapSize 是在命令行上配的,-Xmx4096m,這個java程序能夠用到的最大堆內存。
VSZ是指已分配的線性空間大小,這個大小一般並不等於程序實際用到的內存大小,產生這個的可能性不少,好比內存映射,共享的動態庫,或者向系統申請了更多的堆,都會擴展線性空間大小,要查看一個進程有哪些內存映射,可使用 pmap 命令來查看:
pmap -x [pid]
[root@server ~]$ pmap -x 837 837: java Address Kbytes RSS Dirty Mode Mapping 0000000040000000 36 4 0 r-x-- java 0000000040108000 8 8 8 rwx-- java 00000000418c9000 13676 13676 13676 rwx-- [ anon ] 00000006fae00000 83968 83968 83968 rwx-- [ anon ] 0000000700000000 527168 451636 451636 rwx-- [ anon ] 00000007202d0000 127040 0 0 ----- [ anon ] ...... 00007f55ee124000 4 4 0 r-xs- az.png 00007fff017ff000 4 4 0 r-x-- [ anon ] fffffffff600000 4 0 0 r-x-- [ anon ] ---------------- ------ ------ ------ total kB 7796020 3037264 3023928
這裏能夠看到不少anon,這些表示這塊內存是由mmap分配的。
RSZ是Resident Set Size,常駐內存大小,即進程實際佔用的物理內存大小, 在如今這個例子當中,RSZ和實際堆內存佔用差了2.3G,這2.3G的內存組成分別爲:
查看 JVM 堆各個分區的內存狀況
jstat -gcutil [pid]
[root@server ~]$ jstat -gcutil 837 1000 20 S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 80.43 24.62 87.44 98.29 7101 119.652 40 19.719 139.371 0.00 80.43 33.14 87.44 98.29 7101 119.652 40 19.719 139.371
分析 JVM 堆內存中的對象
查看存活的對象統計
jmap -histo:live [pid]
dump 內存
jmap -dump:format=b,file=heapDump [pid]
而後用jhat命令能夠參看
jhat -port 5000 heapDump
在瀏覽器中訪問:http://localhost:5000/ 查看詳細信息
4.1 響應時間(RT)
響應時間是指系統對請求做出響應的時間。直觀上看,這個指標與人對軟件性能的主觀感覺是很是一致的,由於它完整地記錄了整個計算機系統處理請求的時間。
因爲一個系統一般會提供許多功能,而不一樣功能的處理邏輯也千差萬別,於是不一樣功能的響應時間也不盡相同,甚至同一功能在不一樣輸入數據的狀況下響應時間也不相同。
因此,在討論一個系統的響應時間時,人們一般是指該系統全部功能的平均時間或者全部功能的最大響應時間。
固然,每每也須要對每一個或每組功能討論其平均響應時間和最大響應時間。
對於單機的沒有併發操做的應用系統而言,人們廣泛認爲響應時間是一個合理且準確的性能指標。須要指出的是,響應時間的絕對值並不能直接反映軟件的性能的高低,軟件性能的高低實際上取決於用戶對該響應時間的接受程度。
對於一個遊戲軟件來講,響應時間小於100毫秒應該是不錯的,響應時間在1秒左右可能屬於勉強能夠接受,若是響應時間達到3秒就徹底難以接受了。
而對於編譯系統來講,完整編譯一個較大規模軟件的源代碼可能須要幾十分鐘甚至更長時間,但這些響應時間對於用戶來講都是能夠接受的。
4.2 吞吐量(Throughput)
吞吐量是指系統在單位時間內處理請求的數量。對於無併發的應用系統而言,吞吐量與響應時間成嚴格的反比關係,實際上此時吞吐量就是響應時間的倒數。
前面已經說過,對於單用戶的系統,響應時間(或者系統響應時間和應用延遲時間)能夠很好地度量系統的性能,但對於併發系統,一般須要用吞吐量做爲性能指標。
對於一個多用戶的系統,若是隻有一個用戶使用時系統的平均響應時間是t,當有你n個用戶使用時,每一個用戶看到的響應時間一般並非n×t,而每每比n×t小不少(固然,在某些特殊狀況下也可能比n×t大,甚至大不少)。
這是由於處理每一個請求須要用到不少資源,因爲每一個請求的處理過程當中有許多不走難以併發執行,這致使在具體的一個時間點,所佔資源每每並很少。也就是說在處理單個請求時,在每一個時間點均可能有許多資源被閒置,當處理多個請求時,若是資源配置合理,每一個用戶看到的平均響應時間並不隨用戶數的增長而線性增長。
實際上,不一樣系統的平均響應時間隨用戶數增長而增加的速度也不大相同,這也是採用吞吐量來度量併發系統的性能的主要緣由。
通常而言,吞吐量是一個比較通用的指標,兩個具備不一樣用戶數和用戶使用模式的系統,若是其最大吞吐量基本一致,則能夠判斷兩個系統的處理能力基本一致。
4.3 併發用戶數
併發用戶數是指系統能夠同時承載的正常使用系統功能的用戶的數量。與吞吐量相比,併發用戶數是一個更直觀但也更籠統的性能指標。
實際上,併發用戶數是一個很是不許確的指標,由於用戶不一樣的使用模式會致使不一樣用戶在單位時間發出不一樣數量的請求。
一網站系統爲例,假設用戶只有註冊後才能使用,但註冊用戶並非每時每刻都在使用該網站,所以具體一個時刻只有部分註冊用戶同時在線,在線用戶就在瀏覽網站時會花不少時間閱讀網站上的信息,於是具體一個時刻只有部分在線用戶同時向系統發出請求。
這樣,對於網站系統咱們會有三個關於用戶數的統計數字:註冊用戶數、在線用戶數和同時發請求用戶數。因爲註冊用戶可能長時間不登錄網站,使用註冊用戶數做爲性能指標會形成很大的偏差。而在線用戶數和同事發請求用戶數均可以做爲性能指標。
相比而言,以在線用戶做爲性能指標更直觀些,而以同時發請求用戶數做爲性能指標更準確些。
4.4 QPS每秒查詢率(Query Per Second)
每秒查詢率QPS是對一個特定的查詢服務器在規定時間內所處理流量多少的衡量標準,在因特網上,做爲域名系統服務器的機器的性能常常用每秒查詢率來衡量。對應fetches/sec,即每秒的響應請求數,也便是最大吞吐能力。
從以上概念來看吞吐量和響應時間是衡量系統性能的重要指標,QPS雖然和吞吐量的計量單位不一樣,但應該是成正比的,任何一個指標均可以含量服務器的並行處理能力。固然Throughput更關心數據量,QPS更關心處理筆數。
CPU Load Average < CPU個數 核數 0.7
Context Switch Rate
就是Process(Thread)的切換,若是切換過多,會讓CPU忙於切換,也會致使影響吞吐量。
《高性能服務器架構 》這篇文章的第2節就是說的是這個問題的。
究竟多少算合適?google 了一大圈,沒有一個確切的解釋。
Context Switch大致上由兩個部分組成:中斷和進程(包括線程)切換,一次中斷(Interrupt)會引發一次切換,進程(線程)的建立、激活之類的也會引發一次切換。CS的值也和TPS(Transaction Per Second)相關的,假設每次調用會引發N次CS,那麼就能夠得出
Context Switch Rate = Interrupt Rate + TPS* N
CSR減掉IR,就是進程/線程的切換,假如主進程收到請求交給線程處理,線程處理完畢歸還給主進程,這裏就是2次切換。
也能夠用CSR、IR、TPS的值代入公式中,得出每次事物致使的切換數。所以,要下降CSR,就必須在每一個TPS引發的切換上下功夫,只有N這個值降下去,CSR就能下降,理想狀況下N=0,可是不管如何若是N >= 4,則要好好檢查檢查。另外網上說的CSR<5000,我認爲標準不應如此單一。
這三個指標在 LoadRunner 中能夠監控到;另外,在 linux 中,也能夠用 vmstat 查看r(Load Arerage),in(Interrupt)和cs(Context Switch)
uptime
dmesg
top
查看進程活動狀態以及一些系統情況
vmstat
查看系統狀態、硬件和系統信息等
iostat
查看CPU 負載,硬盤情況
sar
綜合工具,查看系統情況
mpstat
查看多處理器情況
netstat
查看網絡情況
iptraf
實時網絡情況監測
tcpdump
抓取網絡數據包,詳細分析
mpstat
查看多處理器情況
tcptrace
數據包分析工具
netperf
網絡帶寬工具
dstat
綜合工具,綜合了 vmstat, iostat, ifstat, netstat 等多個信息
Reference
*http://tmq.qq.com/2016/07/it-...
https://www.ibm.com/developer...http://www.oracle.com/technetwork/java/javase/index-137495.htmlhttp://www.hollischuang.com/a...
原文爲《服務調優》
歡迎你們關注個人微信公衆號【民工哥技術之路】,最新整理的 2TB 技術乾貨:包括架構師實戰教程、大數據、Docker容器、系統運維、數據庫、redis、MogoDB、電子書、Java基礎課程、Java實戰項目、ELK Stack、機器學習、BAT面試精講視頻等。只需在「 民工哥技術之路」微信公衆號對話框回覆關鍵字:1024便可獲取所有資料。