天天看點

前端面試題:如何做性能優化?

作者:科技樹亂點
前端面試題:如何做性能優化?

#頭條創作挑戰賽#

前端面試最常見但是也最不好回答的一個問題:如何做性能優化?

為什麼?

題目問得很寬泛:性能+優化(具體什麼性能?渲染展示、加載、伺服器響應?優化的手段和方式很多,開發的全鍊路和各個階段都可以涉及)。

是以,這個問題既能考察出面試者的技術廣度,也可以考察出面試者的技術深度來。

那麼本文将嘗試盡可能寬泛和深入的來回答下這個問題。

性能優化要做什麼?

首先,需要确定目前的業務場景和系統架構。

業務場景,例如電商詳情頁面、交易付款頁面;面試視訊頁面;直播頁面等等。

系統架構,例如手機app、移動站點、PC站點等等。

抽象來說,可以分成:

  • 用戶端:手機App或者頁面
  • 網絡層:CDN、HTTP/HTTPS、RPC、網關服務等
  • 服務端:Java、Node.js、PHP等伺服器
  • 資料層:Redis、MongoDB、MySql等

對用戶端進行性能優化:

  • 原生應用
  • Hybrid應用
  • HTML頁面

原生應用性能優化:

啟動時間過長:

應用啟動時間是使用者體驗的重要名額,如果啟動時間過長,會讓使用者感覺應用響應較慢。優化建議:

  • 減少啟動時的初始化工作,隻加載必要的資源。
  • 使用冷啟動和熱啟動時的差異,優先加載核心功能和界面。
  • 考慮使用啟動畫面來給使用者一個即時的回報。

卡頓和掉幀:

當應用界面出現卡頓或掉幀,使用者會感到操作不流暢。優化建議:

  • 将耗時操作放到背景線程執行,避免主線程阻塞。
  • 使用硬體加速和動畫優化來提高界面繪制性能。
  • 減少不必要的布局和繪制操作。

記憶體洩漏:

記憶體洩漏會導緻應用占用過多記憶體,可能引起應用崩潰或被系統終止。優化建議:

  • 定期檢查和釋放不再使用的對象和資源。
  • 使用記憶體分析工具來定位記憶體洩漏問題。

過度繪制:

過度繪制是指在每一幀中進行多餘的繪制操作,浪費了系統資源。優化建議:

  • 使用Hierarchy Viewer工具來檢查視圖層次結構,避免重疊繪制。
  • 優化布局和繪制操作,減少不必要的繪制。

網絡性能問題:

網絡請求過多或網絡請求過慢會影響應用的性能和使用者體驗。優化建議:

  • 合并多個網絡請求為一個,減少請求次數。
  • 使用緩存技術,減少重複的網絡請求。
  • 使用GZIP等壓縮技術來減小網絡傳輸資料量。

電量消耗過高:

應用的電量消耗是使用者關注的一個重點。優化建議:

  • 減少背景任務和定時任務的頻率和耗時。
  • 使用Doze模式和應用待機來降低應用在背景的能耗。

資源浪費:

使用過多的資源會占用裝置存儲和帶寬。優化建議:

  • 壓縮圖檔和音頻資源,減小應用安裝包的大小。
  • 使用WebP格式代替PNG或JPEG格式的圖檔,可以減少圖檔大小。

Hybrid應用性能優化:

Hybrid應用是指同時使用Web技術(HTML、CSS、JavaScript等)和原生代碼(通常是通過WebView或類似元件加載Web頁面)開發的移動應用。性能優化對于Hybrid應用尤為重要,因為它們需要在Web視圖和原生代碼之間進行互動,同時需要處理兩種不同的技術棧。以下是針對Hybrid應用的性能優化建議:

  1. 減少HTTP請求: Hybrid應用通常依賴于遠端加載的Web資源,減少HTTP請求可以加快加載速度。将CSS和JavaScript檔案進行合并和壓縮,減小檔案體積,同時使用緩存政策,減少重複請求。
  2. 優化Web視圖性能: 在Web視圖中,避免使用過多的動畫效果和複雜的CSS樣式,因為它們可能導緻性能下降。使用硬體加速來提高動畫性能,避免頻繁的重繪和重排操作。
  3. 使用本地元件:在Hybrid應用中,盡量使用原生元件代替Web視圖,因為原生元件通常比WebView更高效。例如,可以使用原生的滾動視圖、清單視圖等來替代Web中的滾動容器。
  4. 懶加載和預加載:對于Hybrid應用,可以使用懶加載和預加載技術來優化頁面加載速度。懶加載是指延遲加載某些資源,直到使用者需要通路它們,而預加載是指提前加載下一個頁面的資源,以便在使用者切換時能夠更快地展示。
  5. 避免記憶體洩漏:在Hybrid應用中,特别需要注意記憶體洩漏問題。及時釋放不再使用的JavaScript對象和原生元件引用,避免造成記憶體洩漏。
  6. 使用WebView緩存: 合理配置WebView的緩存政策,可以減少對遠端資源的重複請求,提高頁面加載速度。
  7. 優化JavaScript性能:JavaScript是Hybrid應用的核心,優化JavaScript性能非常重要。避免使用過多的全局變量,減少不必要的DOM操作,優化JavaScript的算法和循環,使用事件委托等技術來優化性能。
  8. 合理使用本地存儲:Hybrid應用可以使用本地存儲(如localStorage)來緩存資料,但要注意不要存儲過多的資料,以免影響應用性能和裝置存儲空間。
  9. 利用WebView和原生通信:在WebView和原生代碼之間建立高效的通信機制,避免頻繁的資料傳遞和轉換,提高應用的響應速度。
  10. 定期檢查性能:對Hybrid應用進行性能測試和監測是保持應用性能的好方法。使用性能分析工具來檢查性能瓶頸,并根據結果進行優化。

網絡層優化:

  1. 減少網絡請求次數: 盡量合并多個請求為一個,減少網絡請求的次數。使用資源合并和壓縮,将多個資源檔案(如CSS、JavaScript)合并為一個,減少請求次數。
  2. 緩存政策: 合理設定緩存政策,對于不經常變化的資源,使用合适的緩存過期時間,避免重複的網絡請求。對于需要經常更新的資源,可以使用版本号或時間戳來確定用戶端擷取到最新的資源。
  3. 使用CDN加速: 使用内容分發網絡(CDN)可以将靜态資源分布到全球多個伺服器節點,加速資源的傳輸和加載速度。
  4. 異步加載: 使用異步加載來提高頁面加載速度,尤其是對于非關鍵資源,可以在頁面加載完成後再進行加載,而不會影響頁面的渲染和互動。
  5. 壓縮資料: 使用GZIP等壓縮技術來減小網絡傳輸的資料量,加快資料的傳輸速度。
  6. 避免重複請求: 在應用中,盡量避免重複請求相同的資料,可以通過緩存、本地存儲或全局變量來避免重複請求。
  7. 優化網絡請求: 合理設計網絡請求,避免不必要的資料傳輸和處理。使用GET請求來擷取資料,使用POST請求來送出資料。
  8. 使用HTTP/2協定: HTTP/2協定支援多路複用和頭部壓縮等功能,可以提高網絡傳輸的效率。
  9. 處理逾時和錯誤: 對網絡請求進行逾時設定和錯誤處理,避免長時間等待和無響應的情況。
  10. 分批加載: 對于大量資料的加載,可以使用分批加載的方式,逐漸加載資料,而不是一次性加載所有資料。
  11. 移動端優化: 對于移動端應用,盡量減小資料量和請求次數,因為移動網絡條件可能不穩定和較慢。
  12. 性能監控和分析: 使用性能監控工具來分析網絡請求的性能名額,定位性能瓶頸,并根據結果進行優化。

服務端優化:

  1. 資料庫優化: 合理設計資料庫表結構和索引,優化複雜查詢語句,使用資料庫緩存技術,減少資料庫通路次數和查詢開銷。
  2. 緩存技術: 使用緩存來存儲常用的資料或計算結果,減少對資料庫或外部接口的重複請求。可以使用記憶體緩存(如Redis、Memcached)或分布式緩存來提高性能。
  3. 異步處理: 将耗時的操作和背景任務放入消息隊列或異步任務中處理,減少請求響應時間。
  4. 負載均衡: 使用負載均衡技術将請求分散到多個伺服器上,確定每台伺服器的負載均衡,提高系統的可擴充性和容錯性。
  5. 并發處理: 使用多線程、多程序或異步處理來支援并發請求,充分利用多核處理器和資源,提高系統的吞吐量和并發能力。
  6. 資料庫連接配接池: 使用資料庫連接配接池來管理資料庫連接配接,避免頻繁地建立和銷毀連接配接,提高資料庫通路的效率。
  7. 代碼優化: 優化代碼邏輯,減少不必要的計算和循環,避免過度的嵌套和複雜的條件判斷。
  8. 資源合并和壓縮: 将多個資源檔案(如CSS、JavaScript)合并為一個,減少網絡請求次數,同時對靜态資源進行壓縮,減小檔案體積。
  9. 定期清理和優化資料庫: 定期清理無用資料,進行資料庫索引優化和碎片整理,保持資料庫的健康狀态。
  10. 使用CDN加速: 使用内容分發網絡(CDN)來分發靜态資源,減少伺服器的負載和加快資源傳輸速度。
  11. 請求合并: 将多個小請求合并為一個大請求,減少網絡請求的次數。
  12. 服務拆分: 将大型服務拆分成小的微服務,按需啟動和部署,提高系統的靈活性和可維護性。
  13. 使用緩存代理: 使用緩存代理伺服器,将部分請求直接由緩存傳回,減少對後端服務的壓力。
  14. 監控和分析: 使用性能監控工具來監控系統的性能名額,定位性能瓶頸,并根據結果進行優化。

資料層優化:

  1. 合理設計資料庫表結構: 對于關系型資料庫,合理設計表結構可以提高查詢效率。使用适當的資料類型和索引來優化資料庫查詢。
  2. 使用緩存: 對于頻繁讀取的資料,可以使用緩存來減少資料庫查詢次數,提高讀取性能。可以使用記憶體緩存(如Redis、Memcached)或分布式緩存來存儲常用的資料。
  3. 分庫分表: 對于大型資料量的資料庫,可以考慮将資料進行分庫分表,将資料分散存儲在多個資料庫中,提高資料庫讀寫性能。
  4. 異步處理: 對于耗時的資料處理操作,可以使用異步處理或消息隊列來減少使用者請求的響應時間。
  5. 批量處理: 對于大量資料的處理,可以使用批量處理方式,而不是逐條處理資料,減少資料庫事務和IO操作的開銷。
  6. 資料壓縮: 對于大量的文本資料或日志資料,可以使用資料壓縮技術減小存儲空間和網絡傳輸資料量。
  7. 定期清理: 定期清理無用的資料,減少資料庫存儲空間占用。
  8. 使用索引: 在資料庫中使用合适的索引可以提高查詢效率,加快資料檢索速度。
  9. 備援資料: 對于頻繁查詢的資料,可以在多個位置進行備援存儲,減少查詢的複雜度。
  10. 資料預處理: 對于常用的查詢,可以在資料插入或更新時進行預處理,以減少查詢時的計算開銷。
  11. 分級存儲: 對于曆史資料或不常通路的資料,可以将其存儲在低成本的存儲媒體中,以減少高成本存儲的負擔。
  12. 使用NoSQL資料庫: 根據應用場景選擇合适的資料庫類型,對于複雜的查詢和海量資料的存儲,NoSQL資料庫可能更适合。
  13. 壓縮和序列化: 在資料傳輸過程中,可以使用壓縮和序列化技術來減小資料傳輸量,提高資料傳輸效率。
  14. 使用緩存代理: 對于一些經常請求的資料,可以使用緩存代理伺服器,直接傳回緩存資料,減少後端伺服器的負載。

總結

可以看到,上面很多内容是可以通用的,例如減少請求、使用緩存。但是具體到每一層的具體措施又不一樣。是以,性能優化問題可以很好地考察技術深度和廣度。具體到面試過程中,我們可以先分類總結出一些優化技巧,再加以細節的補充和完善。面試官希望能通過這個題目對面試者的技術能力有一個大概的把握,這也是這道題目最大的意義。

性能優化嚴格來說是沒有終點的。是以我們在回答的時候,如果面試官問到了一些具體的優化名額,我們需要給出一些對比的資料,例如優化前頁面加載時間xx秒,優化後加載時間xx秒。優化前單機QPSxx,優化後單機QPSxx。

繼續閱讀