最近參與了一個(gè)微信小程序項(xiàng)目,里面需要做一個(gè)圖表,故事就這么開始了。。。 圖表組件支持的少搜了一圈組件,發(fā)現(xiàn) 圖表類組件在小程序生態(tài)里面好殘缺 。。。像 echarts 這類豐富的圖表組件庫(kù)還沒有適配小程序,能夠想得到的原因大概有:
最終,我們是在 wx-charts 這個(gè)組件上進(jìn)行了一些二次開發(fā)才完成的圖表組件。 js 執(zhí)行效率低除了社區(qū)支持不足的問(wèn)題以外,還遇到了 js 執(zhí)行效率低 的問(wèn)題。 需要說(shuō)明的是,我們要在圖表上實(shí)現(xiàn)拖拽圖表滾動(dòng)的效果,wx-charts 并不支持,團(tuán)隊(duì)里的小伙伴自己擼了一個(gè)。可是同樣的代碼,在 iPhone7 上運(yùn)行流暢程度勉強(qiáng)可以接受,但是在我的 iPhone6 上神卡。小程序開發(fā)工具在真機(jī) profiling 方面的支持基本沒有,只能用 log 大法來(lái)定位問(wèn)題。 要說(shuō)拖拽功能的開發(fā)套路:主要就是監(jiān)聽 touch 事件,在 touchstart 事件里,記錄手指的起始位置,在 touchmove 事件里計(jì)算手指位置的偏移,根據(jù)偏移重新畫一幀。跟蹤性能的方法就是使用日志記錄下來(lái)每一幀的繪制時(shí)間。 實(shí)測(cè)發(fā)現(xiàn), iPhone6 上平均每幀要 100~120 ms,也就是說(shuō)只能達(dá)到 8~10 fps。。。可不就是卡嘛。。。 大概想了一下,性能問(wèn)題應(yīng)該出在以下幾處:
期初都沒懷疑 js 的效率問(wèn)題。先是懷疑問(wèn)題出在第二點(diǎn)上,因?yàn)槲覀円龅氖且粋€(gè)左右滑動(dòng)的圖表,在顯示區(qū)域以外的數(shù)據(jù)點(diǎn)還是很多的,所以先是優(yōu)化了 canvas 接口的調(diào)用次數(shù),不在顯示區(qū)域里面的數(shù)據(jù)點(diǎn)全部都過(guò)濾掉。優(yōu)化之后看結(jié)果,性能確實(shí)有提升,但是也就是能提升到 12~15 fps 的水平,性能提升不明顯。 趕巧那段時(shí)間,有人在討論 Node.js v8.0 上 forEach 的性能提升。再看 wx-charts 里面用了大量的 forEach/map 方法。抱著試一試的態(tài)度,把里面最關(guān)鍵的部分全都改寫成普通的 for 循環(huán)。結(jié)果驚人地發(fā)現(xiàn),每幀的繪制時(shí)間降到了 30~40 ms。 結(jié)論,實(shí)際測(cè)試發(fā)現(xiàn):在 iPhone6上,forEach/map 方法的性能問(wèn)題還是比較明顯的。平時(shí)做一些普通的功能開發(fā)看不出來(lái),但是如果是在 canvas 圖表這類對(duì)性能要求比較高的場(chǎng)景下,問(wèn)題就很明顯了。 touch 事件大量積壓除了 js 執(zhí)行效率問(wèn)題外,我發(fā)現(xiàn)小程序的 touch 事件有明顯的延遲現(xiàn)象。準(zhǔn)確的說(shuō)是:事件觸發(fā)的時(shí)間間隔低,如果事件回調(diào)函數(shù)執(zhí)行時(shí)間長(zhǎng)的話,touch 事件不會(huì)被丟棄而是會(huì)大量積壓。像上面說(shuō)的情況,每次 touchmove 時(shí)間回調(diào)要執(zhí)行 100+ ms 可是 touchmove 事件目測(cè)不超過(guò) 20ms 就會(huì)觸發(fā)一次。所以如果快速滑動(dòng)屏幕,圖表就跟上了發(fā)條一樣,會(huì)延遲繪制很多次。 上面雖然優(yōu)化了性能,但是還不能避免事件積壓的問(wèn)題。最終是加了一個(gè)控制邏輯,將 touch 事件的頻率降低到每秒 40 次,代碼大概如下: const LIMIT = 40; let prev = 0; function onTouchMove(e) { const now = new Date(); const duration = prev - now; if (duration < Math.floor(1000 / LIMIT)) { return; } prev = now; // draw canvas... } 其他問(wèn)題除了上面提到的 canvas 圖表問(wèn)題,做一次小程序之后還發(fā)現(xiàn)了一些問(wèn)題,希望大家開發(fā)的時(shí)候提前準(zhǔn)備好應(yīng)對(duì)措施:
|