...

Web前端性能優化深度解讀

2022-01-29

導讀: 用戶體驗是(shì)web産品非常重要(yào / yāo)的(de)部分,核心是(shì)讓用戶使用舒服,幫助用戶流暢地(dì / de)得到(dào)所求,用戶體驗的(de)優劣甚至會影響到(dào)用戶的(de)留存。體驗差的(de)網站各有各的(de)不(bù)同,但是(shì)體驗好的(de)網站往往都有一(yī / yì /yí)些共性,這(zhè)些優秀的(de)特征凝結了(le/liǎo)設計師、研發工程師和(hé / huò)産品經理的(de)大(dà)量智慧。

  • 訪問交互速度迅速

  • 動畫效果順滑流暢

  • 有用戶操作的(de)反饋

  • 簡單的(de)操作步驟

  • 整站體驗一(yī / yì /yí)緻性

  • 主體内容在(zài)最顯眼的(de)位置

  • 無障礙訪問,不(bù)同的(de)人(rén)群均可使用

在(zài)這(zhè)些優秀體驗的(de)特性中,最容易讓人(rén)産生共鳴的(de)往往是(shì)網站的(de)性能問題,比如網站的(de)訪問交互速度。如何發現性能問題?性能如何優化(性能優化的(de)常規方法和(hé / huò)框架方法)?如何衡量收益?本文根據多年在(zài)性能優化方面的(de)實踐,着重分享一(yī / yì /yí)下首屏性能優化的(de)一(yī / yì /yí)些經驗。

01 性能采集

工欲利器事,必先利其器。我們所說(shuō)的(de)性能采集并不(bù)是(shì)性能分析Devtools,而(ér)是(shì)指在(zài)産品真實用戶訪問的(de)大(dà)數據中進行抽樣,對于(yú)抽樣用戶進行性能數據采集,得到(dào)真實用戶環境下産品性能數據。各浏覽器廠商都已認識到(dào)性能對于(yú)web開發的(de)重要(yào / yāo)性,爲(wéi / wèi)了(le/liǎo)解決當前性能測試的(de)困難,W3C推出(chū)了(le/liǎo)一(yī / yì /yí)套性能API标準,目的(de)是(shì)簡化開發者對網站性能進行精确分析與控制的(de)過程,方便開發者采取手段提高web性能。整套标準包含了(le/liǎo)10餘種API,在(zài)下圖中可以(yǐ)看到(dào)它們當前在(zài)規範流程中的(de)進展。

圖:性能API标準(摘錄51CTO圖片)

這(zhè)套标準中提供了(le/liǎo)導航定時(shí)(Navigation Timing)、資源定時(shí)(Resource Timing)、用戶定時(shí)User Timing和(hé / huò)性能時(shí)間線(Performance Timeline)規範可以(yǐ)幫助開發人(rén)員精确地(dì / de)測量文檔的(de)導航時(shí)間,在(zài)頁面上(shàng)獲取資源的(de)情況,以(yǐ)及開發人(rén)員腳本執行情況。

在(zài)這(zhè)套API中,頁面加載Navigation Timing和(hé / huò)頁面資源加載Resource Timing這(zhè)兩個(gè)API可以(yǐ)幫助我們獲取頁面的(de)Domready時(shí)間、onload時(shí)間、白屏時(shí)間以(yǐ)及單個(gè)頁面資源在(zài)從發送請求到(dào)獲取到(dào)response各階段例如帶寬、延遲或主頁的(de)整體頁面加載時(shí)間的(de)性能參數,這(zhè)些都是(shì)基于(yú)真實用戶數據(RUM)。

圖:Navigation Timing關系圖(摘錄W3C)

在(zài)獲取用戶訪問Timing數據的(de)前提下,我們可以(yǐ)結合具體業務場景定義訪問性能的(de)核心指标,例如白屏時(shí)間、首屏時(shí)間FSP、用戶可交互時(shí)間TTI、頁面onload時(shí)間等作爲(wéi / wèi)核心優化指标,其中首屏時(shí)間和(hé / huò)用戶可交互時(shí)間需要(yào / yāo)單獨埋點自定義。

還可以(yǐ)通過獲取DNS查詢耗時(shí)、TCP鏈接耗時(shí)、request請求耗時(shí)、解析dom樹耗時(shí)、白屏時(shí)間、domready時(shí)間、onload時(shí)間等做性能分析,後續根據症狀對這(zhè)些細緻階段做性能優化,這(zhè)些參數是(shì)通過上(shàng)面的(de)performance.timing各個(gè)屬性的(de)差值組成的(de)。

通過使用API對各個(gè)階段性能指标進行采集,等待到(dào)所有數據都獲取完成之(zhī)後,通過網絡請求将數據發送到(dào)服務器用作後續數據分析使用。

02 性能優化

快速加載、及時(shí)響應用戶反饋、提供流暢的(de)動畫、以(yǐ)及擁有類似原生APP一(yī / yì /yí)般沉浸的(de)用戶體驗是(shì)web應用在(zài)性能優化上(shàng)的(de)目标,這(zhè)主要(yào / yāo)關系到(dào)加載性能和(hé / huò)渲染性能兩個(gè)方面,本章節介紹一(yī / yì /yí)些常規優化方法和(hé / huò)框架級優化方案。

2.1 加載性能優化

Web 頁面通常由 HTML、CSS、JavaScript 和(hé / huò)其他(tā)多媒體資源組成,充斥着各種同步資源和(hé / huò)異步資源。頁面加載時(shí),必須從服務器獲取這(zhè)些資源。

2.1.1 減小資源體積

  • 壓縮文本内容

  • 優化JavaScript第三方庫引入

壓縮雖然簡單,但十分有效,這(zhè)也(yě)是(shì)最廣泛的(de)優化資源體積的(de)操作。許多工具可以(yǐ)幫助我們完成HTML、CSS、JavaScript、圖片等壓縮。例如,TerserPlugin可以(yǐ)用于(yú)壓縮 JavaScript,PostCSS可以(yǐ)對 CSS 進行壓縮,以(yǐ)及完成前綴自動補全工作。除了(le/liǎo)壓縮單個(gè)文件外,在(zài)服務器上(shàng)配置 Gzip 也(yě)十分重要(yào / yāo)。Gzip 對文本資源的(de)壓縮效果非常明顯,通常可以(yǐ)将體積再壓縮至原本的(de) 30% 左右,但 Gzip 對已經單獨壓縮的(de)圖像等非文本資源來(lái)說(shuō),效果并不(bù)好。

如果我們隻需要(yào / yāo)使用工具庫中少數幾個(gè)簡單函數,可以(yǐ)考慮使用原生 JavaScript 代替。不(bù)計後果地(dì / de)引入第三方庫,會迅速增大(dà) JavaScript 資源的(de)體積。

2.1.2 對資源進行緩存

緩存在(zài)優化頁面加載性能的(de)工作中有舉足輕重的(de)作用,緩存無處不(bù)在(zài),包括浏覽器端、網絡代理、服務端緩存,往往能大(dà)幅加快響應速度。

圖:web全鏈路緩存

  • HTTP 緩存

  • Local Storage

  • Cache Storage

  • IndexedDB

  • CDN

現代浏覽器都實現了(le/liǎo) HTTP 緩存機制。浏覽器在(zài)初次獲取資源後,會根據 HTTP 響應頭部的(de)Cache-Control和(hé / huò)ETag字段,來(lái)決定該資源的(de)強緩存策略或者協商緩存策略。

Local Storage主要(yào / yāo)是(shì)用來(lái)作爲(wéi / wèi)本地(dì / de)存儲來(lái)使用的(de),解決了(le/liǎo)cookie存儲空間不(bù)足的(de)問題(cookie中每條cookie的(de)存儲空間爲(wéi / wèi)4k),localStorage中一(yī / yì /yí)般浏覽器支持的(de)是(shì)5M大(dà)小。

Cache Storage它用來(lái)存儲 Response 對象的(de),也(yě)就(jiù)是(shì)說(shuō)用來(lái)對 HTTP響應做緩存的(de),通常在(zài)PWA技術中使用。

IndexedDB是(shì)一(yī / yì /yí)種在(zài)浏覽器中持久存儲數據的(de)方法,允許我們不(bù)考慮網絡可用性,創建具有豐富查詢能力的(de)可離線web應用程序。

内容緩存在(zài)CDN網絡節點,位于(yú)用戶接入點,是(shì)面向最終用戶的(de)内容提供設備,可緩存靜态Web内容和(hé / huò)流媒體内容,實現内容的(de)邊緣傳播和(hé / huò)存儲,以(yǐ)便用戶的(de)就(jiù)近訪問。

2.1.3 調整資源優先級

通過調整資源加載優先級,保證主體内容能夠較快的(de)被加載完成,通過預加載、懶加載等多種方式,調整資源加載的(de)行爲(wéi / wèi),優化網頁加載性能。

  • 預加載

  • 預連接與 DNS 預解析

  • 預取

  • 懶加載

  • Service Worker

通過來(lái)提前聲明當前頁面所需的(de)資源,以(yǐ)便浏覽器能預加載這(zhè)些資源。通過media屬性進行媒體查詢,根據響應式的(de)情況選擇性地(dì / de)預加載資源。

預連接會提前完成 DNS 解析、TCP 握手和(hé / huò) TLS 協商的(de)工作,但并不(bù)會提前加載資源。也(yě)可以(yǐ)考慮使用,提前與資源建立 socket 連接。

浏覽器會在(zài)空閑時(shí),使用最低優先級下載預取的(de)資源。預取通過聲明,通常用于(yú)點擊“下一(yī / yì /yí)頁”的(de)頁面動作之(zhī)前提前加載用戶接下來(lái)可能需要(yào / yāo)的(de)html資源。

按需加載和(hé / huò)延時(shí)加載都屬于(yú)懶加載的(de)範疇,例如對圖像資源采用“懶加載”策略,即僅加載當前在(zài)視口内的(de)圖像,對于(yú)視口外未加載的(de)圖像,在(zài)其即将滾動進入視口時(shí)才開始加載。

利用Service Worker 線程脫離在(zài)主線程之(zhī)外來(lái)進行 Web 資源和(hé / huò)請求的(de)持久離線緩存。

2.1.4 合理拆分代碼

浏覽器支持并行加載資源,合理拆分資源也(yě)是(shì)一(yī / yì /yí)種有效的(de)優化方法。爲(wéi / wèi)了(le/liǎo)更好的(de)效果,我們往往不(bù)需要(yào / yāo)在(zài)首屏一(yī / yì /yí)次性加載所有 JavaScript 代碼,合理的(de)拆分代碼、區分開發和(hé / huò)生産環境使用少量主要(yào / yāo)代碼,将當前暫時(shí)不(bù)需要(yào / yāo)的(de)代碼拆分出(chū)去可以(yǐ)有效加快首屏展現的(de)速度。通過webpack區分開發環境和(hé / huò)生産環境差異化配置打包資源可以(yǐ)有效優化代碼,Tree shaking使得模塊間依賴可以(yǐ)通過靜态分析來(lái)更好地(dì / de)優化剪枝(僅ES modules支持)。webpack-bundle-analyzer 是(shì)一(yī / yì /yí)個(gè)關于(yú) webpack 構建産物的(de)可視化插件,可以(yǐ)清晰地(dì / de)看到(dào)構建産物的(de)體積,幫助分析後續的(de)優化方向。

2.1.5 HTTP/2

HTTP/2帶給WEB帶來(lái)了(le/liǎo)很大(dà)的(de)性能提升,同時(shí)多路複用、頭部壓縮、Server Push等特點,使得可以(yǐ)在(zài)一(yī / yì /yí)個(gè)連接上(shàng)同時(shí)打開多個(gè)流雙向傳輸數據,服務端可以(yǐ)在(zài)發送頁面 HTML 時(shí)主動推送其它資源,而(ér)不(bù)用等到(dào)浏覽器解析到(dào)相應位置,發起請求再響應。

圖:http1 vs http2

2.2 渲染性能優化

浏覽器在(zài)渲染頁面前,首先會将 HTML 文本内容解析爲(wéi / wèi) DOM,将 CSS 解析爲(wéi / wèi) CSSOM。DOM 和(hé / huò) CSSOM 都是(shì)樹狀數據結構,兩者相互獨立,但又有相似之(zhī)處。接着,浏覽器會将 DOM 和(hé / huò) CSSOM 樹合并成渲染樹。從 DOM 樹的(de)根節點開始遍曆,并在(zài) CSSOM 樹中查找節點對應的(de)樣式規則,合并成渲染樹中的(de)節點。在(zài)遍曆的(de)過程中,不(bù)可見的(de)節點将會被忽略。渲染樹随後會被用于(yú)布局,就(jiù)是(shì)計算渲染樹節點在(zài)浏覽器視口中确切的(de)位置和(hé / huò)大(dà)小。浏覽器進行一(yī / yì /yí)次布局的(de)性能開銷較大(dà),我們需要(yào / yāo)小心地(dì / de)避免頻繁觸發頁面重新布局。得到(dào)渲染樹節點的(de)幾何布局信息後,浏覽器就(jiù)可以(yǐ)将節點繪制到(dào)屏幕上(shàng)了(le/liǎo),包括繪制文本、顔色、邊框和(hé / huò)陰影等。

繪制的(de)過程,首先會根據布局和(hé / huò)視覺相關的(de)樣式信息生成一(yī / yì /yí)系列繪制操作,随後執行栅格化(栅格化是(shì)将向量圖形格式表示的(de)圖像轉換成位圖以(yǐ)用于(yú)顯示器或者打印機輸出(chū)的(de)過程),将待繪制項轉換爲(wéi / wèi)位圖存儲在(zài) GPU 中,最終通過圖形庫将像素繪制在(zài)屏幕上(shàng)。

圖:浏覽器渲染過程

頁面不(bù)是(shì)一(yī / yì /yí)次性被繪制出(chū)來(lái)的(de)。實際上(shàng),頁面被分成了(le/liǎo)多個(gè)圖層進行繪制,這(zhè)些圖層會在(zài)另一(yī / yì /yí)個(gè)單獨的(de)線程裏繪制到(dào)屏幕上(shàng),這(zhè)個(gè)過程被稱作合成。合成線程可以(yǐ)對圖層進行剪切、變換等處理,因此可以(yǐ)用于(yú)響應用戶基本的(de)滾動、縮放等操作,又不(bù)會受到(dào)主線程阻塞的(de)影響。

2.2.1 關鍵渲染路徑

由于(yú)渲染都是(shì)在(zài)主進程中執行的(de),所以(yǐ)合理的(de)利用主進程渲染非常重要(yào / yāo)。首屏渲染所必須的(de)關鍵資源,共同組成了(le/liǎo)關鍵渲染路徑,減少非關鍵渲染路徑的(de)資源消耗可以(yǐ)有效提升渲染速度。

  • 延遲非關鍵 CSS 加載

  • async 和(hé / huò) defer

Web 應用中往往會有一(yī / yì /yí)些首屏渲染時(shí)用不(bù)到(dào)的(de) CSS,如彈框的(de)樣式等。通過引用的(de) CSS 都會在(zài)加載時(shí)阻塞頁面渲染。爲(wéi / wèi)了(le/liǎo)使這(zhè)些非關鍵 CSS 不(bù)阻塞頁面渲染,可以(yǐ)通過拆分資源的(de)方式并延遲非關鍵資源加載。

由于(yú)渲染都是(shì)在(zài)主進程中執行的(de),所以(yǐ)合理的(de)利用主進程渲染非常重要(yào / yāo)。首屏渲染所必須的(de)關鍵資源,共同組成了(le/liǎo)關鍵渲染路徑,減少非關鍵渲染路徑的(de)資源消耗可以(yǐ)有效提升渲染速度。

2.2.2 非阻塞 JavaScript

用戶對于(yú)不(bù)流暢的(de)滾動或動畫十分敏感,一(yī / yì /yí)般要(yào / yāo)求頁面幀率應達到(dào)每秒 60 幀。由于(yú) JavaScript 一(yī / yì /yí)般是(shì)單線程執行的(de),長時(shí)間執行的(de)任務會阻塞浏覽器的(de)主線程,使頁面失去響應,出(chū)現卡頓和(hé / huò)假死的(de)現象。

  • 頁面滾動

  • requestAnimationFrame 任務在(zài)浏覽器渲染下一(yī / yì /yí)幀之(zhī)前執行

  • requestIdleCallback 将任務安排在(zài)浏覽器空閑時(shí)執行

  • Web Workers

當我們監聽 touchstart、touchmove 等事件時(shí),由于(yú)合成線程并不(bù)知道(dào)我們是(shì)否會通過 event.preventDefault() 來(lái)阻止默認的(de)滾動行爲(wéi / wèi),從而(ér)在(zài)每次事件觸發時(shí),都會等待事件處理函數執行完畢後再進行頁面滾動。這(zhè)通常會導緻較明顯的(de)延遲,影響頁面滾動的(de)流暢性。通過在(zài)addEventListener()時(shí)聲明{passive: true},來(lái)表明事件處理函數不(bù)會阻止頁面滾動,使得用戶的(de)操作更快得到(dào)響應。

我們可以(yǐ)将一(yī / yì /yí)些耗性能的(de)邏輯放在(zài) worker 線程中進行處理,這(zhè)樣主線程就(jiù)能繼續響應用戶操作和(hé / huò)渲染頁面了(le/liǎo)。

2.2.3 降低渲染樹計算複雜性

結構越複雜的(de)頁面往往性能越差,動畫多的(de)頁面出(chū)現卡頓的(de)幾率也(yě)越大(dà)。

  • 減少查找與元素匹配成本

  • 減少布局次數

  • 優化繪制與合成

渲染樹由 DOM 和(hé / huò) CSSOM 樹合并而(ér)成,對于(yú)每個(gè) DOM 元素,需要(yào / yāo)查找與元素匹配的(de)樣式規則。CSS Modules 是(shì)一(yī / yì /yí)種較爲(wéi / wèi)主流的(de) CSS-in-JS 解決方案,利用 webpack 等構建工具,可以(yǐ)對類選擇器生成自定義格式的(de)唯一(yī / yì /yí)類名,同樣能減少浏覽器匹配 CSS 選擇器的(de)開銷。

浏覽器進行一(yī / yì /yí)次布局的(de)開銷很大(dà),所以(yǐ)我們需要(yào / yāo)盡可能避免直接修改這(zhè)些屬性,尤其是(shì)不(bù)應将布局屬性用于(yú)動畫效果,否則會出(chū)現明顯的(de)掉幀現象。

修改絕大(dà)多數樣式屬性都會導緻頁面重繪,這(zhè)很難避免。僅有的(de)例外是(shì)transform和(hé / huò)opacity,這(zhè)是(shì)由于(yú)它們可以(yǐ)僅由合成器操作圖層來(lái)實現。transform和(hé / huò)opacity非常适合用于(yú)實現動畫效果,但我們仍需要(yào / yāo)通過will-change爲(wéi / wèi)它們創建獨立的(de)圖層,避免影響其他(tā)圖層的(de)繪制。

2.3 框架優化方法

CSR、SSR、NSR、ESR、hybrid離線包、Big pipe、app cache等,都是(shì)不(bù)錯的(de)方法。

2.3.1 CSR(Client Side Render)

浏覽器渲染顧名思義就(jiù)是(shì)所有的(de)頁面渲染、邏輯處理、頁面路由、接口請求均是(shì)在(zài)浏覽器中發生,也(yě)就(jiù)是(shì)從服務端請求一(yī / yì /yí)個(gè)簡單HTML文件然後通過執行JavaScript在(zài)HTML上(shàng)進行内容的(de)添加。其實,現代主流的(de)前端框架均是(shì)這(zhè)種渲染方式,這(zhè)種渲染方式的(de)好處在(zài)于(yú)實現了(le/liǎo)前後端架構分離,利于(yú)前後端職責分離,并且能夠首次渲染迅速有效減少白屏時(shí)間。同時(shí),CSR可以(yǐ)通過在(zài)打包編譯階段進行預渲染或者骨架屏生成,可以(yǐ)進一(yī / yì /yí)步提升首次渲染的(de)用戶體驗。

圖:CSR

2.3.2 SSR(Server Side Render)

服務端渲染則是(shì)在(zài)服務端完成頁面的(de)渲染,在(zài)服務端完成頁面模闆、數據填充、頁面渲染,然後将完整的(de)HTML内容返回給到(dào)浏覽器。由于(yú)所有的(de)渲染工作都在(zài)服務端完成,因此網站的(de)首屏時(shí)間和(hé / huò)TTI都會表現比較好。

圖:SSR

但是(shì),渲染需要(yào / yāo)在(zài)服務端完成,并不(bù)能很好進行前後端職責分離,而(ér)且白屏時(shí)間也(yě)會比較長,同時(shí),對于(yú)服務端的(de)負載要(yào / yāo)求也(yě)會比較高。

2.3.3 NSR(Native Side Render)

GMTC2019 全球大(dà)前端技術上(shàng) UC 團隊提到(dào)了(le/liǎo) 0.3 秒的(de) “閃開” 方案。這(zhè)種方案适用于(yú)混合開發,NSR本質是(shì)分布式SSR,通過加載離線頁面模闆,Ajax預加載頁面數據,Native渲染生成Html數據并且緩存在(zài)客戶端,将服務器的(de)渲染工作放在(zài)了(le/liǎo)一(yī / yì /yí)個(gè)個(gè)獨立的(de)移動設備中,實現了(le/liǎo)頁面的(de)預加載,同時(shí)又不(bù)會增加額外的(de)服務器壓力。核心思路是(shì)借助浏覽器啓用一(yī / yì /yí)個(gè) JS-Runtime,提前将下載好的(de) html 模闆及預取的(de) feed 流數據進行渲染,然後将 html 設置到(dào)内存級别的(de) MemoryCache 中,從而(ér)達到(dào)點開即看的(de)效果。

圖:NSR

2.3.4 ESR(Edge Side Render)

邊緣渲染的(de)核心思想是(shì),借助邊緣計算的(de)能力,将靜态内容與動态内容以(yǐ)流式的(de)方式,先後返回給用戶。CDN 節點相比于(yú)Server距離用戶更近,有着更短的(de)網絡延時(shí)。在(zài) CDN 節點上(shàng)将可緩存的(de)頁面靜态部分先快速返回給用戶,同時(shí)在(zài) CDN 節點上(shàng)發起動态部分内容請求,并将動态内容在(zài)靜态部分的(de)響應流後繼續返回給用戶。

圖:ESR

03、收益衡量

速度是(shì)應用性能最直接體現。做性能收益衡量也(yě)需要(yào / yāo)多維度全方位的(de)進行分析與對比。通過等量實驗組和(hé / huò)對照組在(zài)核心指标方面大(dà)量真實數據的(de)分位值對比,可以(yǐ)得到(dào)性能方面的(de)收益,也(yě)可以(yǐ)關聯到(dào)用戶PV、UV以(yǐ)及收入等方面是(shì)數據收益。

監控網站真實用戶可感知的(de)白屏、首屏、可交互等用戶體驗指标,從服務器端響應時(shí)間、網絡延時(shí)、DOM解析等細緻指标的(de)變化也(yě)可以(yǐ)做日常性能優化。

  • 統計核心指标不(bù)同分位數的(de)占比數據。

  • 統計不(bù)同版本浏覽器和(hé / huò)設備類型的(de)核心指标數據,基于(yú)多平台浏覽器性能分析。

  • 統計不(bù)同區域(包括國(guó)家、省份、城市)、不(bù)同運營商以(yǐ)及接入方式(包括2G/3G/4G/WiFi)下的(de)各關鍵網絡性能指标。

圖:性能平台

業内不(bù)錯的(de)性能監控平台包括ONEAPM、聽雲、性能魔方等,各個(gè)大(dà)公司和(hé / huò)雲平台也(yě)都提供不(bù)錯的(de)相關監控服務。

04 總結

你做事的(de)時(shí)候不(bù)隻是(shì)靠經驗教訓的(de)曆史積累,還有一(yī / yì /yí)套系統的(de)流程或者模闆。做性能優化是(shì)一(yī / yì /yí)件需要(yào / yāo)具有閉環思維的(de)事情,特别是(shì)這(zhè)種端到(dào)端的(de)優化要(yào / yāo)注意事前規劃、事中執行和(hé / huò)事後總結三個(gè)階段,而(ér)且還要(yào / yāo)結合不(bù)同的(de)業務場景進行優化,有時(shí)候還要(yào / yāo)與客戶端相協同,并不(bù)是(shì)生拉硬套就(jiù)可以(yǐ)完成的(de)事情。

甚至很多大(dà)廠的(de)業務前端還要(yào / yāo)一(yī / yì /yí)邊解決曆史包袱,一(yī / yì /yí)邊進行優化,小心前行!随着優化後業務仍然在(zài)不(bù)斷的(de)叠代和(hé / huò)發展,如何鞏固性能優化結果也(yě)是(shì)一(yī / yì /yí)件任重道(dào)遠持續投入的(de)事情,掌握性能優化基本原理結合具有優秀性能結構設計或許是(shì)一(yī / yì /yí)種智慧的(de)方法。


來(lái)源:51CTO