昨天開了個頭
博文連結:
今天,來說說 什麼樣的代碼才是壞代碼,怎麼來找出這些壞代碼。
不少猿在吐槽爛代碼。但是我們今天說的不是爛代碼,壞代碼隻需要改動很小的一部分,把它的壞的地方改掉,他依然是好代碼
。而爛代碼,隻有重新寫過了,才會讓你覺得渾身輕松,壓力瞬間釋放,而且在寫之前你還得花90%的時間去看懂它。是以我說改掉壞代碼,因為隻有壞代碼才能改,而爛代碼是用來看。我很慶幸我在的這個團隊的代碼駕馭能力都還不錯,很少有爛代碼。但為什麼還會有壞代碼?壞代碼不是與生俱來的,他在剛上線的時候也許也是好代碼,慢慢的變壞了,沒關系,我們把它找出來。
找出壞代碼,我們有兩個階段
第一個階段是我們應用無法對自身的性能進行監控,隻能通過db提供性能較差以及執行頻率過高的sql。dba給你找出那些高峰期太過消耗資源的sql,這些sql可以大緻的讓你找出來是哪個功能再具體到哪個方法。部落客負責的項目使用了mybatis架構(用hibernate的,我就隻能
呵呵 了),如果有sql,我們能很快的定位到具體的方法,然後再進一步的檢視代碼,了解業務,并修改影響性能的代碼。但是這種通過sql定位的方法并不全面,隻能找出單條具有性能問題sql所在的方法,
sql本身的性能是以條為機關,而我們的方法往往包含多個sql。如:2個每個隻需要250ms的sql,在同一個方法裡面,那就要消耗500ms,這種情況,sql性能上沒有較大的問題,通過db是很難找出來的。一些有性能問題的單條sql(查詢比較多)以及執行頻率較高的sql,dba會比較容易提供。而且這種sql性能的問題,優化的手段非常有限,如增加一些條件或者hint的方式強制走索引,dba綁定執行計劃降低sql的消耗,比較複雜的查詢的sql拆分成單表查詢,增加字段進行關聯屬性的備援,資料庫中的字典值直接放入到記憶體中,盡量減少大表之間的關聯查詢......詳細的優化手段的使用場景,我在下一節中再詳細的介紹。
第二階段是,建立應用内部的自我監控,我們使用spring的aop實作了一個簡單高效的監控功能,這個監控功能可以切入到各個層,如service,manager,dao等等,切入之後,每一層中的方法所消耗的時間都會放入到記憶體中,方法調用結束後,如果超出預先設定的執行時間如
500ms
預警線,就會将各個調用執行的方法的時間列印在一個日志中,這非常有用,而且實作的簡單優雅,基本能滿足應用的自我性能監控所需要的資料。但它也是有缺點的,如果預警線設定的過低,對io的消耗還是有點小嚴重。一般情況下,性能優化的預警線我們設定的時間為500ms。這樣,執行時間超過500ms的方法都會收集在日志中。
使用應用内部的自我監控,還有一個非常明顯的好處,在系統平均響應時間突然變慢的時候,我們打開這個日志可以很快定位出到底是什麼問題。幾個月前在我們的應用中,使用了一個叫
hazelcast的緩存元件,jvm毫無征兆的oom,并由我們的運維系統自動重新開機,我們打開這個日志,定位到是hazelcast操作逾時造成,很快,我們就有了下一步的動作。
有了性能監控的日志檔案之後,我們就有了基礎資料,通過腳本每天分析出來性能最差的top10和超過500ms執行次數的top10。得到類似如下的資料
這個簡單有效,能有如此多的好處的小東西,到底是怎麼實作的?
我在之前的博文中有介紹
它記錄下來的檔案的格式大概是:
前面的東西都很好了解,方括号的東西的意思是 第一個數字
方法執行的總時間,第二個百分比數字,方法執行占上一層方法調用總耗時百分比,第三個數字的意思是時間流,從0開始,執行到哪個方法的時候耗時多少。
這種記錄的方式讓我們很快的就能找到對應的壞代碼的地方。
總之,隻有對自身的應用有所了解,才能準确的找到那些壞的代碼。找到了他們,性能優化就成功了一半。
還沒有實作自己應用内部監控的,趕緊寫一個,讓壞代碼無處可藏。