当前位置: 首页 > news >正文

长沙cms建站模板设计说明英文翻译

长沙cms建站模板,设计说明英文翻译,企业网站建设如何去规划,淘宝客手机网站搭建一、背景 冷启动时长是App性能的重要指标#xff0c;作为用户体验的第一道“门”#xff0c;直接决定着用户对App的第一印象。美团外卖iOS客户端从2013年11月开始#xff0c;历经几十个版本的迭代开发#xff0c;产品形态不断完善#xff0c;业务功能日趋复杂#xff1b;… 一、背景 冷启动时长是App性能的重要指标作为用户体验的第一道“门”直接决定着用户对App的第一印象。美团外卖iOS客户端从2013年11月开始历经几十个版本的迭代开发产品形态不断完善业务功能日趋复杂同时外卖App也已经由原来的独立业务App演进成为一个平台App陆续接入了闪购、跑腿等其他新业务。因此更多更复杂的工作需要在App冷启动的时候被完成这给App的冷启动性能带来了挑战。对此我们团队基于业务形态的变化和外卖App的特点对冷启动进行了持续且有针对性的优化工作目的就是为了呈现更加流畅的用户体验。 二、冷启动定义 一般而言大家把iOS冷启动的过程定义为从用户点击App图标开始到appDelegate didFinishLaunching方法执行完成为止。这个过程主要分为两个阶段 T1main()函数之前即操作系统加载App可执行文件到内存然后执行一系列的加载链接等工作最后执行至App的main()函数。T2main()函数之后即从main()开始到appDelegate的didFinishLaunchingWithOptions方法执行完毕。 然而当didFinishLaunchingWithOptions执行完成时用户还没有看到App的主界面也不能开始使用App。例如在外卖App中App还需要做一些初始化工作然后经历定位、首页请求、首页渲染等过程后用户才能真正看到数据内容并开始使用我们认为这个时候冷启动才算完成。我们把这个过程定义为T3。 综上外卖App把冷启动过程定义为从用户点击App图标开始到用户能看到App主界面内容为止这个过程即T1T2T3。在App冷启动过程当中这三个阶段中的每个阶段都存在很多可以被优化的点。 三、问题现状 性能存量问题 美团外卖iOS客户端经过几十个版本的迭代开发后在冷启动过程中已经积累了若干性能问题解决这些性能瓶颈是冷启动优化工作的首要目标这些问题主要包括 注启动项的定义在App启动过程中需要被完成的某项工作我们称之为一个启动项。例如某个SDK的初始化、某个功能的预加载等。 性能增量问题 一般情况下在App早期阶段冷启动不会有明显的性能问题。冷启动性能问题也不是在某个版本突然出现的而是随着版本迭代App功能越来越复杂启动任务越来越多冷启动时间也一点点延长。最后当我们注意到并想要优化它的时候这个问题已经变得很棘手了。外卖App的性能问题增量主要来自启动项的增加随着版本迭代启动项任务简单粗暴地堆积在启动流程中。如果每个版本冷启动时间增加0.1s那么几个版本下来冷启动时长就会明显增加很多。 四、治理思路 冷启动性能问题的治理目标主要有三个 解决存量问题优化当前性能瓶颈点优化启动流程缩短冷启动时间。管控增量问题冷启动流程规范化通过代码范式和文档指导后续冷启动过程代码的维护控制时间增量。完善监控完善冷启动性能指标监控收集更详细的数据及时发现性能问题。 五、规范启动流程 截止至2017年底美团外卖用户数已达2.5亿而美团外卖App也已完成了从支撑单一业务的App到支持多业务的平台型App的演进美团外卖iOS多端复用的推动、支撑与思考公司的一些新兴业务也陆续集成到外卖App当中。下面是外卖App的架构图外卖的架构主要分为三层底层是基础组件层中层是外卖平台层平台层向下管理基础组件向上为业务组件提供统一的适配接口上层是基础组件层包括外卖业务拆分的子业务组件外卖App和美团App中的外卖频道可以复用子业务组件和接入的其他非外卖业务。 App的平台化为业务方提供了高效、标准的统一平台但与此同时平台化和业务的快速迭代也给冷启动带来了问题 现有的启动项堆积严重拖慢启动速度。新的启动项缺乏添加范式杂乱无章修改风险大难以阅读和维护。面对这个问题我们首先梳理了目前启动流程中所有的启动项然后针对App平台化设计了新的启动项管理方式分阶段启动和启动项自注册。 分阶段启动 早期由于业务比较简单所有启动项都是不加以区分简单地堆积到didFinishLaunchingWithOptions方法中但随着业务的增加越来越多的启动项代码堆积在一起性能较差代码臃肿而混乱。 通过对SDK的梳理和分析我们发现启动项也需要根据所完成的任务被分类有些启动项是需要刚启动就执行的操作如Crash监控、统计上报等否则会导致信息收集的缺失有些启动项需要在较早的时间节点完成例如一些提供用户信息的SDK、定位功能的初始化、网络初始化等有些启动项则可以被延迟执行如一些自定义配置一些业务服务的调用、支付SDK、地图SDK等。我们所做的分阶段启动首先就是把启动流程合理地划分为若干个启动阶段然后依据每个启动项所做的事情的优先级把它们分配到相应的启动阶段优先级高的放在靠前的阶段优先级低的放在靠后的阶段。 下面是我们对美团外卖App启动阶段进行的重新定义对所有启动项进行的梳理和重新分类把它们对应到合理的启动阶段。这样做一方面可以推迟执行那些不必过早执行的启动项缩短启动时间另一方面把启动项进行归类方便后续的阅读和维护。然后把这些规则落地为启动项的维护文档指导后续启动项的新增和维护。 通过上面的工作我们梳理出了十几个可以推迟执行的启动项占所有启动项的30%左右有效地优化了启动项所占的这部分冷启动时间。 启动项自注册 确定了启动项分阶段启动的方案后我们面对的问题就是如何执行这些启动项。比较容易想到的方案是在启动时创建一个启动管理器然后读取所有启动项然后当时间节点到来时由启动器触发启动项执行。这种方式存在两个问题 所有启动项都要预先写到一个文件中在.m文件import或用.plist文件组织这种中心化的写法会导致臃肿的代码难以阅读维护。启动项代码无法复用启动项无法收敛到子业务库内部在外卖App和美团App中要重复实现和外卖App平台化的方向不符。 而我们希望的方式是启动项维护方式可插拔启动项之间、业务模块之间不耦合且一次实现可在两端复用。下图是我们采用的启动项管理方式我们称之为启动项的自注册一个启动项定义在子业务模块内部被封装成一个方法并且自声明启动阶段例如一个启动项A在独立App中可以声明为在willFinishLaunch阶段被执行在美团App中则声明在resignActive阶段被执行。这种方式下启动项即实现了两端复用不相关的启动项互相隔离添加/删除启动项都更加方便。 那么如何给一个启动项声明启动阶段又如何在正确的时机触发启动项的执行呢在代码上一个启动项最终都会对应到一个函数的执行所以在运行时只要能获取到函数的指针就可以触发启动项。美团平台开发的组件启动治理基建Kylin正是这样做的Kylin的核心思想就是在编译时把数据如函数指针写入到可执行文件的__DATA段中运行时再从__DATA段取出数据进行相应的操作调用函数。 为什么要用借用__DATA段呢原因就是为了能够覆盖所有的启动阶段例如main()之前的阶段。 Kylin实现原理简述Clang 提供了很多的编译器函数它们可以完成不同的功能。其中一种就是 section() 函数section()函数提供了二进制段的读写能力它可以将一些编译期就可以确定的常量写入数据段。 在具体的实现中主要分为编译期和运行时两个部分。在编译期编译器会将标记了 attribute((section())) 的数据写到指定的数据段中例如写一个{key(key代表不同的启动阶段), *pointer}对到数据段。到运行时在合适的时间节点在根据key读取出函数指针完成函数的调用。 上述方式可以封装成一个宏来达到代码的简化以调用宏 KLN_STRINGS_EXPORT(“Key”, “Value”)为例最终会被展开为 __attribute__((used, section(__DATA , __kylin__))) static const KLN_DATA __kylin__0 (KLN_DATA){(KLN_DATA_HEADER){Key, KLN_STRING, KLN_IS_ARRAY}, Value};使用示例编译器把启动项函数注册到启动阶段A KLN_FUNCTIONS_EXPORT(STAGE_KEY_A)() { // 在a.m文件中通过注册宏把启动项A声明为在STAGE_KEY_A阶段执行// 启动项代码A }KLN_FUNCTIONS_EXPORT(STAGE_KEY_A)() { // 在b.m文件中把启动项B声明为在STAGE_KEY_A阶段执行// 启动项代码B }在启动流程中在启动阶段STAGE_KEY_A触发所有注册到STAGE_KEY_A时间节点的启动项通过对这种方式几乎没有任何额外的辅助代码我们用一种很简洁的方式完成了启动项的自注册。 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {// 其他逻辑[[KLNKylin sharedInstance] executeArrayForKey:STAGE_KEY_A]; // 在此触发所有注册到STAGE_KEY_A时间节点的启动项// 其他逻辑return YES; }完成对现有的启动项的梳理和优化后我们也输出了后续启动项的添加维护规范规范后续启动项的分类原则优先级和启动阶段。目的是管控性能问题增量保证优化成果。 六、优化main()之前 在调用main()函数之前基本所有的工作都是由操作系统完成的开发者能够插手的地方不多所以如果想要优化这段时间就必须先了解一下操作系统在main()之前做了什么。main()之前操作系统所做的工作就是把可执行文件Mach-O格式加载到内存空间然后加载动态链接库dyld再执行一系列动态链接操作和初始化操作的过程加载、绑定、及初始化方法。这方面的资料网上比较多但重复性较高此处附上一篇WWDC的TopicOptimizing App Startup Time 。 加载过程—从exec()到main() 真正的加载过程从exec()函数开始exec()是一个系统调用。操作系统首先为进程分配一段内存空间然后执行如下操作 把App对应的可执行文件加载到内存。把Dyld加载到内存。Dyld进行动态链接。 下面我们简要分析一下Dyld在各阶段所做的事情 阶段工作加载动态库Dyld从主执行文件的header获取到需要加载的所依赖动态库列表然后它需要找到每个 dylib而应用所依赖的 dylib 文件可能会再依赖其他 dylib所以所需要加载的是动态库列表一个递归依赖的集合Rebase和Bind- Rebase在Image内部调整指针的指向。在过去会把动态库加载到指定地址所有指针和数据对于代码都是对的而现在地址空间布局是随机化所以需要在原来的地址根据随机的偏移量做一下修正- Bind是把指针正确地指向Image外部的内容。这些指向外部的指针被符号(symbol)名称绑定dyld需要去符号表里查找找到symbol对应的实现Objc setup- 注册Objc类 (class registration)- 把category的定义插入方法列表 (category registration)- 保证每一个selector唯一 (selector uniquing)Initializers- Objc的load()函数- C的构造函数属性函数- 非基本类型的C静态全局变量的创建(通常是类或结构体)最后 dyld 会调用 main() 函数main() 会调用 UIApplicationMain()before main()的过程也就此完成。 了解完main()之前的加载过程后我们可以分析出一些影响T1时间的因素 动态库加载越多启动越慢。ObjC类方法越多启动越慢。ObjC的load越多启动越慢。C的constructor函数越多启动越慢。C静态对象越多启动越慢。针对以上几点我们做了如下一些优化工作。 代码瘦身 随着业务的迭代不断有新的代码加入同时也会废弃掉无用的代码和资源文件但是工程中经常有无用的代码和文件被遗弃在角落里没有及时被清理掉。这些无用的部分一方面增大了App的包体积另一方便也拖慢了App的冷启动速度所以及时清理掉这些无用的代码和资源十分有必要。 通过对Mach-O文件的了解可以知道__TEXT:__objc_methname:中包含了代码中的所有方法而__DATA__objc_selrefs中则包含了所有被使用的方法的引用通过取两个集合的差集就可以得到所有未被使用的代码。核心方法如下具体可以参考objc_cover: def referenced_selectors(path):re_sel re.compile(__TEXT:__objc_methname:(.)) //获取所有方法refs set()lines os.popen(/usr/bin/otool -v -s __DATA __objc_selrefs %s % path).readlines() ## ios mac //真正被使用的方法for line in lines:results re_sel.findall(line)if results:refs.add(results[0])return refs }通过这种方法我们排查了十几个无用类和250无用的方法。 load优化 目前iOS App中或多或少的都会写一些load方法用于在App启动执行一些操作load方法在Initializers阶段被执行但过多load方法则会拖慢启动速度对于大中型的App更是如此。通过对App中load的方法分析发现很多代码虽然需要在App启动时较早的时机进行初始化但并不需要在load这样非常靠前的位置完全是可以延迟到App冷启动后的某个时间节点例如一些路由操作。其实load也可以被当做一种启动项来处理所以在替换load方法的具体实现上我们仍然采用了上面的Kylin方式。 使用示例 // 用WMAPP_BUSINESS_INIT_AFTER_HOMELOADING声明替换load声明即可不需其他改动 WMAPP_BUSINESS_INIT_AFTER_HOMELOADING() { // 原load方法中的代码 }// 在某个合适的时机触发注册到该阶段的所有方法如冷启动结束后 [[KLNKylin sharedInstance] executeArrayForKey:kWMAPP_BUSINESS_INITIALIZATION_AFTER_HOMELOADING_KEY] }七、优化耗时操作 在main()之后主要工作是各种启动项的执行上面已经叙述主界面的构建例如TabBarVCHomeVC等等。资源的加载如图片I/O、图片解码、archive文档等。这些操作中可能会隐含着一些耗时操作靠单纯阅读非常难以发现如何发现这些耗时点呢找到合适的工具就会事半功倍。 Time Profiler Time Profiler是Xcode自带的时间性能分析工具它按照固定的时间间隔来跟踪每一个线程的堆栈信息通过统计比较时间间隔之间的堆栈状态来推算某个方法执行了多久并获得一个近似值。Time Profiler的使用方法网上有很多使用教程这里我们也不过多介绍附上一篇使用文档Instruments Tutorial with Swift: Getting Started。 火焰图 除了Time Profiler火焰图也是一个分析CPU耗时的利器相比于Time Profiler火焰图更加清晰。火焰图分析的产物是一张调用栈耗时图片之所以称为火焰图是因为整个图形看起来就像一团跳动的火焰火焰尖部是调用栈的栈顶底部是栈底纵向表示调用栈的深度横向表示消耗的时间。一个格子的宽度越大越说明其可能是瓶颈。分析火焰图主要就是看那些比较宽大的火苗特别留意那些类似“平顶山”的火苗。下面是美团平台开发的性能分析工具-Caesium的分析效果图 通过对火焰图的分析我们发现了冷启动过程中存在着不少问题并成功优化了0.3S的时间。优化内容总结如下 优化点举例发现隐晦的耗时操作发现在冷启动过程中archive了一张图片非常耗时推迟减少I/O操作减少动画图片组的数量替换大图资源等。因为相比于内存操作硬盘I/O是非常耗时的操作推迟执行的一些任务如一些资源的I/O一些布局逻辑对象的创建时机等八、优化串行操作 在冷启动过程中有很多操作是串行执行的若干个任务串行执行时间必然比较长。如果能变串行为并行那么冷启动时间就能够大大缩短。 闪屏页的使用 现在许多App在启动时并不直接进入首页而是会向用户展示一个持续一小段时间的闪屏页如果使用恰当这个闪屏页就能帮我们节省一些启动时间。因为当一个App比较复杂的时候启动时首次构建App的UI就是一个比较耗时的过程假定这个时间是0.2秒如果我们是先构建首页UI然后再在Window上加上这个闪屏页那么冷启动时App就会实实在在地卡住0.2秒但是如果我们是先把闪屏页作为App的RootViewController那么这个构建过程就会很快。因为闪屏页只有一个简单的ImageView而这个ImageView则会向用户展示一小段时间这时我们就可以利用这一段时间来构建首页UI了一举两得。 缓存定位首页预请求 美团外卖App冷启动过程中一个重要的串行流程就是首页定位–首页请求–首页渲染过程这三个操作占了整个首页加载时间的77%左右所以想要缩短冷启动时间就一定要从这三点出发进行优化。 之前串行操作流程如下 优化后的设计在发起定位的同时使用客户端缓存定位进行首页数据的预请求使定位和请求并行进行。然后当用户真实定位成功后判断真实定位是否命中缓存定位如果命中则刚才的预请求数据有效这样可以节省大概40%的时间首页加载时间效果非常明显如果未命中则弃用预请求数据重新请求。 九、数据监控 Time Profiler和Caesium火焰图都只能在线下分析App在单台设备中的耗时操作局限性比较大无法在线上监控App在用户设备上的表现。外卖App使用公司内部自研的Metrics性能监控系统长期监控App的性能指标帮助我们掌握App在线上各种环境下的真实表现并为技术优化项目提供可靠的数据支持。Metrics监控的核心指标之一就是冷启动时间。 冷启动开始结束时间节点 结束时间点结束时间比较好确定我们可以将首页某些视图元素的展示作为首页加载完成的标志。开始时间点一般情况下我们都是在main()之后才开始接管App但以main()函数作为冷启动起始点显然不合适因为这样无法统计到T1时间段。那么起始时间如何确定呢目前业界常见的有两种方法一是以可执行文件中任意一个类的load方法的执行时间作为起始点二是分析dylib的依赖关系找到叶子节点的dylib然后以其中某个类的load方法的执行时间作为起始点。根据Dyld对dylib的加载顺序后者的时机更早。但是这两种方法获取的起始点都只在Initializers阶段而Initializers之前的时长都没有被计入。Metrics则另辟蹊径以App的进程创建时间即exec函数执行时间作为冷启动的起始时间。因为系统允许我们通过sysctl函数获得进程的有关信息其中就包括进程创建的时间戳。#import sys/sysctl.h #import mach/mach.h (BOOL)processInfoForPID:(int)pid procInfo:(struct kinfo_proc*)procInfo {int cmd[4] {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};size_t size sizeof(*procInfo);return sysctl(cmd, sizeof(cmd)/sizeof(*cmd), procInfo, size, NULL, 0) 0; } (NSTimeInterval)processStartTime {struct kinfo_proc kProcInfo;if ([self processInfoForPID:[[NSProcessInfo processInfo] processIdentifier] procInfo:kProcInfo]) {return kProcInfo.kp_proc.p_un.__p_starttime.tv_sec * 1000.0 kProcInfo.kp_proc.p_un.__p_starttime.tv_usec / 1000.0;} else {NSAssert(NO, 无法取得进程的信息);return 0;} }进程创建的时机非常早。经过实验在一个新建的空白App中进程创建时间比叶子节点dylib中的load方法执行时间早12ms比main函数的执行时间早13ms实验设备iPhone 7 Plus iOS 12.0、Xcode 10.0、Release 模式。外卖App线上的数据则更加明显同样的机型iPhone 7 Plus和系统版本iOS 12.0进程创建时间比叶子节点dylib中的load方法执行时间早688ms。而在全部机型和系统版本中这一数据则是878ms。 冷启动过程时间节点 我们也在App冷启动过程中的所有关键节点打上一连串测速点Metrics会记录下测速点的名称及其距离进程创建时间的时长。我们没有采用自动打点的方式是因为外卖App的冷启动过程十分复杂而自动打点无法做到如此细致并不实用。另外Metrics记录的是时间轴上以进程创建时间为原点的一组顺序的时间点而不是一组时间段是因为顺序的时间点可以计算任意两个时间点之间的距离即可以将时间点处理成时间段。但是一组时间段可能无法还原为顺序的时间点因为时间段之间可能并不是首尾相接的特别是对于异步执行或者多线程的情况。 在测速完毕后Metrics会统一将所有测速点上报到后台。下图是美团外卖App 6.10版本的部分过程节点监控数据截图 Metrics还会由后台对数据做聚合计算得到冷启动总时长和各个测速点时长的50分位数、90分位数和95分位数的统计数据这样我们就能从宏观上对冷启动时长分布情况有所了解。下图中横轴为时长纵轴为上报的样本数。 十、总结 对于快速迭代的App随着业务复杂度的增加冷启动时长会不可避免的增加。冷启动流程也是一个比较复杂的过程当遇到冷启动性能瓶颈时我们可以根据App自身的特点配合工具的使用从多方面、多角度进行优化。同时优化冷启动存量问题只是冷启动治理的第一步因为冷启动性能问题并不是一日造成的也不能简单的通过一次优化工作就能解决我们需要通过合理的设计、规范的约束来有效地管控性能问题的增量并通过持续的线上监控来及时发现并修正性能问题这样才能够长期保证良好的App冷启动体验。 作者简介 郭赛美团点评资深工程师。2015年加入美团目前作为外卖iOS团队主力开发负责移动端业务开发业务类基础设施的建设与维护。徐宏美团点评资深工程师。2016年加入美团目前作为外卖iOS团队主力开发负责移动端APM性能监控高可用基础设施支撑相关推进工作。招聘 美团外卖长期招聘Android、iOS、FE高级/资深工程师和技术专家Base北京、上海、成都欢迎有兴趣的同学投递简历到chenhang03meituan.com。
http://www.zqtcl.cn/news/783942/

相关文章:

  • 网站编辑信息怎么做茶叶网站建设策划书ppt
  • 网站建设费摊销几年嵌入式软件开发用什么语言
  • 网站备案 后期商业设计网站
  • 网站负责人半身照国际公司和跨国公司
  • 网站的组成友情下载网站
  • 做视频课程网站中职网站建设
  • seo整站优化服务盗图来做网站
  • 网站服务器基本要素有哪些交易网站的建设规划
  • 网站开发源代码mvc山东网站推广
  • 深圳建网站兴田德润团队织梦的网站模板免费吗
  • 手机响应式网站怎么做图书馆建设网站注意点
  • 白云做网站要多少钱wordpress指定分类子类
  • 侧导航网站济南网上房地产
  • 做得比较好的公司网站自己可以学做网站吗
  • 陕西省两学一做网站产品推广方案
  • 做网站ps文字有锯齿网站建设项目管理基本要求
  • 大连网站制作的网络科技公司取名创意
  • 哈尔滨企业网站建站推荐专业微网站营销
  • 阿里云模板建站怎么样上海免费建站模板
  • 中企动力网站建设合同织梦商业网站内容管理系统
  • 厦门石材网站建设个人网页模板制作
  • 网站建设责任分工手机兼职群
  • 做网站维护的收入怎么确认网校网站毕业设计的方案
  • 商丘网站建设想象力网络普洱做网站的报价
  • wordpress前端是什么网站建设备案优化
  • 琼海市建设局网站网络宣传网站建设制作
  • 怎样做返利网站apple私人免费网站怎么下载
  • 靖宇东兴自助建站深圳网站建设 排行榜
  • 怎样编辑网站梅州免费建站
  • 桂林北站怎么去阳朔简易网页