微信團隊披露:微信介面卡死超級bug“15。。。。”的來龍去脈

jsjsjjs發表於2017-10-10

1、微信超級Bug

大家好,給大家介紹一下,這是Bug:

應該有很多Android的使用者熟悉上面這圖。

(本文同步釋出於:http://www.52im.net/thread-1099-1-1.html)

2、事件背景

國慶前幾天,微信Android大量使用者反饋接收或傳送類似“15。。。。。。。。。。。。。。。”資訊會導致微信聊天介面卡死,程式崩潰。這對微信來說是很嚴重的事情啊,一時半會反饋也鋪天蓋地的過來,我們得知這個問題後,第一時間對這個問題進行了緊急修復並在兩天內覆蓋了全網大部分使用者,最終這個問題得到了解決。追根溯源,毫無疑問這鍋開發小弟來背,這次不能冤枉了產品MM哈哈。

與此同時,很多熱心的網友也開始分析原因,25號當日就有行內大神通過ANR日誌和反編譯debug,一步步推敲出此次ANR的根源,給出了卡死的原因。請受小弟一拜,實在佩服佩服!

詳情可參考連結:http://androidwing.net/index.php/243

下圖是網友分析結果圖:

根據該網友的推敲,此次卡死的真正原因在於:“這個wwk是始終等於0的,也就是不滿足while內部的dVar2的置空條件,也就造成了while死迴圈”。這裡具體怎麼做到動態反編譯的?

這個知乎的回答很詳細:https://www.zhihu.com/question/65828771

3、真正原因揭曉

真正的原因確實如網友分析的,主要是卡在了這個while迴圈裡面,這個迴圈的主要作用是將當前文字內容按具體的規則進行斷句排版,見下圖。

因為dVar2且dVar2.getText一直不為空,一直滿足這個條件,所以造成死迴圈。

而dVar2這個值為null的條件取決於下面這個函式:

“i4”變數實際是斷句演算法返回截斷的實際位置,dvar2.getLength()實際是當前行的文字長度,這裡因為斷句演算法的bug,造成了”i4”這個變數一直返回0,而當前行文字長度dvar2.getLength()是>0的,所以這個dVar2永遠不會被賦值為空。

繼續追根問底:是什麼原因造成斷句演算法一直返回0呢,實際上斷句演算法是呼叫了以下這個函式:

該函式返回了一個物件a其包含兩個引數,一個是斷句的位置(a.wwk),及斷句後的文字長度(a.width),主要是因為在判斷換行的時候,因為考慮到標點符號不應該位於行首這條規則,需要將當前行最後一個非標點符號截斷到下一行,而截斷受另外一條規則限制,截斷不可以為英文或者數字,這導致“15。。。。。。。。。。。。。。。”最後返回截斷的位置為0,並將結果返回,所以才產生了死迴圈,造成這個bug。

4、那麼問題來了

很多網友也開始討論,為什麼要自己排版,放著好端端的系統TextView不用?到底好在哪裡?效果是怎麼樣的?

不著急,諸多問題的來龍去脈得容小弟一一道來。

5、為什麼有這個需求?

實際上,世界上大部分需求都源於使用者。這需求還得得益於之前有幾個使用者會反饋說“微信Android的聊天氣泡好像沒有iOS的美觀,比較死板”。這個問題也引起了我們的關注。

那事實是否如此呢?我們對iOS和Android進行了對比,如下圖:

從效果圖看,iOS確實比Android好看了些,至少最右邊並不會有多餘的padding這麼明顯,簡單來說多餘的padding產生的原因是氣泡寬度受螢幕大小的限制,所以這裡TextView即是氣泡有了最大的寬度限制,當剩下的空間不足以容下一個字元時,系統排版會選擇自動換行,導致了這個問題的產生。

6、又一個問題

那麼,iOS的排版是否就是完美的呢,其實仔細觀察並非這樣,從上圖可以看出,除了Android,iOS也會有這種問題,那就是氣泡中的文字左右參差不齊。

一開始我們懷疑,會不會是微信應用本身使用該元件不當的原因造成,而非系統元件的問題。於是乎,在手機上,我們隨便找了一些熱門app,仔細對比,同樣的問題依然存在。

知乎:

掘金:

支付寶:

等等。。。

而且除了移動端,pc端同樣也有諸類問題。結合上面這些對比,確實市面上大部分應用都存在這個問題。通過這次反饋,我們也開始在思考能不能在移動客戶端的文字排版上做得更人性化一些,體驗上更好?。就這個問題,我們找了設計的同學一起探討,認為確實有這個必要。於是就開始有了下一步。

7、排版要怎麼排?

對於文字排版,這容易讓人想起,“我的(word)哥”,微軟對於這款應用,有沒有一些文字左右對齊的手段或者方案可以參考呢?

下圖為word的左對齊效果,也就是Android的TextView預設對其方式:

下圖為word的居中‘硬’對齊效果:

下圖為word的居中‘軟’對齊效果:

從這種效果上看,“軟對齊方式”更美觀,體驗最好。於是我們能想到的就是動態調整字間距的方式來實現這種效果(word也是這麼實現的)。

那既然要動態調整字型間距,是不是可以一味的這麼做就可以?答案當然不是,如果這麼做就像‘硬對齊方式’一樣,顯得過於生硬了。

我們就這個問題跟設計組的同事進行討論,通過他們的調研及嘗試,得出了一個合理的方案,那就是最多允許有一個英文字元寬度的調整範圍,將調整的寬度平均分配到當前行每個字元中去,對使用者來說影響是最小的,同時也保持了一定的美觀。

8、實踐自定義排版

對於Android來說,實現這條規則並不難,要麼是改造系統TextView,要麼自己寫個自定義view實現文字排版及渲染,最後我們採用了後者這個方案。

原因在於:

系統TextView真正排版及繪製的邏輯不在其本身,而是交給三個繼承了Layout的子類負責,分別為StaticLayout、DynamicLayout、BoringLayout,我們更常用的是StaticLayout,它只負責靜態的文書處理,關於各自Layout的區別,這裡了就不展開講了。系統TextView並沒有暴露介面去代理它們。當然沒有介面不意味著做不到,我們完全可以通過反射等手段代理它,但其實這麼做的話,代價是比較大的。

原因有三:

1)其一:從Android 2.3到Android 8.0,TextView的程式碼雖說變化不會很大,但從Layout來看,實現的邏輯或者介面也好都有所變更,如果通過這個方式,代理的相容性會是一個問題;

2)其二:TextView堪稱Android最複雜的一個元件之一,幾個Layout邏輯程式碼的複雜程度很高,自己實現所有的Layout介面,本身就是一件複雜且工作量很大的工作;

3)其三:實際上自己實現一個Layout,基本上就實現了一個顯示元件,排版和渲染都是要處理的,所以這樣實現的意義不大,甚至反而不靈活。

迴歸正題,我們對系統TextView的規則進行對比,最後我們確定了以下幾條規則:

1、最多允許有一個字母字元寬度的來調整字間距;

2、對於標點符號儘量規避不出現在行首;

3、對於英文單詞或數字不截斷排版。

於是我們開始進行簡單的demo實現。效果如下圖:

對比優化前的效果,確實這麼做效果是明顯的。但仔細觀察,還是會發現,對於一些特殊的中文全形符號(如,《》()【】等)因為有多餘的padding存在,放在行首和行末也會導致參差不齊的效果。

於是我們多增加了一條規則:

對一些常見的有多餘padding的全形符號位於行首或行末時,預設減去多餘的padding來達到更好的對齊效果。

最後的優化效果,如圖:

最後一張是應用了4條規則的效果圖,整體文字的對齊效果比系統預設的排版改善了不少。

9、問題又來了

那既然效果是不錯的,是否存在其他問題?確實如此。

9.1 小語種處理問題

因為微信對小語種是支援的,對於一些特殊的小語種,如泰語,阿拉伯語等,泰語的排版方式並非簡單的橫排,字元與字元之間是有上下關係的,而對於阿拉伯語,是從右往左排列的。如果只是按上面所講的幾個規則,那麼排版後的效果肯定是不合理的。

考慮到小語種存在多樣性,排版規則不統一,而且使用小語種使用者比例小,但也不能讓其排版錯誤不管,所以對於這種情況,我們通過一個簡單的正規表示式去匹配是否屬於能處理的字串範圍內,這就是為什麼有網友分析”15。。。。。。。。”這個事件時,一開始會懷疑是正則匹配耗時造成的。

下圖為該網友的分析:

而實際上,這個簡單的正規表示式,如該網友測試的一樣,處理起來很快,基本都在1ms內,對效能的影響可忽略。通過正則去判斷後,如果是可處理的字串則應用上面的規則進行排版,如果是特殊的字串,則用系統的TextView代理顯示。

9.2 適配率問題

既然小語種的問題可以解決,但這裡又產生一個問題,現網上的使用者, 使用特殊字元的頻率多高?這問題直接關係到我們這個排版元件的適配率,也就是對使用者體驗改善多少?在我們看來,一般人並不會發些奇奇怪怪的符號在微信裡面,所以能應用上這個排版規則的應該佔大多數。當然這裡只是猜想,如果這樣確定可行性也太草率了。

於是我們針對這個問題,進行了一輪灰度,灰度的結果如下:

通過這次灰度,現網使用者能應用上該元件適配的情況達到了預期的結果。

9.3 效能問題

如果該元件的效能跟系統相差太多,甚至嚴重影響幀率,造成使用者卡頓,這當然也是不可取的。我們針對這個問題,進行了本地的自動化幀率測試及與系統TextView進行函式間的對比。

下圖是實驗資料:

得出結論:

從微觀上:通過函式進行對比,CellTextView對比系統TextView效能稍差2倍,主要差距在於繪製文字時需要單字調整間距;

從巨集觀上:CellTextView對實際幀率的影響較小,使用者無明顯感知效能變差。

通過以上的嘗試及灰度結果來看,做這個事情其實是很有意義的,那麼最後也敲定下了這個優化方案。

10、事件結尾

整個需求的來龍去脈就是這樣子的,其實梳理這個過程的來龍去脈來,一來可以讓自己不斷反思該過程存在的一些問題,二來呢,因為本次bug確實對大家造成了不好的影響(真的是深感歉意啊!),可以讓大家清楚這個事情是怎麼發生的,至少大家不會卡得不明不白的。

寫程式碼萬萬要小心謹慎,考慮周全啊。這次痛定思痛,吃一塹,長一智吧。願天下的程式統統沒有bug。對,統統沒有!

最後貼上一張優化後的效果圖:

文章寫得不好的地方,望見諒,大神莫噴莫噴。小弟我要背鍋去面壁了。

(原文連結:點此進入

附錄:更多微信、QQ技術文章彙總

[1] 有關QQ、微信的技術文章:

微信團隊披露:微信介面卡死超級bug“15。。。。”的來龍去脈

QQ 18年:解密8億月活的QQ後臺服務介面隔離技術

月活8.89億的超級IM微信是如何進行Android端相容測試的

以手機QQ為例探討移動端IM中的“輕應用”

一篇文章get微信開源移動端資料庫元件WCDB的一切!

微信客戶端團隊負責人技術訪談:如何著手客戶端效能監控和優化

微信後臺基於時間序的海量資料冷熱分級架構設計實踐

微信團隊原創分享:Android版微信的臃腫之困與模組化實踐之路

微信後臺團隊:微信後臺非同步訊息佇列的優化升級實踐分享

微信團隊原創分享:微信客戶端SQLite資料庫損壞修復實踐

騰訊原創分享(一):如何大幅提升行動網路下手機QQ的圖片傳輸速度和成功率

騰訊原創分享(二):如何大幅壓縮行動網路下APP的流量消耗(下篇)

騰訊原創分享(二):如何大幅壓縮行動網路下APP的流量消耗(上篇)

微信Mars:微信內部正在使用的網路層封裝庫,即將開源

如約而至:微信自用的移動端IM網路層跨平臺元件庫Mars已正式開源

開源libco庫:單機千萬連線、支撐微信8億使用者的後臺框架基石 [原始碼下載]

微信新一代通訊安全解決方案:基於TLS1.3的MMTLS詳解

微信團隊原創分享:Android版微信後臺保活實戰分享(程式保活篇)

微信團隊原創分享:Android版微信後臺保活實戰分享(網路保活篇)

Android版微信從300KB到30MB的技術演進(PPT講稿) [附件下載]

微信團隊原創分享:Android版微信從300KB到30MB的技術演進

微信技術總監談架構:微信之道——大道至簡(演講全文)

微信技術總監談架構:微信之道——大道至簡(PPT講稿) [附件下載]

如何解讀《微信技術總監談架構:微信之道——大道至簡》

微信海量使用者背後的後臺系統儲存架構(視訊+PPT) [附件下載]

微信非同步化改造實踐:8億月活、單機千萬連線背後的後臺解決方案

微信朋友圈海量技術之道PPT [附件下載]

微信對網路影響的技術試驗及分析(論文全文)

一份微信後臺技術架構的總結性筆記

架構之道:3個程式設計師成就微信朋友圈日均10億釋出量[有視訊]

快速裂變:見證微信強大後臺架構從0到1的演進歷程(一)

快速裂變:見證微信強大後臺架構從0到1的演進歷程(二)

微信團隊原創分享:Android記憶體洩漏監控和優化技巧總結

全面總結iOS版微信升級iOS9遇到的各種“坑”

微信團隊原創資源混淆工具:讓你的APK立減1M

微信團隊原創Android資源混淆工具:AndResGuard [有原始碼]

Android版微信安裝包“減肥”實戰記錄

iOS版微信安裝包“減肥”實戰記錄

移動端IM實踐:iOS版微信介面卡頓監測方案

微信“紅包照片”背後的技術難題

移動端IM實踐:iOS版微信小視訊功能技術方案實錄

移動端IM實踐:Android版微信如何大幅提升互動效能(一)

移動端IM實踐:Android版微信如何大幅提升互動效能(二)

移動端IM實踐:實現Android版微信的智慧心跳機制

移動端IM實踐:WhatsApp、Line、微信的心跳策略分析

移動端IM實踐:谷歌訊息推送服務(GCM)研究(來自微信)

移動端IM實踐:iOS版微信的多裝置字型適配方案探討

信鴿團隊原創:一起走過 iOS10 上訊息推送(APNS)的坑

騰訊信鴿技術分享:百億級實時訊息推送的實戰經驗

>>更多同類文章 ……

[2] 有關QQ、微信的技術故事:

技術往事:創業初期的騰訊——16年前的冬天,誰動了馬化騰的程式碼

技術往事:史上最全QQ圖示變遷過程,追尋IM巨人的演進歷史

技術往事:“QQ群”和“微信紅包”是怎麼來的?

開發往事:深度講述2010到2015,微信一路風雨的背後

開發往事:微信千年不變的那張閃屏圖片的由來

開發往事:記錄微信3.0版背後的故事(距微信1.0釋出9個月時)

一個微信實習生自述:我眼中的微信開發團隊

首次揭祕:QQ實時視訊聊天背後的神祕組織

>>更多同類文章 ……

(本文同步釋出於:http://www.52im.net/thread-1099-1-1.html)


相關文章