1. 程式人生 > >效能調優從哪裡入手

效能調優從哪裡入手

    說到效能調優,給人的感覺往往都是修煉有成的專家幹得事了,對於我們這些菜鳥還是想也不要想了,做好分內事,不出現紕漏就OK了。對於這種觀點我表示嚴肅的否決!那想學習效能調優的童鞋應該從哪裡下手呢?接下來就讓我們來談談關於效能調優你所忽視的一些常識。

一、程式碼;
前文講過“華為Java程式設計軍規,每季度程式碼驗收標準”這個標準是衡量程式碼本身的缺陷,也是衡量一個研發人員本身的價值。程式碼是效能調優中的一粒分子,分子雖小但經過上億次的分裂也會變成黑洞,所以程式碼本身的缺陷也是我們效能調優的主因之一。

軍規一:【避免在程式中使用魔鬼數字,必須用有意義的常量來標識。】

軍規二:【明確方法的功能,一個方法僅完成一個功能。】

軍規三:【方法引數不能超過5個】

軍規四:【方法調用盡量不要返回null,取而代之以丟擲異常,或是返回特例物件(SPECIAL CASE object,SPECIAL CASE PATTERN);對於以集合或陣列型別作為返回值的方法,取而代之以空集合或0長度陣列。】

軍規五:【在進行資料庫操作或IO操作時,必須確保資源在使用完畢後得到釋放,並且必須確保釋放操作在finally中進行。】

軍規六:【異常捕獲不要直接catch (Exception ex) ,應該把異常細分處理。】

軍規七:【對於if „ else if „(後續可能有多個else if …)這種型別的條件判斷,最後必須包含一個else分支,避免出現分支遺漏造成錯誤;每個switch-case語句都必須保證有default,避免出現分支遺漏,造成錯誤。】

軍規八:【覆寫物件的equals()方法時必須同時覆寫hashCode()方法。】

軍規九:【禁止迴圈中建立新執行緒,儘量使用執行緒池。】

軍規十:【在進行精確計算時(例如:貨幣計算)避免使用float和double,浮點數計算都是不精確的,必須使用BigDecimal或將浮點數運算轉換為整型運算。】

二、基準;
基準環境,基準負載和基準指標,這是前提也是標準更是依據。沒有人能保證每次執行的指標就是真實有效的,今天提交個版本明天升級個環境這是我們不能容忍的。怎麼才能基準?什麼又叫基準?正式的標準的穩定版本就是基準。也只有基準了,我們才能發現問題。

三、硬體;
硬體環境的調整:主要是對系統執行的硬體環境進行調整,包括改變系統執行的伺服器、主機裝置環境(改用具有更高效能的機器,或是調整某些伺服器的實體記憶體總量,CPU數量等),調整網路環境(更換快速的網路裝置,或是採用更高頻寬的組網技術)等。

注:“工作經驗總結:百萬資料引發的效能瓶頸問題”http://www.cnblogs.com/Javame/p/3510641.html

四、系統;
系統設定的調整:主要是對系統執行的基礎平臺設定進行調整,例如,根據應用需要調整UNIX系統的核心引數,調整資料庫的記憶體池大小,調整應用伺服器使用的記憶體大小,或是採用更高版本的JVM環境等;

注:推薦常有效能測試工具

  效能測試工具:LR、kylinPET

  系統監控工具:nmon 或Linux(top sar)等自帶命令

  強烈推薦:Spotlight.On.Oracle 非常不錯的工具,誰用誰知道! ^^

五、軟體;
應用框架的調整:主要是對應用實現本身進行調整,包括選用新的架構、採用新的資料訪問或是修改業務邏輯的實現方式等。

注:說到架構我現在正在研究阿里巴巴的Dubbo,有興趣的朋友可以一起探討探討。

“通過dubbo暴露介面呼叫方法,及基於zookeeper的dubbo涉及配置檔案”http://www.cnblogs.com/Javame/p/3645481.html“基於ZooKeeper的Dubbo註冊中心”http://www.cnblogs.com/Javame/p/3632708.html“最近專案用到Dubbo框架,臨時抱佛腳分享一下共探討”http://www.cnblogs.com/Javame/p/3632473.html

 六、再說系統

ulimit -a 用來顯示當前的各種使用者程序限制。
Linux對於每個使用者,系統限制其最大程序數。為提高效能,可以根據裝置資源情況,設定各linux 使用者的最大程序數,下面我把某linux使用者的最大程序數設為10000個:

ulimit -u 10000

對於需要做許多 socket 連線並使它們處於開啟狀態的 Java 應用程式而言,最好通過使用 ulimit -n xx 修改每個程序可開啟的檔案數,預設值是 1024。
ulimit -n 4096 將每個程序可以開啟的檔案數目加大到4096,預設為1024
其他建議設定成無限制(unlimited)的一些重要設定是:

資料段長度:ulimit -d unlimited
最大記憶體大小:ulimit -m unlimited
堆疊大小:ulimit -s unlimited
CPU 時間:ulimit -t unlimited
虛擬記憶體:ulimit -v unlimited

暫時地,適用於通過 ulimit 命令登入 shell 會話期間。
永久地,通過將一個相應的 ulimit 語句新增到由登入 shell 讀取的檔案中, 即特定於 shell 的使用者資原始檔,如:

1)、解除 Linux 系統的最大程序數和最大檔案開啟數限制:

vi /etc/security/limits.conf
# 新增如下的行    * soft noproc 11000
* hard noproc 11000
* soft nofile 4100
* hard nofile 4100


說明:* 代表針對所有使用者
noproc 是代表最大程序數
nofile 是代表最大檔案開啟數

2)、讓 SSH 接受 Login 程式的登入,方便在 ssh 客戶端檢視 ulimit -a 資源限制:
a、vi /etc/ssh/sshd_config
把 UserLogin 的值改為 yes,並把 # 註釋去掉
b、重啟 sshd 服務:
/etc/init.d/sshd restart
3)、修改所有 linux 使用者的環境變數檔案:

vi /etc/profile
ulimit -u 10000ulimit -n 4096ulimit -d unlimited
ulimit -m unlimited
ulimit -s unlimited
ulimit -t unlimited
ulimit -v unlimited

/**************************************

有時候在程式裡面需要開啟多個檔案,進行分析,系統一般預設數量是1024,(用ulimit -a可以看到)對於正常使用是夠了,但是對於程式來講,就太少了。

修改2個檔案。

1./etc/security/limits.conf
vi /etc/security/limits.conf
加上: * soft nofile 8192
* hard nofile 204802./etc/pam.d/login
session required /lib/security/pam_limits.so


另外確保/etc/pam.d/system-auth檔案有下面內容
session required /lib/security/$ISA/pam_limits.so
這一行確保系統會執行這個限制。

3.一般使用者的.bash_profile
#ulimit -n 1024
重新登陸ok

對於solaris

其實在系統裡面有這樣一個命令ulimit,以下是ulimit -a執行的結果:

time(seconds) unlimited
file(blocks) unlimited
data(kbytes) unlimited
stack(kbytes) 8192coredump(blocks) unlimited
nofiles(descriptors) 1024memory(kbytes) unlimited

其中nofiles就是檔案描述符的變數值,該值受rlim_fd_cur這個引數的影響,可以用ulimit -n number命令來修改。但不管怎麼改,程式仍然不能突破fd=256的限制。在Solaris Tunable Parameters Reference Manua這本書裡面能查到以下的資料:

A 32-bit program using standard I/O is limited to 256 file descriptors。
A 64-bit program using standard I/O can use up to 2 billion descriptors。
這也就是說32位的程式是沒有辦法突破這個限制的,只有64位的程式才能使用高達2億個檔案描述符,SUN的軟硬體在很早以前就實現了64位的架構,現在唯一要解決的就是將程式編譯成64位程式,為了生成64位程式,就必須要有64位的編譯器(其實不是這樣的),如果你去www.sunfreeware.com下載64位編譯器gcc,網站上沒有特別註明是64位的gcc,但是會有個意外的收穫,就是該軟體的說明裡面註明了只要在用gcc編譯的時候加上-m64的option就能生成64位程式了。

於是用gcc -m64去編譯生成一個64位程式後,用ulimit -n 102400將number of fd設成很大的情況下,所有問題迎刃而解,再也不存在檔案描述符不夠用的情況。

在/etc/system檔案設定rlimi_fc_max和rlim_fd_cur格式如下:

  • set hard limit on file descriptors
    set rlim_fd_max = 4096
  • set soft limit on file descriptors
    set rlim_fd_cur = 1024
    命令ulimit使用格式如下:

usage: ulimit [ -HSacdfnstv ] [ limit ]
ulimit -a是顯示各引數的設定值,ulimit -n是用來設定fd的最大值的。


修改檔案描述符限制

Solaris有兩個引數控制程序可開啟的檔案描述符:rlim_fd_max,rlim_fd_cur。前者修改是個硬設定,修改需要許可權,後者是個軟設定,使用者可以limit或者setrlimit() 修改,該值最大不能超過前者。一般我們在/etc/system裡修改這兩個引數

set rlim_fd_max = 65535

set rlim_fd_cur = 65535

==========================

ulimit 用於shell啟動程序所佔用的資源。

可以使用該命令檢視程序佔用資源的情況。

使用方法:ulimit [-acdfHlmnpsStvw] [size]

-H 設定硬體資源限制.
-S 設定軟體資源限制.
-a 顯示當前所有的資源限制.
-c size:設定core檔案的最大值.單位:blocks
-d size:設定資料段的最大值.單位:kbytes
-f size:設定建立檔案的最大值.單位:blocks
-l size:設定在記憶體中鎖定程序的最大值.單位:kbytes
-m size:設定可以使用的常駐記憶體的最大值.單位:kbytes
-n size:設定核心可以同時開啟的檔案描述符的最大值.單位:n
-p size:設定管道緩衝區的最大值.單位:kbytes
-s size:設定堆疊的最大值.單位:kbytes
-t size:設定CPU使用時間的最大上限.單位:seconds
-v size:設定虛擬記憶體的最大值.單位:kbytes 5
1]在RH8的環境檔案/etc/profile中,我們可以看到系統是如何配置ulimit的:

#grep ulimit /etc/profile
ulimit -S -c 0 > /dev/null 2>&1 (輸出重定向,正常輸出和異常輸出都忽略)

這條語句設定了對軟體資源和對core檔案大小的設定
2]如果我們想要對由shell建立的檔案大小作些限制,如:

#ll h-rw-r–r-- 1 lee lee 150062 7月 22 02:39 h
#ulimit -f 100 #設定建立檔案的最大塊(一塊=512位元組)
#cat h>newh
File size limit exceeded
#ll newh-rw-r–r-- 1 lee lee 51200 11月 8 11:47 newh

檔案h的大小是150062位元組,而我們設定的建立檔案的大小是512位元組x100塊=51200位元組
當然系統就會根據你的設定生成了51200位元組的newh檔案.
Linux效能調優基本策略設定3]可以像例項1]一樣,把你要設定的ulimit放在/etc/profile這個環境檔案中.
如果針對所有使用者設定,可在/etc/security/limits.conf 設定.

copyright by ixdba.

簡述以上五點,你可以循序漸進依步調優,也可以著重調優,但有一點你卻要牢記,那就是軟體工程的概論,有一才有二,有因才有果,到頭來千萬不要揀了芝麻丟了西瓜