在今天继续我的传奇故事,反对荒谬的应用程序大小,我来看看联合航空公司';iOS应用。
我就在那里,登上我的联合飞机,走过一排又一排的座位,这时我终于注意到它们都没有内置头枕屏幕。我发誓在订票前我仔细检查了一下。当我坐下时,一条对讲机广播提醒乘客,如果他们想观看机上电影和娱乐节目,请下载United应用程序。这不是我第一次看到这个,夏威夷航空公司以前也对我做过同样的特技表演。通过让乘客携带硬件来降低成本已经成为航空业的一种流行趋势,作为额外的奖励,他们可以强行进入你梦寐以求的已安装应用程序列表。那就不用担心了,我会下载他们的应用程序,然后上路…
注意:正如我在前一篇文章中提到的,对于iOS来说,下载和安装大小是一个棘手的问题。苹果严重压缩了下载量(这太棒了!)但这并不容易找到。苹果还支持增量下载,这意味着在某些情况下,你可以下载“不同”的应用程序二进制文件(也很神奇!),但这在实际设备上更难测量。就我而言,在我的航班起飞前,我第一次尝试在跑道上下载United应用程序。
如此臃肿的应用给人留下了深刻的印象,也让我很感兴趣——大多数臃肿的应用都在100-200MB的范围内,而不是400MB。Netflix本身只有101.5MB,United真的需要4倍的空间来播放电影吗?我们来看看。
使用这个奇妙的工具,你可以在本地下载应用程序二进制文件以供检查。下载IPA文件后,只需将文件扩展名重命名为zip,然后像往常一样进行解压缩。
---UnitedCustomerFacingIPhone。应用程序-----------414.8 MiB[█████████████████████ ] /框架3.8 MiB[]/插件2.3 MiB[]/LPMessagingSDKModels。捆绑2.3 MiB[]UnitedCustomerFacingIPhone 1.5 MiB[]资产。汽车1.4MIB[]/_代码签名1.4MIB[]/手表500.0kib[]/按钮。捆绑40.0千磅[]/SC_信息12.0千磅[]信息。plist 12.0千磅[]每基。lproj 8.0 KiB[]受电子邮件保护]~ipad。png 8.0 KiB[][受电子邮件保护]4.0 KiB[]/UALFlightStatus。捆绑4.0 KiB[]/UALReservation。捆绑4.0 KiB[]/UALBagTracking。捆绑4.0 KiB[]/UALPayment。捆绑4.0 KiB[]/UALBooking。捆绑包4.0 KiB[]可本地化。字符串4.0 KiB[]PkgInfo
几乎所有的应用程序大小都来自框架!不过,这并不奇怪,将代码推入框架已经是一段时间以来的最佳实践。
---UnitedCustomerFacingIPhone。app/Frameworks/。。86.0 MiB[█████████████████████ ] /乌拉普科雷。框架44.7 MiB[██████████▌ ] /UALBooking。框架40.3 MiB[█████████▌ ] /NodeMobile。框架36.1 MiB[████████▌ ] /UALHomeScreen。框架25.7 MiB[██████ ] /阿尔切金。框架25.0 MiB[██████ ] /保存。框架17.5 MiB[████ ] /UALCommonUI。框架15.9 MiB[███▌ ] /UAL支付。框架14.7 MiB[███▌ ] /蝗虫。框架8.7 MiB[██ ] /地图盒。框架8.6 MiB[██ ] /无人机状态。框架8.6 MiB[██ ] /widevine_cdm_安全ios。框架7.2 MiB[█▌ ] /LPMessagingSDK。框架6.8 MiB[█▌ ] /网络验证。框架6.6 MiB[█▌ ] /布林肯卡。框架6.4 MiB[█▌ ] /UALMYAAccount。框架5.7 MiB[█ ] /WebRTC。框架5.3 MiB[█ ] /统一层图书馆。框架4.4 MiB[█ ] /乌洛金。框架4.1 MiB[▌ ] /UALAirportMaps。框架3.9 MiB[▌ ] /INPlayUtils。框架3.5 MiB[▌ ] /u娱乐。框架2.5 MiB[▌ ] /UALUnitedClubs。框架2.4 MiB[▌ ] /UALBagTracking。框架2.3 MiB[▌ ] /达什托尔斯。框架2.3 MiB[▌ ] /艾美。框架1.9 MiB[]/AcquireIOSDK。框架1.8 MiB[]/优化。framework 1.8 MiB[]/GoogleInteractiveMediads。框架1.7 MiB[]/Qualtrics。框架1.7 MiB[]/UALDocumentScanning。框架1.4 MiB[]/PACStreaming。框架1.3 MiB[]/INPLAYControlsLibrary。框架1.1 MiB[]/JumioCore。框架968.0 KiB[]/UALCommonSearch。框架892.0 KiB[]/PACCoreKit。框架876.0 KiB[]/UnifiedPlayerViewController。框架868.0 KiB[]/SocketIO。框架856.0 KiB[]/INPLAYiOSLibrary。框架632.0 KiB[]/UpLiftSDK。框架540.0千磅[]/红蜘蛛。框架424.0 KiB[]/MapboxMobileEvents。框架384.0 KiB[]/McPicker。框架284.0 KiB[]/UALUnifiedPlayer。框架164.0 KiB[]/iosadbrary。框架124.0 KiB[]/iosvastadbrary。框架
---框架/UALAppCore。框架/。。76.8 MiB[███████████████ ] UALAppCore 6.9 MiB[█ ] /UnitediPhoneCoreDataModel。momd 760.0基布[]默认机场。json 708.0 KiB[]UA_AppCore_数据库。sqlite 412.0 KiB[]/SC_Info 116.0 KiB[]/UAAppCoreDataModel。momd 108.0 KiB[]/HomeScreendaModel。momd 44.0 KiB[]UAAppCoreDataModelv3v4。cdm 36.0 KiB[]/_代码签名20.0 KiB[]/ReservationDataModel。momd 16.0 KiB[]登录数据库v3_v4。清洁发展机制
好的,所以绝大多数尺寸都在UALAppCore内。框架本身。77MB对于一个框架来说非常大。我们可以使用可靠的nm工具进一步深入研究框架的符号。
➜ UnitedCustomerFacingIPhone。应用程序nm-m框架/UALAppCore。framework/UALAppCore000000000153c36c(_-TEXT,_-TEXT)非外部+[CYFBackgroundEventFormatter formatEvent:]000000000 1542Bec(_-TEXT,__-TEXT)非外部+[CYFBackgroundEventManager sharedBackgroundEventManager]000000000 1538764(__u-TEXT,___-TEXT)非外部+[CYFChallengeActionView showDialog:标题:消息:取消按钮:委托:]000000000 1533E78(_文本,_文本)非外部+[CyfCryptorProgressTheme标准主题]000000000 1533E50(_文本,_文本)非外部+[CyfCryptorProgressTheme主题名:]000000000 152F3D4(_文本,__;文本)非外部+[CyfCryptoryChallengeAction sharedInstance]000000000 152A99C(____;文本,__;文本)非外部+[CYFDCTEncoder DCTENCE:withLength:and Compression:[CYFDCTEncoder DCTENCE:withLength:[CYFDCTEncoder DCTENCE:withLength:[CYFDCTEncoder:withLength:and Compression:[CYFDCTEncoder:withLength:and Compression:]000000000 152AFF4(_______;TEXT,_________。。。
现在我们有进展了。我不擅长将符号打包到可执行文件中,但我确实记得Swift符号需要剥离,不像ObjC(事实检查pls?)。看看能不能找到。
000000000 1A4C760(__数据,_llvm_prf_cnts)非外部(是一个私有外部)___;profc_/Users/uasvcagent/Go_Pipeline/pipelines/UA AppCore发布iOS/UALAppCore/Classes/CoreData/Handlers/HomeScreen/UASudokuPuzzle。swift:$S10UALAPPCORE14UASUDOKUYULDSV06CreateB10DataObject33_4C5; ded22C8FD26C81E26FA4955E2A9410所有困难3Num6YULDS5Int16V_s5Int32VS2StF0000000001a4c7a0(数据,llvm_prf_cnts)非外部(是一个私有外部)___profc_/Users/uasvcagent/Go_Pipeline/pipelines/UA AppCore发布iOS/UALAppCore/Classes/CoreData/Handlers/HomeScreen/UASudokuPuzzle。swift:$S10UALAPPCORE14UASUDOKUQUIZV19FIXUNRESPONSVEGAME33_4C5DED22C8FD26C81E26FA4955E2A94ALLYF0000000001A4C808(_数据,__llvm_prf_cnts)非外部(是一个私有的外部)_____profc_U/Users/uasvcagent/Go_U管道/管道/UA应用核心发布iOS/UALAppCore/Classes/Classes/Classes/CORE/CORE/CORE/CORE/CORE/CORE。swift:$S10UALAPPCORE14UASUDOKUQUIZV19FIXUNRESPONSVEGAME33_4C5ded22C8FD26C81E26FA4955E2A94ALLYFSSYKXEFU0_0000000001a4c800(__数据,__;llvm_prf_cnts)非外部(是一个私有的外部)_______u专业/用户/uasvcagent/Go管道/管道/管道/UA应用核心发布iOS/uLappCore/uPCore/uCore/Classes/Core/。swift:$S10UALAPPCORE14UASUDOKUQUIZV19FIXUNRESPONSVEGAME33_4C5ded22C8FD26C81E26FA4955E2A94ALLYFSSYKXEFU_0000000001a4c7c8(__数据,__;llvm_prf_cnts)非外部(是一个私有的外部)______u专业/用户/uSvCAgent/Go管道/管道/UA应用核心发布iOS/uLappCore/class/Core/Core/Core/Core/Core/Core/。swift:$S10UALAPPCORE14UASUDOKUQUIZV21预填充CDMANAGER33_4C5; ded22C8FD26C81E26FA4955E2A94allaa0B11数据管理器SGYF0000000001A4C7D8(uuuu数据,uuuu llvm_prf_cnts)非外部(是一个私有的外部)uuuuuuuuuu专业/用户/uSvCAgent/Go管道/管道/UA应用核心发布iOS/uLappCore/Classes/Core/Core/Core/Core/Core数据处理程序/HomeScreen/UASUDOKUKUKUK。swift:$S10UALAPPCORE14UASUDOKUQUIZV21预填充CDMANAGER33_4C5; ded22C8FD26C81E26FA4955E2A94allaa0B11数据管理器SGYFYCFU_0000000001a4c738(_u数据,uuu llvm_prf_cnts)非外部(是一个私有的外部)u__u专业/用户/uasvcagent代理/Go管道/管道/UA应用核心发布iOS/UALAppCore/Classes/Classes/Core/Core/Core/Core/Core处理程序/主屏幕/UASUDOKUKUK。swift:$10 UALAPPCORE 14 UASUDOKUYULDSV24从模板33_4C5; ded22C8FD26C81E26FA4955E2A94All8获取请求,名称为21替换变量SO07NSFETCHF0CYSO0VF6结果_pGSgSS_SDySSypGtF
有趣的看起来没有任何Swift框架符号被剥离,这严重增加了我们的二进制大小。实际上,我们可以将联合航空的CI管道视为符号名称的一部分。🤣
正如我之前所说,这些符号实际上都不需要。让我们编写一个Bash脚本,通过strip运行框架:
#!/bin/bash函数strip_framework(){framework_NAME=$(basename";$1";)strip-rSTx-no_代码_签名_警告#34$1 " -o";StrippedFrameworks/$FRAMEWORK_NAME";}函数copy_framework(){framework_NAME=$(basename";$1";)cp--"$1 " "OriginalFrameworks/$FRAMEWORK#u NAME";}export-f strip_framework export-f copy_framework#我不能';我不知道如何';找到';只对二进制文件来说,只对二进制文件来说,[find###;34;34;34;perm+111-类型f-非-非-名称名称和(35)34;34;js#;34;34;34;34;34;34;34;3;34;34;34;34;perm+111-类型f-非-非-非-名称-名称-名称-名称和(不-名称)名称和34;34;34;34;3;3;3;3;4;4;4;4;3;3;3;3;4;4;svg和无-无-无-无-无-无-无-名称和34;34;svg和34;34;34;34;无-无-无-无-无-无-无-无-无-无-无-名名名;34;无-无-无-无-无-无-无-无-无-名名;34;34;无-无-#34;\-exec bash-c";strip#u framework\";{}\";copy#u framework\";{}\"" \;
➜ 联合分析du-s-h原创框架350M原创框架➜ 联合分析du-s-h带式框架163M带式框架
哇!老实说,我没想到会有这么大的进步。我们通过剥离框架符号,在五分钟内减少了187MB的应用程序大小。我打赌还有一些额外的低挂水果,但我在这里就到此为止。
虽然曼联开发团队早就应该注意到这一点了——我最初是在2021年8月开始编写水果挞的,但是生活发生了,公平地说,这个领域的应用程序开发是复杂的。
我最大的收获是,开发者工具在监控应用程序大小方面仍然非常差。应用商店应该向那些有如此简单的修复程序的开发者发出各种各样的危险信号。这就引出了一个问题,即苹果是否有动力改进该工具。我要大声疾呼,让工具公司成为我所知道的唯一一家试图解决这个问题的初创公司。
不管怎样,我希望你读得开心!我真的希望这个问题得到解决,并为人们在T台上节省真正的带宽和压力!