over 6 years ago
前陣子在最佳化公司的 WebAPI 效能,學習到不少寶貴的經驗。
還沒進公司的時候,寫 WebAPI 主要使用 php,接過的案子也都不大,不太需要做太徹底的最佳化,頂多自己玩玩技術。
以下為之前嘗試過的效能最佳化:
- 前端:靜態元素使用 CDN、lazy load javascript、預先快取圖片、minimize resource、cookie-free domain for static files、yslow 分析
- CDN:採用 cloudflare,進行過細部的效能調整
- Reverse proxy:使用 varnish,並和 application custom header 搭配調整快取效能
- Web Server:apache + php-cgi -> apache-worker / event + php-fpm -> nginx + php-fpm
- PHP:調整 fpm 設定、加入 php opcode cache,關閉動態更新功能、session改存在redis中、HHVM / PHP7
- Application:整頁快取 + 部份快取機制(php-apc)
這些是我架設網站會使用的效能最佳化技巧,但是進公司就要面對公司的複雜的噁心的架構,往往和自己做會有不少差異。敝公司的 WebAPI 全都是使用 C++ 寫成(什麼?PHP HipHop?我們不需要XD),但就算是 C++,在架構日益龐大的情況下還是可能發生效能問題。
我們是一間很重視效能的公司,但就跟其他公司一樣,feature都做不完了還管效能,當然是先上再說,就像 IOS7 剛出的時候舊ipad升級之後解鎖要等30秒我現在都還餘悸猶存。但成山的feature做完之後,該面對的還是要面對。
最近公司的 API 比上一個大版本來的緩慢,找了很久發現速度的瓶頸其實是在 dlopen 時載入的 so 太多,導致一隻 API 所用到,全部 so 載入進來至少需要 80ms 以上的時間,對比上一個大版本大概只要 3x ms,足足落後了一倍以上。進行夾板測試之後,我們發現是 library 拆小的策略所導致,在這一季我們將大的 library 拆成很多個小 library,導致 so 數量是以往的兩倍以上。
知道原因之後,接下來我們就開始進行兩個方針,其一為所有 project link 的時候都加上 -Wl,--as-needed,避免連結到不必要的 so;其二為將 webapi 基本使用到的 library 再拆小,用不到的就不要 link,這兩個方針下下去之後,我們成功的將延遲時間提升到 30 ms 左右。