昨天大年初三,晚上 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 在北京的朋友也欢迎过来办公室玩!只要提早跟我约好就好啦~