昨天大年初三,晚上 11 點半,忽然被個人同事金司機敲了一下:「幫我看看這個實驗吧,我們還一塊兒 review 的……」面試
難道這個實驗能出問題?公司的 code review 制度作得很完善,每一行代碼都要過 review ;而我同事這段還專門放到 review 會上,七八個腦殼湊在一塊兒盯着看過的。這還能有問題嗎?swift
但數據不會說謊:明明開給使用中文的用戶的實驗,從數據上看卻涌入了大批的美國用戶。bash
倉鼠:「從代碼上看真的徹底沒問題。」多線程
同事:「可能在美國確實有不少使用中文的人。出乎意料啊!」app
倉鼠:「這個確定有問題的,美國是中國的4倍……真是這樣,我們能夠解放美帝了……」函數
一塊兒看了兩個多小時,終於發現了問題所在,原來是被 Swift 坑了。讓咱們來看看代碼是怎麼寫的吧!性能
出現問題的相關代碼能夠大概簡化以下:優化
class StaticVarTestClass {
static var myStaticVar: Bool = {
print("initializing static var!")
return false
}()
}
class SomeOtherClass {
static func foo(myEnum: SomeEnum) {
print("before!")
switch myEnum {
case a:
print("into case a!")
print(StaticVarTestClass.myStaticVar)
case b: break
}
print("after!")
}
}
// 調用的時候
print("call foo!")
SomeOtherClass.foo(.b)
複製代碼
上面這段代碼,應該輸出什麼結果呢?ui
要解答這個問題,須要先弄明白 static var 的初始化時機。Swift 官方文檔是這麼說的:spa
Stored type properties are lazily initialized on their first access. They are guaranteed to be initialized only once, even when accessed by multiple threads simultaneously, and they do not need to be marked with the lazy modifier.
簡單翻譯下:人家文檔裏說了,static var 是在第一次訪問的時候懶加載的,不須要寫 lazy
關鍵字也能保證是懶加載。並且能保證即便是多線程訪問,都會只初始化一次(因此能夠用來作單例)。順帶提醒一個小知識,非 static 的 lazy var 是不能保證多線程訪問下只初始化一次的。
這不是說得很明白了嗎?那麼從咱們的代碼看,調用 foo
的時候,傳死了一個 .b
,所以根本走不到 .a
的分支裏,也就不會訪問到 myStaticVar
,也就不會觸發它的懶加載。所以,console 輸出應該是:
call foo!
before!
after!
複製代碼
實際上,debug 編譯的輸出結果的確是這樣的。可是,release 編譯的輸出結果出人意料:
call foo!
initializing static var!
before!
after!
複製代碼
release 下,若是把斷點打在 print("into case a!")
上,斷點不會停。若是打在 print("initializing static var!")
上,斷點是會停的,而且順着調用棧往上找,能找到停在 print(StaticVarTestClass.myStaticVar)
這一句,儘管代碼的實際執行根本就沒走進 case a
這個分支。
這是什麼狀況,說好的懶加載呢?但運行結果擺在眼前,何況線上收集到的大量數據也證實了這個殘酷的現實:static var 的懶加載並非那麼靠譜,實際上,它的初始化時機並不肯定。文檔裏所說的「懶加載」只能大概理解成,它不會在 app 一啓動就全面加載,不用擔憂性能。可是在咱們遇到的這個 case 下,實際路徑並無訪問到這個變量;只是調到了 foo
這個函數,而這個函數裏涉及到了它。多是一個編譯的優化,它先把可能用到的 static var 給預備好了,這就觸發了 static var 的初始化。
若是用我上面提供的代碼寫個 demo,極可能會發現並不能重現這樣的結果,我和金司機分別寫的 demo 都沒有重現;可是在咱們的工程裏是穩定重現的,而實際工程很是複雜,不知道是哪一點觸發了這個問題。沒處說理,只能記住這個血的教訓:能夠不用擔憂 static var 會影響 app 的冷啓動性能,可是業務邏輯上不能依賴它的懶加載特性,它是有可能在沒訪問到的狀況下預先加載的。
倉鼠原本已經對公司的推薦獎死心了,可是今年意外成功了一次,所以賺外快的心又蠢蠢欲動;容我在個人文章結尾打個小廣告:Airbnb 北京辦公室今年大量招聘 iOS、Android 工程師~ 幾個常見 Q&A:
Q: 崗位有什麼要求嗎?
A: 硬性要求的話,就是大致 3 年以上的 iOS/Android 開發經驗就能夠~ 而後我以爲有大中廠的經歷或者畢業學校比較好,以上二者有其一簡歷會比較容易過~
Q: 對英語有要求嗎?
A: 零要求!只要寫代碼不寫拼音就好……
Q: 面試都面啥?
A: 實際工做 90% swift ,但面試不須要會。我特別喜歡這公司 iOS 面試的一點,就是徹底不考知識性問題,像「消息機制分爲哪幾步」……從電話面試到現場面試,全部環節全都是上機寫代碼,並且題目全都是開發工做中常見的功能、解決工程中實際出現的 bug,沒有任何偏難怪的東西。咱們主要會看開發的熟練度、代碼結構的設計、解決問題的能力。
Q: 薪資怎麼樣?福利呢?
A: 我猜想薪水能至少跟 BAT 差很少,另外還給很多股票。公司年年嚷着明年上市,但確實仍是比較有但願要上市的。福利方面,幾個比較給力的:15 天年假 + 一週左右聖誕假;高端醫療保險,三甲醫院特需、國際部隨便看,生孩子好像和氣家全包,公司直付;入職總部培訓三週,以後還有很多出差機會,能夠順便去舊金山玩。其餘就跟正常大公司差很少了。
Q: 有沒有機會 transfer 到總部?
A: 有機會,但不保證。
Q: 我想報名 / 能夠推薦朋友嗎?
A: 私信我吧!我會告訴你郵箱,而後發一份簡歷(中文便可)給我就好~ 推薦朋友若是成功的話,我也不準諾啥電子產品了,給您轉一萬人民幣現金好了您想買什麼本身買 :)
還有任何問題,倉鼠都很願意幫忙解答~ 能夠加個人 QQ 羣倉鼠洞:546948320 在北京的朋友也歡迎過來辦公室玩!只要提早跟我約好就好啦~