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

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

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

測(cè)試條件:CPU占比不超過85%,超時(shí)時(shí)間不超過900ms

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

針對(duì)春節(jié)排行榜運(yùn)動(dòng)側(cè)準(zhǔn)備了120臺(tái)V8機(jī)器。以排行榜首頁為例,優(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)運(yùn)行而言,系統(tǒng)QPS = 4700*120 = 56.4w/s,此時(shí)平均每個(gè)請(qǐng)求從發(fā)包到收包耗時(shí)約40ms。

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

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

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

排行榜架構(gòu)圖

要點(diǎn)如下:

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

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

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

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

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

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

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

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

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

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

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

3. 優(yōu)化Json操作。思路:將Json庫(kù)替換為簡(jiǎn)單字符串拼接(這里由于是和前端交互,限定了只能使用json交互,因此優(yōu)化的思路還是從組裝json方面考慮,而不是替換為二進(jìn)制協(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存儲(chǔ)的編解碼封裝,也就是說,后續(xù)的性能優(yōu)化已經(jīng)和業(yè)務(wù)無關(guān)了。

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

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

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

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

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

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

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

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

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

三、走過的彎路

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

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

等...

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

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

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


參考資料

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


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

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

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

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

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

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