春節(jié)運動排行榜性能優(yōu)化小記

春節(jié)初一~初三期間,紅包活動頁左上角會有春節(jié)排行榜的入口,前期預(yù)估峰值:15w/s。

排行榜server優(yōu)化前后數(shù)據(jù)對比如下(備注:以下數(shù)據(jù),均假設(shè)從CKV中拿到數(shù)據(jù),忽略掉oidb相關(guān)邏輯):

測試條件:CPU占比不超過85%,超時時間不超過900ms

優(yōu)化前單機QPS 優(yōu)化后單機QPS
獲取排行榜首頁數(shù)據(jù)(實時拉取好友步數(shù)并進行排序) 2200 5200 ( +3000)
獲取排行榜分頁數(shù)據(jù)(從Redis快照中直接獲取數(shù)據(jù)) 3000 5500 ( +2500)
用戶點贊 12000 12000
發(fā)送C2C消息 12000 12000

針對春節(jié)排行榜運動側(cè)準備了120臺V8機器。以排行榜首頁為例,優(yōu)化前,系統(tǒng)QPS(極限值) = 2200*120 = 26.4w/s,優(yōu)化后,系統(tǒng)QPS(極限值) = 5200*120 = 62.4w/s,提升136.4%。
以CPU占比75%平穩(wěn)運行而言,系統(tǒng)QPS = 4700*120 = 56.4w/s,此時平均每個請求從發(fā)包到收包耗時約40ms。

所有接口中,由于排行榜首頁,做的邏輯更多更復(fù)雜(包括拉取關(guān)系鏈、取所有好友步數(shù)、排序、取用戶信息、取會員標記、取點贊數(shù)據(jù)等),因此,不出意外,首頁QPS是最低的。另外,春節(jié)期間排行榜所有請求中,首頁的請求應(yīng)該是最多的,畢竟,用戶進入頁面首先就會請求首頁數(shù)據(jù)。

綜上所述,優(yōu)化排行榜首頁性能成為了整個系統(tǒng)的關(guān)鍵所在。這次優(yōu)化,也是根據(jù)這條思路進行的,下面簡要介紹下優(yōu)化的思路和過程。

一、排行榜邏輯架構(gòu)圖

排行榜架構(gòu)圖

要點如下:

  1. 存儲:主要采用CKV,
  2. 外部接口:能異步就異步(除oidb查會員標記位外)
  3. 框架:SPP微線程,相關(guān)網(wǎng)絡(luò)操作均采用異步。
  4. 備注:SSO尋址走hash一致性尋址,server本地采用Redis做快照,防止排名錯亂的問題。

二、壓測數(shù)據(jù)

工欲善其事,必先利其器。這里不得不提到test.server.com這個壓測利器,文中所有數(shù)據(jù)和結(jié)果均來自test.server.com提供的壓測客戶端。
優(yōu)化的步驟無外乎:
A. 壓測得到當前Server性能(CPU不超過80%,延遲不超過900ms)
B. Perf查看CPU消耗點在哪里(因為排行榜這里是CPU Bound型)
C. 針對B的結(jié)果相應(yīng)優(yōu)化,再重復(fù)進行步驟A。

1. 原始壓測數(shù)據(jù)(未做優(yōu)化前):壓測到2200/s時,CPU占比已經(jīng)飆升至80%。

此時,Perf出來的火焰圖如下(圖為搜索JSON匹配后的結(jié)果):

分析后得知,Server中的Json和map的相關(guān)操作吃了很大一部分CPU,約占用30%左右。

2. 優(yōu)化map操作,將代碼中所有涉及到map的邏輯全部替換為hash_map和vector。思路:map底層采用RB_Tree的方式實現(xiàn),查找復(fù)雜度為OLog(n);hash_map底層采用Hash_table實現(xiàn),查找復(fù)雜度為O(1)。

優(yōu)化前QPS 優(yōu)化后QPS 優(yōu)化措施
2200 3200 (+1000) hash_map和vector替換map操作

備注:C99里面的hash_map,不是標準庫,是gcc實現(xiàn)的:__gnu_cxx::hash_map。這里性能提升明顯,主要是獲取步數(shù)數(shù)據(jù)、用戶關(guān)系鏈數(shù)據(jù)及相互匹配時,查找操作較多。

優(yōu)化后Perf圖如下(搜索關(guān)鍵字<map>如下圖,CPU占比11%左右):

右圖中,之所以map匹配CPU占比超過11%,因為Json相關(guān)的操作中大量的使用了map,而Json還沒有進行優(yōu)化。搜索hash_map,CPU占比只有5%左右。

3. 優(yōu)化Json操作。思路:將Json庫替換為簡單字符串拼接(這里由于是和前端交互,限定了只能使用json交互,因此優(yōu)化的思路還是從組裝json方面考慮,而不是替換為二進制協(xié)議,例如pb等)。

優(yōu)化前QPS 優(yōu)化后QPS 優(yōu)化措施
3200 4000 (** +800**) json組裝,改為自己拼接字符串

優(yōu)化后Perf圖如右下(搜索關(guān)鍵字<ssdasn::>后如下圖):

右圖中,可以看到,優(yōu)化完成后,占用CPU最多的已經(jīng)變?yōu)閟sdasn::的相關(guān)操作,這些操作是CKV存儲的編解碼封裝,也就是說,后續(xù)的性能優(yōu)化已經(jīng)和業(yè)務(wù)無關(guān)了。

此時CPU使用如下,占比約80%左右:

4. 減少日志流水操作。思路:忽略正常處理的請求,只打印出錯請求處理日志。

優(yōu)化前QPS 優(yōu)化后QPS 優(yōu)化措施
4000 4500 (+500) 減少日志打印,只打印出錯日志

優(yōu)化前后perf圖對比如下:

左圖為優(yōu)化前,日志流水操作占比: 2.08%;右圖為優(yōu)化后,正常情況下日志流水操作占比0%(只有出錯才打)。留出了更多的CPU時間給業(yè)務(wù)邏輯,優(yōu)化后QPS如下:

5. gcc編譯增加O2選項。思路:利用編譯器自身的編譯優(yōu)化選項,從編譯執(zhí)行的底層嘗試優(yōu)化性能(業(yè)務(wù)無關(guān))

優(yōu)化前QPS 優(yōu)化后QPS 優(yōu)化措施
4500 5200 (** +700**) 使用gcc O2優(yōu)化選項

優(yōu)化后QPS如下圖:

此時,業(yè)務(wù)server等待隊列耗時如下,可以看到,請求基本都在server收到包后1ms內(nèi)開始被處理,不會堆積:
CPU占比如下,約占比85%左右:

三、走過的彎路

在初步壓測出單機QPS=2200后,由于缺乏經(jīng)驗,沒有從火焰圖去分析CPU到底消耗在哪里。因此只能嘗試各種經(jīng)驗上的方法進行優(yōu)化,例如:

  1. 去掉同步快照操作(傷害用戶體驗)
  2. 去掉關(guān)系鏈CKV同步操作(更換成本高)
  3. 調(diào)整批量獲取CKV的數(shù)量(經(jīng)驗值)
  4. 調(diào)大進程數(shù)
  5. 關(guān)閉系統(tǒng)日志
  6. 關(guān)閉排序(排行榜基礎(chǔ)功能)

等...

這些效果都不明顯,提升作用有效,最多的時候,有損體驗的前提下,QPS才提升到2500左右。

后面在查閱相關(guān)資料后,系統(tǒng)化的使用perf、火焰圖等工具進行分析,抓到性能瓶頸后,有的放矢,才能在后面的優(yōu)化過程中,有效的提升系統(tǒng)QPS。

這次優(yōu)化,從接觸學(xué)習壓測工具開始,到昨天優(yōu)化告一段落,斷斷續(xù)續(xù)持續(xù)了有3、4天左右。


參考資料

gcc 編譯優(yōu)化選項O2相關(guān)知識,可以參考這篇文章GCC中-O1 -O2 -O3 優(yōu)化的原理


另外,O2選項優(yōu)化打開時,注意另外一個選項:-fno-strict-aliasing,如果沒有配合使用的話,程序可能產(chǎn)生未定義的行為,大意是說O2選項默認認為不同類型的指針不能指向同一片內(nèi)存區(qū),如果業(yè)務(wù)代碼中,有強制類型轉(zhuǎn)換,需要注意下這里。具體參考:gcc 編譯參數(shù) -fno-strict-aliasing
官方說明在此:Options That Control Optimization

我的理解:O2性能優(yōu)化選項打開前后代碼語義必然相同,最主要的性能優(yōu)化點,可能還是:未打開前,Gcc編譯生成的代碼是獨立的,每一行代碼都可以打斷,方便調(diào)試;打開后,Gcc編譯生成的代碼是相關(guān)的,并根據(jù)一些相關(guān)性進行了優(yōu)化,當然這時候,調(diào)試的難度就很大了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 特別說明: 1、本文只是面對數(shù)據(jù)庫應(yīng)用開發(fā)的程序員,不適合專業(yè)DBA,DBA在數(shù)據(jù)庫性能優(yōu)化方面需要了解更多的知識...
    安易學(xué)車閱讀 2,158評論 0 40
  • 從三月份找實習到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時芥藍閱讀 42,875評論 11 349
  • TITLE: 編程語言亂燉 碼農(nóng)最大的煩惱——編程語言太多。不是我不學(xué)習,這世界變化快! 有時候還是蠻懷念十幾、二...
    碼園老農(nóng)閱讀 5,602評論 2 35
  • 雨還在下 像在說話 下雨了-薛之謙 喜歡雨天 聽著窗外 ...
    七嶼PHOTO閱讀 274評論 4 9
  • 昨晚關(guān)注了一個小姐姐的公眾號,然后小姐姐后臺回復(fù)說,你的名字很好聽呢,我這才想起來,貌似我這個微信昵稱從注冊...
    方依然閱讀 3,572評論 0 0

友情鏈接更多精彩內(nèi)容