一键释放iOS 64位App潜力

作者:eddiecmchen , PCG客户端开发工程师
| 导语 把我的iphone XR扶起来 , 它还能再顶一会儿~
背景远在IOS 11时期(2017年) , 苹果就发公告要求所有需要上架AppStore的应用都必须支持64位 。32位应用不再支持上架与运行 。

一键释放iOS 64位App潜力

文章插图
 
升级64位应用有什么好处呢?(以下内容纯摘抄 , 客官可以直接跳过)
  • 指针字长更长 , 可使用的虚拟内存更大 , 摆脱32位下受限的4G内存空间
    • 16 bit = 65,536 bytes (64 Kilobytes)
    • 32 bit = 4,294,967,296 bytes (4 Gigabytes)
    • 64 bit = 18,446,744,073,709,551,616 (16 Exabytes)
  • 寄存器更多 , 减少内存读写 , 加快执行速度
这里我们要注意的是:虚拟内存确实比纯32位多了 , 但是App到底能用多少 , 是否跟宣传一样接近16EB?下面将会展开聊聊 , 我们先来看一个Crash 。
一个长期存在的幽灵我们先来看下面的一个内存导致的崩溃 , JSC在使用bmalloc尝试进行内存分配时 , 提示OOM导致了SIGTRAP 。
Last Exception :0JAVAScriptCore0x000000018b777570 _pas_panic_on_out_of_memory_error1JavaScriptCore0x000000018b72e918 _bmalloc_try_iso_allocate_impl_impl_slow2JavaScriptCore0x000000018b73d3d8 _bmalloc_heap_config_specialized_local_allocator_try_allocate_small_segregated_slow +59523JavaScriptCore0x000000018b7276f8 _bmalloc_allocate_impl_casual_case +8004JavaScriptCore0x000000018c60d494 JSC::PropertyTable::create(JSC::VM&, unsigned int) +2445JavaScriptCore0x000000018c66ba74 JSC::Structure::materializePropertyTable(JSC::VM&, bool) +3246JavaScriptCore0x000000018c66dfac JSC::Structure::changePrototypeTransition(JSC::VM&, JSC::Structure*, JSC::JSValue, JSC::DeferredStructureTransitionWatchpointFire&) +6127JavaScriptCore0x000000018c559930 JSC::JSObject::setPrototypeDirect(JSC::VM&, JSC::JSValue) +1928JavaScriptCore0x000000018c559e40 JSC::JSObject::setPrototypeWithCycleCheck(JSC::VM&, JSC::JSGlobalObject*, JSC::JSValue, bool) +3169JavaScriptCore0x000000018c4f580c JSC::globalFuncProtoSetter(JSC::JSGlobalObject*, JSC::CallFrame*) +19210 JavaScriptCore0x000000018ba1f7a8 _vmEntryToNative +28011 JavaScriptCore0x000000018c1b0cd0 JSC::Interpreter::executeCall(JSC::JSGlobalObject*, JSC::JSObject*, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) +61612 JavaScriptCore0x000000018c474ecc JSC::GetterSetter::callSetter(JSC::JSGlobalObject*, JSC::JSValue, JSC::JSValue, bool) +21213 JavaScriptCore0x000000018c5b6264 JSC::JSGenericTypedArrayView<JSC::Uint8Adaptor>::put(JSC::JSCell*, JSC::JSGlobalObject*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&) +61214 JavaScriptCore0x000000018c2c2ecc _llint_slow_path_put_by_id +3244// 忽略多余重复堆栈37 JavaScriptCore0x000000018ba1f5fc _vmEntryToJavaScript +26438 JavaScriptCore0x000000018c1b0c7c JSC::Interpreter::executeCall(JSC::JSGlobalObject*, JSC::JSObject*, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) +53239 JavaScriptCore0x000000018bac7ae4 _JSObjectCallAsFunction +56840 mttlite0x0000000102a54914 hippy::napi::JSCCtx::CallFunction(std::__1::shared_ptr<hippy::napi::CtxValue> const&, unsigned long, std::__1::shared_ptr<hippy::napi::CtxValue> const*) (js_native_api_value_jsc.cc:406)41 mttlite0x0000000102a664e0 _ZNSt3__110__function6__funcIZN11TimerModule5StartERKN5hippy4napi12CallbackInfoEbE3$_4NS_9allocatorIS8_EEFvvEEclEv (memory:3237)42 mttlite0x0000000102a63018 hippy::base::TaskRunner::Run() (memory:3237)43 mttlite0x0000000102a64974 ThreadEntry (thread.cc:0)44 libsystem_pthread.dylib0x00000001dc129348 __pthread_start +116------Exception Type: SIGTRAP Exception Codes: fault addr: 0x000000018b777570Crashed Thread: 48 hippy.js这个OOM问题 , 与iOS上常见的OOM不一样 。按照常规的理解 , 当App内存不足的时候 , 正常会触发系统的Jetsam机制杀死App 。在系统日志中会留下Jetsam相关日志 , 理论上不会在Bugly等异常上报中发现 。但这一类崩溃却一直在产生上报 , 并且低内存的崩溃堆栈表现形式有很多种 。
以上的JSC崩溃问题已经存在很长一段时间了(至少2年) , 而且崩溃堆栈都集中在JSC执行JS代码的过程中 , 长期缺乏JS相关的监控与Debug工具导致该问题一直无法解决 。
虽然堆栈上有明确的原因说明是OOM , 但我们观察到有不少用户实际上物理内存空间还是足够的:
一键释放iOS 64位App潜力

文章插图
 
两年前 , 冲浪的时候偶然看来了来自微视同学的Case总结:《OOM与内存》


推荐阅读