李蘭蘭,宋永鵬
(1.山東省氣象服務(wù)中心,山東濟(jì)南 250031;2.山東省氣象信息中心,山東濟(jì)南 250031)
HTTP Archive 統(tǒng)計(jì)顯示,圖片內(nèi)容已經(jīng)占到了互聯(lián)網(wǎng)內(nèi)容總量的62%,也就是說超過一半的流量和時間都用來下載圖片。從性能優(yōu)化的角度看,圖片也是優(yōu)化的重點(diǎn)和熱點(diǎn)之一,Google PageSpeed 優(yōu)化規(guī)則把圖片優(yōu)化作為重要的優(yōu)化手段。傳統(tǒng)的圖片加載方式是通過Url 或者Src 屬性加載圖片地址,向服務(wù)器提出Http 請求[1]后下載圖片至瀏覽器,圖片站點(diǎn)的開發(fā)過程中,加載的圖片過多會增加向服務(wù)器請求的次數(shù)而導(dǎo)致請求時間過長,對服務(wù)器和本地網(wǎng)絡(luò)資源是極大的浪費(fèi);圖片體積過大會使瀏覽器從上到下逐步顯示圖片直到圖片完整呈現(xiàn),這種從空白區(qū)域到完全加載的過程顯得比較突兀會使用戶體驗(yàn)較差[2]?;贘avascript 的懶加載和預(yù)加載是目前流行的圖片優(yōu)化技術(shù),能夠從頁面前端的角度優(yōu)化加載速度[3];Base64 轉(zhuǎn)碼和圖像壓縮在后端和系統(tǒng)架構(gòu)方面為圖片站點(diǎn)的優(yōu)化提供技術(shù)支持。該文的硬件測試環(huán)境是4G 內(nèi)存的DELL 一體機(jī),軟件測試環(huán)境為Win7 操作系統(tǒng)、山東省氣象部門圖片資料云平臺和Google Chrome。
Base64 是網(wǎng)絡(luò)中常見的用于傳輸8 Bit 字節(jié)代碼的編碼方式,Base64 編碼可用于在Http 環(huán)境下傳遞較長的標(biāo)識信息,具有不可讀性,即編碼的數(shù)據(jù)無法直接查看,通過Html 的Img 圖片標(biāo)簽的Src 屬性和CSS 背景圖片的Url 屬性傳遞[4]。頁面中的每一個圖片需要先向服務(wù)器遞交一個Http 請求,再進(jìn)行圖片的下載與顯示,圖片過多會導(dǎo)致Http 請求時間過長,而Base64 轉(zhuǎn)碼技術(shù)將圖片在服務(wù)器中的保存地址通過編碼表轉(zhuǎn)換成一串字符,隨著頁面的Html 代碼下載到本地,避免了向服務(wù)器進(jìn)行Http 請求的時間消耗和網(wǎng)絡(luò)資源的浪費(fèi)。
Base64 轉(zhuǎn)碼技術(shù)在圖片站點(diǎn)中的應(yīng)用有(圖1所示,包含傳統(tǒng)圖片加載方式)兩種方式:1)對用戶上傳的圖片進(jìn)行轉(zhuǎn)碼,將轉(zhuǎn)碼后圖片的編碼存儲于服務(wù)器的數(shù)據(jù)庫或文件中,用戶訪問圖片時,前端瀏覽器會下載內(nèi)聯(lián)有Base64 編碼字符串的Html 以顯示圖片;2)前端用戶將圖片上傳至服務(wù)器后,后端應(yīng)用將圖片進(jìn)行格式化存儲,并將圖片在服務(wù)器中的相對地址保存于數(shù)據(jù)庫或文件中,前端用戶對圖片有Http 請求的時候,應(yīng)用將圖片的存儲相對地址轉(zhuǎn)換成Base64 編碼字符串隨Html 進(jìn)行下載并加載至瀏覽器[5]。二者區(qū)別在于圖片在服務(wù)器中的存儲方式和前端的顯示方式,前者保存、加載的是圖片的編碼,后者保存圖片本身及其相對地址,加載的同樣僅是相對地址的轉(zhuǎn)碼數(shù)據(jù)流。
圖1 傳統(tǒng)圖片加載和Base64轉(zhuǎn)碼實(shí)現(xiàn)方式
上述程序?qū)崿F(xiàn)Base64 轉(zhuǎn)碼的核心功能,代碼將名為Source 的圖片變量賦值給另一變量fp,目標(biāo)變量經(jīng)過函數(shù)Base64_encode 的轉(zhuǎn)碼后生成Base64 格式的數(shù)據(jù)流,之后將該數(shù)據(jù)流分配至圖片標(biāo)簽img的Src 屬性,通過img 標(biāo)簽加載至用戶前端并顯示,此時瀏覽器加載的字符串是圖片儲存相對地址的轉(zhuǎn)碼流或是圖片本身的轉(zhuǎn)碼流,而不是圖片存儲于服務(wù)器中的相對地址[6]。
由于測試環(huán)境平臺已經(jīng)上線運(yùn)行,數(shù)據(jù)庫中已儲存了大量用戶上傳圖片的相對地址,所以該文采取第二種Base64 轉(zhuǎn)碼方式并和傳統(tǒng)圖片加載方式進(jìn)行性能對比。將數(shù)據(jù)庫中存儲的圖片在服務(wù)器中的相對地址轉(zhuǎn)碼后,將編碼返回前端由Url 或Src 加載并顯示。利用Google Chrome 的開發(fā)者工具,對兩種加載方式下的同一頁面圖片加載時間進(jìn)行對比分析,如表1 所示。原始圖片大小在200 kB 左右時,傳統(tǒng)方式加載和Base64 轉(zhuǎn)碼方式加載的時間分別為281 ms 和4 ms,瀏覽器加載速度相差70 倍,圖片大小在500 kB 時,Base64 轉(zhuǎn)碼方式的加載速度較傳統(tǒng)方式提升20 余倍,圖片大小在5 MB 左右時,提升16倍,性能提升的同時也大大提高了用戶體驗(yàn)度。
隨著圖片大小的增大,它的Base64 編碼字符串長度增長更明顯,4 kB 大小的圖片轉(zhuǎn)碼后的數(shù)據(jù)流足足有5 000 個字符,2 M 以上的圖片轉(zhuǎn)碼后的數(shù)據(jù)流更是長達(dá)200 行以上,當(dāng)頁面中的一個Html 元素的CSS 樣式超過200 行,整個CSS 的體積會變得異常龐大,繼而影響頁面的渲染[7]。經(jīng)測試,在表1 的頁面中加載的圖片超過200 kB 時,接近40%的概率出現(xiàn)頁面崩潰,90%以上的概率出現(xiàn)一張或數(shù)張圖片空白的情況。綜上,Base64 轉(zhuǎn)碼技術(shù)的應(yīng)用局限在能夠嚴(yán)格控制圖片大小在200 kB 以下的站點(diǎn)中[8]。
表1 Base64對比傳統(tǒng)加載方式的性能優(yōu)勢
一張1 920*1 080 像素的圖片,在每個像素4 字節(jié)大小的情況下,圖片大小將超過8 M,對存儲和傳輸會造成極大的浪費(fèi)。圖像數(shù)據(jù)能夠被壓縮的理論基礎(chǔ)是圖像數(shù)據(jù)的冗余性,并且允許一定程度的失真。假設(shè)該圖片第一行像素的亮度值是[100 100…100(1 920個)],那么第一行的大小就是4字節(jié)*1 920,將第一行重復(fù)數(shù)據(jù)壓縮成[100,1 920]表示1 920 個100亮度值的像素,那么第一行的大小就變成4字節(jié)*2,上述基于圖像空間冗余性的壓縮是目前的主流圖像壓縮原理[9]。主流的Web 開發(fā)語言都有優(yōu)秀的圖片壓縮類庫,例如Java 的Thumb nailator、C#的Drawing和PHP 的GD(Graphic Device 圖像處理擴(kuò)展),出于對高壓縮比的追求,它們支持的多是有失真即允許一定程度的有損壓縮[10]。由于測試平臺由PHP 開發(fā),筆者基于GD 類庫進(jìn)行程序的改編對壓縮前后的圖片進(jìn)行采樣對比。
利用GD 庫壓縮圖片的流程如圖2 所示,依據(jù)不同的圖片格式調(diào)用格式相應(yīng)的圖像加載函數(shù),亦或是根據(jù)圖片的Ur(lUniform resource locator)圖像加載函數(shù)(文中方式),之后創(chuàng)建新畫布以載入原始圖片的圖像資源,在新畫布中完成對圖像資源的壓縮操作,通過壓縮比的調(diào)整對圖像資源的大小和清晰度,進(jìn)而生成壓縮后圖片[11]。
圖2 壓縮流程
上述程序?qū)崿F(xiàn)基于GD 庫圖像壓縮Jpg 格式圖片的基本功能,代碼讀取代表圖像的變量Source,調(diào)整壓縮比,即改變Quality 的數(shù)值,調(diào)用圖像壓縮函數(shù)Imagejpeg 生成變量名為destination 所代表的壓縮后圖片,Gif 和Png 格式的圖片壓縮有各自相似的處理函數(shù)。值得注意的是第一行代碼ini_set(′memory_limit′,′256 M′),擴(kuò)大了PHP默認(rèn)的內(nèi)存限制至256 M字節(jié),經(jīng)多次測試,當(dāng)壓縮的圖片大小在10 M 以上時,過小的內(nèi)存限制會有一定幾率導(dǎo)致應(yīng)用程序的崩潰[12]。
經(jīng)過對不同大小的圖片進(jìn)行不同壓縮比的壓縮,對比壓縮前后圖片,得出如下結(jié)論(見表2):在壓縮比為50 的條件下壓縮后得到的圖片能較好地兼顧清晰度和大小的要求,并且隨著圖片大小的增大,原始圖片與壓縮圖片的大小比例遞增。其余的壓縮比數(shù)值的壓縮較難實(shí)現(xiàn)二者的兼顧,25 壓縮比的壓縮雖然滿足較小圖片的要求,但是清晰度失真較為嚴(yán)重反而影響圖片內(nèi)容的辨識;同理,75 壓縮比生成的圖片雖然保留了大部分原始圖片的像素但是失去了壓縮的意義:圖片大小無明顯變化。
表2 50壓縮比條件下壓縮前后圖片大小
對一張測試平臺中1.2 MB 大小的圖片進(jìn)行壓縮前后采樣對比發(fā)現(xiàn),壓縮后圖片大小約400 kB,較原始圖片大小縮小了3 倍多,在色彩和清晰度方面有輕微的失真不會致使讀者對圖片表達(dá)的原始信息產(chǎn)生誤解,而3 倍的大小差距體現(xiàn)在瀏覽器的加載性能上將會對用戶體驗(yàn)造成巨大的影響。
將表1 中對比Base64 轉(zhuǎn)碼和傳統(tǒng)加載方式應(yīng)用到的圖片壓縮后重新上傳入庫,利用Google Chrome開發(fā)者工具測試頁面加載時間,結(jié)果如表3 所示,原始圖片大小在200 kB 左右時,傳統(tǒng)方式加載和圖片壓縮方式加載的時間分別是281 ms和4 ms,瀏覽器加載速度相差70倍,圖片大小在500 kB 時,Base64轉(zhuǎn)碼方式的加載速度較傳統(tǒng)方式提升20余倍,圖片大小在5M左右時,提升2.44倍,圖片大小越大時,對比Base64轉(zhuǎn)碼方式,圖像壓縮方式的加載時間優(yōu)勢越小。
表3 圖像壓縮技術(shù)的性能優(yōu)勢
根據(jù)表3 所示對比內(nèi)容,顯而易見,圖像壓縮技術(shù)的不足之處在于因壓縮導(dǎo)致像素丟失造成的失真,這種程度的失真作為大圖顯示時會造成肉眼可見的差異,可是作為列表圖片或者縮略圖時,這種差異是能夠忽略不計(jì)的[13]。綜上,解決方案是用戶上傳原始圖片時,后臺同時生成壓縮圖片一并儲存至服務(wù)器,在進(jìn)行列表圖或縮略圖加載時使用壓縮圖片,進(jìn)行大圖顯示時加載原始圖片。由此在頁面加載大量列表圖時,不會由于過多大體積圖片的Http請求而造成頁面卡頓,而且在加載單一大圖時,單一的Http 請求又能夠緩解大體積圖片的下載壓力[14]。
懶加載就是延時加載,用戶有瀏覽需求時手動進(jìn)行加載圖片操作,例如淘寶京東此類購物網(wǎng)站,眾多商品圖片需要集中在一個頁面顯示,1 MB 大小的圖片如果同時有1 000 人訪問,達(dá)到的1 000 并發(fā)量就會產(chǎn)生1G 的帶寬壓力,基于前端的懶加載是解決此類問題的較流行的優(yōu)化技術(shù)[15],類似山東省氣象部門圖片資料云平臺這種屏幕可以完全顯示當(dāng)前頁所需圖片的站點(diǎn),能通過分頁功能展示搜索結(jié)果集中的其他圖片,沒有需要懶加載的內(nèi)容,在加載頁面的同時就能夠加載全部圖片,因此懶加載技術(shù)適用于頁面高度超過屏幕且頁面下方仍有待加載的圖片的站點(diǎn)。
HTTP2 協(xié)議能夠解決瀏覽器連接請求的限制問題。目前主流的瀏覽器,如IE 各版本和筆者測試用的Google Chrome,最大Http 連接數(shù)限制在6 個,瀏覽器的一次Http 請求能夠同時加載6 張圖片,如果頁面待加載圖片過多則會進(jìn)行多次的連接請求從而拖累整個頁面的加載速度[16]。而HTTP2 協(xié)議一個站點(diǎn)只有一個連接,每個請求是一個流數(shù)據(jù),被分為多個二進(jìn)制幀,不同流中的幀可以交錯地發(fā)送,實(shí)現(xiàn)多路復(fù)用,從而解決連接數(shù)限制問題,通過上述論述能夠看出,HTTP2 協(xié)議適用于頁面包含海量圖片的站點(diǎn)。
懶加載和HTTP2 協(xié)議技術(shù)同樣能夠優(yōu)化圖片站點(diǎn)的加載速度,由于不適用于該文測試平臺,筆者不再進(jìn)行相關(guān)的實(shí)驗(yàn)測試。經(jīng)筆者驗(yàn)證的基于系統(tǒng)架構(gòu)和后端開發(fā)的Base64 轉(zhuǎn)碼和圖像壓縮是能夠大幅提高頁面加載速度和用戶體驗(yàn)并且適用范圍更加廣泛的圖片加載優(yōu)化技術(shù),是合格Web 開發(fā)人員的必備技能。